Commit ef081163 authored by John W. Linville's avatar John W. Linville Committed by Greg Kroah-Hartman

mac80211: make ieee802_11_parse_elems return void

patch 67a4cce4 in mainline.

Some APs send management frames with junk padding after the last IE.
We already account for a similar problem with some Apple Airport
devices, but at least one device is known to send more than a single
extra byte.  The device in question is the Draytek Vigor2900:

	http://www.draytek.com.au/products/Vigor2900.php

The junk in question looks like an IE that runs off the end of the
frame.  This cause us to return ParseFailed.  Since the frame in
question is an association response, this causes us to fail to associate
with this AP.

The return code from ieee802_11_parse_elems is superfluous.
All callers still check for the presence of the specific IEs that
interest them anyway.  So, remove the return code so the parse never
"fails".
Acked-by: default avatarMichael Wu <flamingice@sourmilk.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f08fdbd7
...@@ -108,15 +108,11 @@ struct ieee802_11_elems { ...@@ -108,15 +108,11 @@ struct ieee802_11_elems {
u8 wmm_param_len; u8 wmm_param_len;
}; };
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; static void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
{ {
size_t left = len; size_t left = len;
u8 *pos = start; u8 *pos = start;
int unknown = 0;
memset(elems, 0, sizeof(*elems)); memset(elems, 0, sizeof(*elems));
...@@ -127,15 +123,8 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, ...@@ -127,15 +123,8 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elen = *pos++; elen = *pos++;
left -= 2; left -= 2;
if (elen > left) { if (elen > left)
#if 0 return;
if (net_ratelimit())
printk(KERN_DEBUG "IEEE 802.11 element parse "
"failed (id=%d elen=%d left=%d)\n",
id, elen, left);
#endif
return ParseFailed;
}
switch (id) { switch (id) {
case WLAN_EID_SSID: case WLAN_EID_SSID:
...@@ -202,28 +191,15 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, ...@@ -202,28 +191,15 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elems->ext_supp_rates_len = elen; elems->ext_supp_rates_len = elen;
break; break;
default: default:
#if 0
printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
"unknown element (id=%d elen=%d)\n",
id, elen);
#endif
unknown++;
break; break;
} }
left -= elen; left -= elen;
pos += elen; pos += elen;
} }
/* Do not trigger error if left == 1 as Apple Airport base stations
* send AssocResps that are one spurious byte too long. */
return unknown ? ParseUnknown : ParseOK;
} }
static int ecw2cw(int ecw) static int ecw2cw(int ecw)
{ {
int cw = 1; int cw = 1;
...@@ -907,12 +883,7 @@ static void ieee80211_auth_challenge(struct net_device *dev, ...@@ -907,12 +883,7 @@ static void ieee80211_auth_challenge(struct net_device *dev,
printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
pos = mgmt->u.auth.variable; pos = mgmt->u.auth.variable;
if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
== ParseFailed) {
printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
dev->name);
return;
}
if (!elems.challenge) { if (!elems.challenge) {
printk(KERN_DEBUG "%s: no challenge IE in shared key auth " printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
"frame\n", dev->name); "frame\n", dev->name);
...@@ -1200,12 +1171,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, ...@@ -1200,12 +1171,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
aid &= ~(BIT(15) | BIT(14)); aid &= ~(BIT(15) | BIT(14));
pos = mgmt->u.assoc_resp.variable; pos = mgmt->u.assoc_resp.variable;
if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
== ParseFailed) {
printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
dev->name);
return;
}
if (!elems.supp_rates) { if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
...@@ -1434,7 +1400,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, ...@@ -1434,7 +1400,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
size_t baselen; size_t baselen;
int channel, invalid = 0, clen; int channel, clen;
struct ieee80211_sta_bss *bss; struct ieee80211_sta_bss *bss;
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
...@@ -1478,9 +1444,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, ...@@ -1478,9 +1444,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
#endif /* CONFIG_MAC80211_IBSS_DEBUG */ #endif /* CONFIG_MAC80211_IBSS_DEBUG */
} }
if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
&elems) == ParseFailed)
invalid = 1;
if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
...@@ -1699,9 +1663,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, ...@@ -1699,9 +1663,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
if (baselen > len) if (baselen > len)
return; return;
if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
&elems) == ParseFailed)
return;
if (elems.erp_info && elems.erp_info_len >= 1) if (elems.erp_info && elems.erp_info_len >= 1)
ieee80211_handle_erp_ie(dev, elems.erp_info[0]); ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment