Modify ieee80211_saveie and ieee80211_saveath(ewww) to take a NULL source parameter, and to cleanup in this case.

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
This commit is contained in:
mentor 2007-11-13 17:45:58 +00:00
parent 73cbb16ebe
commit 3fbb1d543d

View File

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