aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2011-10-14 18:14:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:00:59 -0500
commitc74d084f914e16e42730bcf625ab3f37a4cae8d4 (patch)
tree2d25a95c18b679d2bd56fae50d2f185851c0d8d5 /net/mac80211/mlme.c
parentfa5e91bc7715c772342b197269a85aa3ced16900 (diff)
mac80211: handle HT PHY BSS membership selector value correctly
802.11n-2009 extends the supported rates element with a magic value which can be used to prevent legacy stations from joining the BSS. However, this magic value is not a rate like the others and the magic can simply be ignored/skipped at this late stage. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>--- Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c90
1 files changed, 49 insertions, 41 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d3b408cda08d..b25567a32f92 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1466,6 +1466,47 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1466 return RX_MGMT_CFG80211_DISASSOC; 1466 return RX_MGMT_CFG80211_DISASSOC;
1467} 1467}
1468 1468
1469static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
1470 u8 *supp_rates, unsigned int supp_rates_len,
1471 u32 *rates, u32 *basic_rates,
1472 bool *have_higher_than_11mbit,
1473 int *min_rate, int *min_rate_index)
1474{
1475 int i, j;
1476
1477 for (i = 0; i < supp_rates_len; i++) {
1478 int rate = (supp_rates[i] & 0x7f) * 5;
1479 bool is_basic = !!(supp_rates[i] & 0x80);
1480
1481 if (rate > 110)
1482 *have_higher_than_11mbit = true;
1483
1484 /*
1485 * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
1486 * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
1487 *
1488 * Note: Even through the membership selector and the basic
1489 * rate flag share the same bit, they are not exactly
1490 * the same.
1491 */
1492 if (!!(supp_rates[i] & 0x80) &&
1493 (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
1494 continue;
1495
1496 for (j = 0; j < sband->n_bitrates; j++) {
1497 if (sband->bitrates[j].bitrate == rate) {
1498 *rates |= BIT(j);
1499 if (is_basic)
1500 *basic_rates |= BIT(j);
1501 if (rate < *min_rate) {
1502 *min_rate = rate;
1503 *min_rate_index = j;
1504 }
1505 break;
1506 }
1507 }
1508 }
1509}
1469 1510
1470static bool ieee80211_assoc_success(struct ieee80211_work *wk, 1511static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1471 struct ieee80211_mgmt *mgmt, size_t len) 1512 struct ieee80211_mgmt *mgmt, size_t len)
@@ -1482,7 +1523,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1482 struct ieee802_11_elems elems; 1523 struct ieee802_11_elems elems;
1483 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 1524 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1484 u32 changed = 0; 1525 u32 changed = 0;
1485 int i, j, err; 1526 int err;
1486 bool have_higher_than_11mbit = false; 1527 bool have_higher_than_11mbit = false;
1487 u16 ap_ht_cap_flags; 1528 u16 ap_ht_cap_flags;
1488 int min_rate = INT_MAX, min_rate_index = -1; 1529 int min_rate = INT_MAX, min_rate_index = -1;
@@ -1540,47 +1581,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1540 basic_rates = 0; 1581 basic_rates = 0;
1541 sband = local->hw.wiphy->bands[wk->chan->band]; 1582 sband = local->hw.wiphy->bands[wk->chan->band];
1542 1583
1543 for (i = 0; i < elems.supp_rates_len; i++) { 1584 ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
1544 int rate = (elems.supp_rates[i] & 0x7f) * 5; 1585 &rates, &basic_rates, &have_higher_than_11mbit,
1545 bool is_basic = !!(elems.supp_rates[i] & 0x80); 1586 &min_rate, &min_rate_index);
1546
1547 if (rate > 110)
1548 have_higher_than_11mbit = true;
1549 1587
1550 for (j = 0; j < sband->n_bitrates; j++) { 1588 ieee80211_get_rates(sband, elems.ext_supp_rates,
1551 if (sband->bitrates[j].bitrate == rate) { 1589 elems.ext_supp_rates_len, &rates, &basic_rates,
1552 rates |= BIT(j); 1590 &have_higher_than_11mbit,
1553 if (is_basic) 1591 &min_rate, &min_rate_index);
1554 basic_rates |= BIT(j);
1555 if (rate < min_rate) {
1556 min_rate = rate;
1557 min_rate_index = j;
1558 }
1559 break;
1560 }
1561 }
1562 }
1563
1564 for (i = 0; i < elems.ext_supp_rates_len; i++) {
1565 int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
1566 bool is_basic = !!(elems.ext_supp_rates[i] & 0x80);
1567
1568 if (rate > 110)
1569 have_higher_than_11mbit = true;
1570
1571 for (j = 0; j < sband->n_bitrates; j++) {
1572 if (sband->bitrates[j].bitrate == rate) {
1573 rates |= BIT(j);
1574 if (is_basic)
1575 basic_rates |= BIT(j);
1576 if (rate < min_rate) {
1577 min_rate = rate;
1578 min_rate_index = j;
1579 }
1580 break;
1581 }
1582 }
1583 }
1584 1592
1585 /* 1593 /*
1586 * some buggy APs don't advertise basic_rates. use the lowest 1594 * some buggy APs don't advertise basic_rates. use the lowest