Modify ieee80211_saveie and ieee80211_saveath(ewww) to take a NULL source parameter...
authormentor <mentor@0192ed92-7a03-0410-a25b-9323aeb14dbd>
Tue, 13 Nov 2007 17:45:58 +0000 (17:45 +0000)
committermentor <mentor@0192ed92-7a03-0410-a25b-9323aeb14dbd>
Tue, 13 Nov 2007 17:45:58 +0000 (17:45 +0000)
On reception of an Associatiion request, always save IEs correctly (i.e., cleanup up any no longer valid IEs in the case that no new, valid IE is received).

Ticket: http://madwifi.org/ticket/1188
Original Patch: Signed-Off-By: Bas

git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@2847 0192ed92-7a03-0410-a25b-9323aeb14dbd

net80211/ieee80211_input.c

index 6364e4c3e405f1b346049201cf0568fc478bb5d6..575e9490d3288f44f78c4a35a6d3888e714072f8 100644 (file)
@@ -2059,19 +2059,19 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, u_int8_t *frm,
        return 0;
 }
 
+/* Record information element for later use. */
 void
 ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
 {
        u_int ielen = ie[1] + 2;
-       /*
-        * Record information element for later use.
-        */
-       if (*iep == NULL || (*iep)[1] != ie[1]) {
+       if ((*iep == NULL) || (ie == NULL) || ((*iep)[1] != ie[1])) {
                if (*iep != NULL)
                        FREE(*iep, M_DEVBUF);
-               MALLOC(*iep, void*, ielen, M_DEVBUF, M_NOWAIT);
+               *iep = NULL;
+               if (ie != NULL)
+                       MALLOC(*iep, void*, ielen, M_DEVBUF, M_NOWAIT);
        }
-       if (*iep != NULL)
+       if ((*iep != NULL) && (ie != NULL))
                memcpy(*iep, ie, ielen);
 }
 EXPORT_SYMBOL(ieee80211_saveie);
@@ -2248,10 +2248,15 @@ ieee80211_saveath(struct ieee80211_node *ni, u_int8_t *ie)
        const struct ieee80211_ie_athAdvCap *athIe =
                (const struct ieee80211_ie_athAdvCap *) ie;
 
-       ni->ni_ath_flags = athIe->athAdvCap_capability;
-       if (ni->ni_ath_flags & IEEE80211_ATHC_COMP)
-               ni->ni_ath_defkeyindex = LE_READ_2(&athIe->athAdvCap_defKeyIndex);
        ieee80211_saveie(&ni->ni_ath_ie, ie);
+       if (athIe != NULL) {
+               ni->ni_ath_flags = athIe->athAdvCap_capability;
+               if (ni->ni_ath_flags & IEEE80211_ATHC_COMP)
+                       ni->ni_ath_defkeyindex = LE_READ_2(&athIe->athAdvCap_defKeyIndex);
+       } else {
+               ni->ni_ath_flags = 0;
+               ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY;
+       }
 }
 
 struct ieee80211_channel *
@@ -3188,10 +3193,8 @@ ieee80211_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
                                                ether_sprintf(wh->i_addr2));
                                break;
                        case IEEE80211_ELEMID_VENDOR:
-                               /* don't override RSN element
-                                * XXX: actually the driver should report both WPA versions,
-                                * so wpa_supplicant can choose and also detect downgrade attacks
-                               */
+                               /* NB: Provide all IEs for wpa_supplicant, so
+                                * it can handle downgrade attacks, etc. */
                                if (iswpaoui(frm) && !wpa) {
                                        if (vap->iv_flags & IEEE80211_F_WPA1)
                                                wpa = frm;
@@ -3210,6 +3213,7 @@ ieee80211_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
                }
                if (frm > efrm)
                        return;
+
                IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
                IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
                IEEE80211_VERIFY_SSID(vap->iv_bss, ssid);
