--- madwifi-orig/net80211/ieee80211_output.c 2005-02-16 17:35:08.000000000 -0800 +++ madwifi-orig/net80211/ieee80211_output.c 2005-11-09 20:30:34.000000000 -0800 @@ -200,32 +200,37 @@ return skb; } +#define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none) /* - * Return the transmit key to use in sending a frame to - * the specified destination. Multicast traffic always - * uses the group key. Otherwise if a unicast key is - * set we use that. When no unicast key is set we fall - * back to the default transmit key. - */ + * Return the transmit key to use in sending a unicast frame. + * If a unicast key is set we use that. When no unicast key is set + * we fall back to the default transmit key. + */ static inline struct ieee80211_key * -ieee80211_crypto_getkey(struct ieee80211com *ic, - const u_int8_t mac[IEEE80211_ADDR_LEN], struct ieee80211_node *ni) +ieee80211_crypto_getucastkey(struct ieee80211com *ic, struct ieee80211_node *ni) { -#define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none) - if (IEEE80211_IS_MULTICAST(mac) || KEY_UNDEFINED(ni->ni_ucastkey)) { - if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || - KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) { - IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT, - ("%s: no transmit key, def_txkey %u\n", - __func__, ic->ic_def_txkey)); - /* XXX statistic */ - return NULL; - } - return &ic->ic_nw_keys[ic->ic_def_txkey]; - } else { - return &ni->ni_ucastkey; - } -#undef KEY_UNDEFINED + if (KEY_UNDEFINED(ni->ni_ucastkey)) { + if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || + KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) + return NULL; + return &ic->ic_nw_keys[ic->ic_def_txkey]; + } else { + return &ni->ni_ucastkey; + } +} + +/* + * Return the transmit key to use in sending a multicast frame. + * Multicast traffic always uses the group key which is installed as + * the default tx key. + */ +static inline struct ieee80211_key * +ieee80211_crypto_getmcastkey(struct ieee80211com *ic, struct ieee80211_node *ni) +{ + if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || + KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) + return NULL; + return &ic->ic_nw_keys[ic->ic_def_txkey]; } /* @@ -274,21 +279,33 @@ } } - /* - * Insure space for additional headers. First - * identify transmit key to use in calculating any - * buffer adjustments required. This is also used - * below to do privacy encapsulation work. - * - * Note key may be NULL if we fall back to the default - * transmit key and that is not set. In that case the - * buffer may not be expanded as needed by the cipher - * routines, but they will/should discard it. - */ - if (ic->ic_flags & IEEE80211_F_PRIVACY) - key = ieee80211_crypto_getkey(ic, eh.ether_dhost, ni); - else - key = NULL; + /* + * Insure space for additional headers. First identify + * transmit key to use in calculating any buffer adjustments + * required. This is also used below to do privacy + * encapsulation work. Then calculate the 802.11 header + * size and any padding required by the driver. + * + * Note key may be NULL if we fall back to the default + * transmit key and that is not set. In that case the + * buffer may not be expanded as needed by the cipher + * routines, but they will/should discard it. + */ + if (ic->ic_flags & IEEE80211_F_PRIVACY) { + if (ic->ic_opmode == IEEE80211_M_STA || + !IEEE80211_IS_MULTICAST(eh.ether_dhost)) + key = ieee80211_crypto_getucastkey(ic, ni); + else + key = ieee80211_crypto_getmcastkey(ic, ni); + if (key == NULL && eh.ether_type != htons(ETHERTYPE_PAE)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, + ("[%s] no default transmit key (%s) deftxkey %u\n", + __func__, + ether_sprintf(eh.ether_dhost), ic->ic_def_txkey)); + ic->ic_stats.is_tx_nodefkey++; + } + } else + key = NULL; skb = ieee80211_skbhdr_adjust(ic, key, skb); if (skb == NULL) { /* NB: ieee80211_skbhdr_adjust handles msgs+statistics */ @@ -333,24 +350,25 @@ case IEEE80211_M_MONITOR: goto bad; } - if (eh.ether_type != __constant_htons(ETHERTYPE_PAE) || - (key != NULL && (ic->ic_flags & IEEE80211_F_WPA))) { - /* - * IEEE 802.1X: send EAPOL frames always in the clear. - * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set. - */ - if (key != NULL) { - wh->i_fc[1] |= IEEE80211_FC1_WEP; - /* XXX do fragmentation */ - if (!ieee80211_crypto_enmic(ic, key, skb)) { - IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, - ("[%s] enmic failed, discard frame\n", - ether_sprintf(eh.ether_dhost))); - /* XXX statistic */ - goto bad; - } - } - } + if (key != NULL) { + /* + * IEEE 802.1X: send EAPOL frames always in the clear. + * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set. + */ + if (eh.ether_type != __constant_htons(ETHERTYPE_PAE) || + ((ic->ic_flags & IEEE80211_F_WPA) && + !KEY_UNDEFINED(ni->ni_ucastkey))) { + wh->i_fc[1] |= IEEE80211_FC1_WEP; + /* XXX do fragmentation */ + if (!ieee80211_crypto_enmic(ic, key, skb)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, + ("[%s] enmic failed, discard frame\n", + ether_sprintf(eh.ether_dhost))); + /* XXX statistic */ + goto bad; + } + } + } if (eh.ether_type != __constant_htons(ETHERTYPE_PAE)) { /* * Reset the inactivity timer only for non-PAE traffic