aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2007-10-12 16:40:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2007-10-18 14:36:18 -0400
commit67a4cce4a89718d252b61aaf58882c69c0e2f6e3 (patch)
treec42df7a57412d20b62f6f1bbf9e509958c2d9079
parent52f095ee88d8851866bc7694ab991ca5abf21d5e (diff)
[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>
-rw-r--r--net/mac80211/ieee80211_sta.c55
1 files changed, 9 insertions, 46 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index db81aef6177a..f7ffeec3913f 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -108,14 +108,11 @@ struct ieee802_11_elems {
108 u8 wmm_param_len; 108 u8 wmm_param_len;
109}; 109};
110 110
111enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 }; 111static void ieee802_11_parse_elems(u8 *start, size_t len,
112 112 struct ieee802_11_elems *elems)
113static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
114 struct ieee802_11_elems *elems)
115{ 113{
116 size_t left = len; 114 size_t left = len;
117 u8 *pos = start; 115 u8 *pos = start;
118 int unknown = 0;
119 116
120 memset(elems, 0, sizeof(*elems)); 117 memset(elems, 0, sizeof(*elems));
121 118
@@ -126,15 +123,8 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
126 elen = *pos++; 123 elen = *pos++;
127 left -= 2; 124 left -= 2;
128 125
129 if (elen > left) { 126 if (elen > left)
130#if 0 127 return;
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 }
138 128
139 switch (id) { 129 switch (id) {
140 case WLAN_EID_SSID: 130 case WLAN_EID_SSID:
@@ -201,28 +191,15 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
201 elems->ext_supp_rates_len = elen; 191 elems->ext_supp_rates_len = elen;
202 break; 192 break;
203 default: 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 break; 194 break;
211 } 195 }
212 196
213 left -= elen; 197 left -= elen;
214 pos += elen; 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
226static int ecw2cw(int ecw) 203static int ecw2cw(int ecw)
227{ 204{
228 int cw = 1; 205 int cw = 1;
@@ -931,12 +908,7 @@ static void ieee80211_auth_challenge(struct net_device *dev,
931 908
932 printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); 909 printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
933 pos = mgmt->u.auth.variable; 910 pos = mgmt->u.auth.variable;
934 if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) 911 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 }
940 if (!elems.challenge) { 912 if (!elems.challenge) {
941 printk(KERN_DEBUG "%s: no challenge IE in shared key auth " 913 printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
942 "frame\n", dev->name); 914 "frame\n", dev->name);
@@ -1230,12 +1202,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1230 aid &= ~(BIT(15) | BIT(14)); 1202 aid &= ~(BIT(15) | BIT(14));
1231 1203
1232 pos = mgmt->u.assoc_resp.variable; 1204 pos = mgmt->u.assoc_resp.variable;
1233 if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) 1205 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 }
1239 1206
1240 if (!elems.supp_rates) { 1207 if (!elems.supp_rates) {
1241 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", 1208 printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
@@ -1459,7 +1426,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1459 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1426 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1460 struct ieee802_11_elems elems; 1427 struct ieee802_11_elems elems;
1461 size_t baselen; 1428 size_t baselen;
1462 int channel, invalid = 0, clen; 1429 int channel, clen;
1463 struct ieee80211_sta_bss *bss; 1430 struct ieee80211_sta_bss *bss;
1464 struct sta_info *sta; 1431 struct sta_info *sta;
1465 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1432 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1505,9 +1472,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1505#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 1472#endif /* CONFIG_MAC80211_IBSS_DEBUG */
1506 } 1473 }
1507 1474
1508 if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, 1475 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
1509 &elems) == ParseFailed)
1510 invalid = 1;
1511 1476
1512 if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && 1477 if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
1513 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && 1478 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
@@ -1724,9 +1689,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1724 if (baselen > len) 1689 if (baselen > len)
1725 return; 1690 return;
1726 1691
1727 if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, 1692 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
1728 &elems) == ParseFailed)
1729 return;
1730 1693
1731 if (elems.erp_info && elems.erp_info_len >= 1) 1694 if (elems.erp_info && elems.erp_info_len >= 1)
1732 ieee80211_handle_erp_ie(dev, elems.erp_info[0]); 1695 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);