@@ -3242,13 +3246,9 @@ ieee80211_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
                }
 
                if (rsn != NULL) {
-                       /*
-                        * Parse WPA information element.  Note that
-                        * we initialize the param block from the node
-                        * state so that information in the IE overrides
-                        * our defaults.  The resulting parameters are
-                        * installed below after the association is assured.
-                        */
+                       /* Initialise values to node defaults, which are then 
+                        * overwritten by values in the IE. These are 
+                        * installed once association is complete. */
                        rsn_parm = ni->ni_rsn;
                        if (rsn[0] != IEEE80211_ELEMID_RSN)
                                reason = ieee80211_parse_wpa(vap, rsn, &rsn_parm, wh);
@@ -3276,7 +3276,7 @@ ieee80211_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
                        FREE(ni->ni_challenge, M_DEVBUF);
                        ni->ni_challenge = NULL;
                }
-               /* 802.11 spec says to ignore station's privacy bit */
+               /* 802.11 spec. says to ignore station's privacy bit */
                if ((capinfo & IEEE80211_CAPINFO_ESS) == 0) {
                        IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, wh->i_addr2,
                                "deny %s request, capability mismatch 0x%x",
@@ -3332,62 +3332,19 @@ ieee80211_recv_mgmt(struct ieee80211_node *ni, struct sk_buff *skb,
                ni->ni_chan = ic->ic_curchan;
                ni->ni_fhdwell = vap->iv_bss->ni_fhdwell;
                ni->ni_fhindex = vap->iv_bss->ni_fhindex;
-               if (wpa != NULL) {
-                       /*
-                        * Record WPA/RSN parameters for station, mark
-                        * node as using WPA and record information element
-                        * for applications that require it.
-                        */
-                       ieee80211_saveie(&ni->ni_wpa_ie, wpa);
-               } else if (ni->ni_wpa_ie != NULL) {
-                       /*
-                        * Flush any state from a previous association.
-                        */
-                       FREE(ni->ni_wpa_ie, M_DEVBUF);
-                       ni->ni_wpa_ie = NULL;
-               }
-               if (rsn != NULL) {
-                       /*
-                        * Record WPA/RSN parameters for station, mark
-                        * node as using WPA and record information element
-                        * for applications that require it.
-                        */
-                       ni->ni_rsn = rsn_parm;
-                       ieee80211_saveie(&ni->ni_rsn_ie, rsn);
-               } else if (ni->ni_rsn_ie != NULL) {
-                       /*
-                        * Flush any state from a previous association.
-                        */
-                       FREE(ni->ni_rsn_ie, M_DEVBUF);
-                       ni->ni_rsn_ie = NULL;
-               }
-               if (wme != NULL) {
-                       /*
-                        * Record WME parameters for station, mark node
-                        * as capable of QoS and record information
-                        * element for applications that require it.
-                        */
-                       ieee80211_saveie(&ni->ni_wme_ie, wme);
-                       if (ieee80211_parse_wmeie(wme, wh, ni) > 0)
+
+               /* WPA */
+               ieee80211_saveie(&ni->ni_wpa_ie, wpa);
+               /* RSN */
+               ni->ni_rsn = rsn_parm;
+               ieee80211_saveie(&ni->ni_rsn_ie, rsn);
+               /* WME - including QoS flag */
+               ieee80211_saveie(&ni->ni_wme_ie, wme);
+               ni->ni_flags &= ~IEEE80211_NODE_QOS;
+               if ((wme != NULL) && (ieee80211_parse_wmeie(wme, wh, ni) > 0))
                                ni->ni_flags |= IEEE80211_NODE_QOS;
-               } else if (ni->ni_wme_ie != NULL) {
-                       /*
-                        * Flush any state from a previous association.
-                        */
-                       FREE(ni->ni_wme_ie, M_DEVBUF);
-                       ni->ni_wme_ie = NULL;
-                       ni->ni_flags &= ~IEEE80211_NODE_QOS;
-               }
-               if (ath != NULL)
-                       ieee80211_saveath(ni, ath);
-               else if (ni->ni_ath_ie != NULL) {
-                       /*
-                        * Flush any state from a previous association.
-                        */
-                       FREE(ni->ni_ath_ie, M_DEVBUF);
-                       ni->ni_ath_ie = NULL;
-                       ni->ni_ath_flags = 0;
-               }
+
+               ieee80211_saveath(ni, ath);
 
                /* Send TGf L2UF frame on behalf of newly associated station */
                ieee80211_deliver_l2uf(ni);