aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-10-28 05:59:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-02 15:23:13 -0400
commit05cb91085760ca378f28fc274fbf77fc4fd9886c (patch)
tree84beafb48cf82b1eb8a6c39a849287442e687f23
parent8a39ef8ba0fa0410d71db8e981e887fe4fdeca88 (diff)
mac80211: disable powersave for broken APs
Only AID values 1-2007 are valid, but some APs have been found to send random bogus values, in the reported case an AP that was sending the AID field value 0xffff, an AID of 0x3fff (16383). There isn't much we can do but disable powersave since there's no way it can work properly in this case. Cc: stable@vger.kernel.org Reported-by: Bill C Riemers <briemers@redhat.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c18
2 files changed, 17 insertions, 2 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4c3d1f591bec..ea10a51babda 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -389,6 +389,7 @@ struct ieee80211_if_managed {
389 389
390 unsigned long timers_running; /* used for quiesce/restart */ 390 unsigned long timers_running; /* used for quiesce/restart */
391 bool powersave; /* powersave requested for this iface */ 391 bool powersave; /* powersave requested for this iface */
392 bool broken_ap; /* AP is broken -- turn off powersave */
392 enum ieee80211_smps_mode req_smps, /* requested smps mode */ 393 enum ieee80211_smps_mode req_smps, /* requested smps mode */
393 ap_smps, /* smps mode AP thinks we're in */ 394 ap_smps, /* smps mode AP thinks we're in */
394 driver_smps_mode; /* smps mode request */ 395 driver_smps_mode; /* smps mode request */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ba2da11a997b..17258feaab9b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -637,6 +637,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
637 if (!mgd->powersave) 637 if (!mgd->powersave)
638 return false; 638 return false;
639 639
640 if (mgd->broken_ap)
641 return false;
642
640 if (!mgd->associated) 643 if (!mgd->associated)
641 return false; 644 return false;
642 645
@@ -1489,10 +1492,21 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1489 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); 1492 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1490 1493
1491 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) 1494 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1492 printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " 1495 printk(KERN_DEBUG
1493 "set\n", sdata->name, aid); 1496 "%s: invalid AID value 0x%x; bits 15:14 not set\n",
1497 sdata->name, aid);
1494 aid &= ~(BIT(15) | BIT(14)); 1498 aid &= ~(BIT(15) | BIT(14));
1495 1499
1500 ifmgd->broken_ap = false;
1501
1502 if (aid == 0 || aid > IEEE80211_MAX_AID) {
1503 printk(KERN_DEBUG
1504 "%s: invalid AID value %d (out of range), turn off PS\n",
1505 sdata->name, aid);
1506 aid = 0;
1507 ifmgd->broken_ap = true;
1508 }
1509
1496 pos = mgmt->u.assoc_resp.variable; 1510 pos = mgmt->u.assoc_resp.variable;
1497 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); 1511 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
1498 1512