Commit 67a4cce4a89718d252b61aaf58882c69c0e2f6e3

Authored by John W. Linville
1 parent 52f095ee88

[PATCH] mac80211: make ieee802_11_parse_elems return void

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: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 1 changed file with 9 additions and 46 deletions Side-by-side Diff

net/mac80211/ieee80211_sta.c
... ... @@ -108,14 +108,11 @@
108 108 u8 wmm_param_len;
109 109 };
110 110  
111   -enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 };
112   -
113   -static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
114   - struct ieee802_11_elems *elems)
  111 +static void ieee802_11_parse_elems(u8 *start, size_t len,
  112 + struct ieee802_11_elems *elems)
115 113 {
116 114 size_t left = len;
117 115 u8 *pos = start;
118   - int unknown = 0;
119 116  
120 117 memset(elems, 0, sizeof(*elems));
121 118  
... ... @@ -126,15 +123,8 @@
126 123 elen = *pos++;
127 124 left -= 2;
128 125  
129   - if (elen > left) {
130   -#if 0
131   - if (net_ratelimit())
132   - printk(KERN_DEBUG "IEEE 802.11 element parse "
133   - "failed (id=%d elen=%d left=%d)\n",
134   - id, elen, left);
135   -#endif
136   - return ParseFailed;
137   - }
  126 + if (elen > left)
  127 + return;
138 128  
139 129 switch (id) {
140 130 case WLAN_EID_SSID:
141 131  
142 132  
... ... @@ -201,28 +191,15 @@
201 191 elems->ext_supp_rates_len = elen;
202 192 break;
203 193 default:
204   -#if 0
205   - printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
206   - "unknown element (id=%d elen=%d)\n",
207   - id, elen);
208   -#endif
209   - unknown++;
210 194 break;
211 195 }
212 196  
213 197 left -= elen;
214 198 pos += elen;
215 199 }
216   -
217   - /* Do not trigger error if left == 1 as Apple Airport base stations
218   - * send AssocResps that are one spurious byte too long. */
219   -
220   - return unknown ? ParseUnknown : ParseOK;
221 200 }
222 201  
223 202  
224   -
225   -
226 203 static int ecw2cw(int ecw)
227 204 {
228 205 int cw = 1;
... ... @@ -931,12 +908,7 @@
931 908  
932 909 printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
933 910 pos = mgmt->u.auth.variable;
934   - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
935   - == ParseFailed) {
936   - printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
937   - dev->name);
938   - return;
939   - }
  911 + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
940 912 if (!elems.challenge) {
941 913 printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
942 914 "frame\n", dev->name);
... ... @@ -1230,12 +1202,7 @@
1230 1202 aid &= ~(BIT(15) | BIT(14));
1231 1203  
1232 1204 pos = mgmt->u.assoc_resp.variable;
1233   - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
1234   - == ParseFailed) {
1235   - printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
1236   - dev->name);
1237   - return;
1238   - }
  1205 + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1239 1206  
1240 1207 if (!elems.supp_rates) {
1241 1208 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
... ... @@ -1459,7 +1426,7 @@
1459 1426 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1460 1427 struct ieee802_11_elems elems;
1461 1428 size_t baselen;
1462   - int channel, invalid = 0, clen;
  1429 + int channel, clen;
1463 1430 struct ieee80211_sta_bss *bss;
1464 1431 struct sta_info *sta;
1465 1432 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
... ... @@ -1505,9 +1472,7 @@
1505 1472 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
1506 1473 }
1507 1474  
1508   - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
1509   - &elems) == ParseFailed)
1510   - invalid = 1;
  1475 + ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
1511 1476  
1512 1477 if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
1513 1478 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
... ... @@ -1724,9 +1689,7 @@
1724 1689 if (baselen > len)
1725 1690 return;
1726 1691  
1727   - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
1728   - &elems) == ParseFailed)
1729   - return;
  1692 + ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
1730 1693  
1731 1694 if (elems.erp_info && elems.erp_info_len >= 1)
1732 1695 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);