diff options
author | John W. Linville <linville@tuxdriver.com> | 2007-10-05 14:23:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-10-16 21:19:18 -0400 |
commit | cffdd30d20d163343b1c6de25bcb0cc978a1ebf9 (patch) | |
tree | dfdf21df7e580c1098e13708a1ae6f0b581ed0fa /net | |
parent | 65c107ab3befc37b21d1c970a6159525bc0121b8 (diff) |
[PATCH] mac80211: store SSID in sta_bss_list
Some AP equipment "in the wild" services multiple SSIDs using the
same BSSID. This patch changes the key of sta_bss_list to include
the SSID as well as the BSSID and the channel so as to prevent one
SSID from eclipsing another SSID with the same BSSID.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index c1cc79e9f1f7..db81aef6177a 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* TODO: | 14 | /* TODO: |
15 | * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs | ||
16 | * order BSS list by RSSI(?) ("quality of AP") | 15 | * order BSS list by RSSI(?) ("quality of AP") |
17 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | 16 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, |
18 | * SSID) | 17 | * SSID) |
@@ -61,7 +60,8 @@ | |||
61 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | 60 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, |
62 | u8 *ssid, size_t ssid_len); | 61 | u8 *ssid, size_t ssid_len); |
63 | static struct ieee80211_sta_bss * | 62 | static struct ieee80211_sta_bss * |
64 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel); | 63 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, |
64 | u8 *ssid, u8 ssid_len); | ||
65 | static void ieee80211_rx_bss_put(struct net_device *dev, | 65 | static void ieee80211_rx_bss_put(struct net_device *dev, |
66 | struct ieee80211_sta_bss *bss); | 66 | struct ieee80211_sta_bss *bss); |
67 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 67 | static int ieee80211_sta_find_ibss(struct net_device *dev, |
@@ -428,7 +428,8 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
428 | return; | 428 | return; |
429 | 429 | ||
430 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 430 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
431 | local->hw.conf.channel); | 431 | local->hw.conf.channel, |
432 | ifsta->ssid, ifsta->ssid_len); | ||
432 | if (bss) { | 433 | if (bss) { |
433 | if (bss->has_erp_value) | 434 | if (bss->has_erp_value) |
434 | ieee80211_handle_erp_ie(dev, bss->erp_value); | 435 | ieee80211_handle_erp_ie(dev, bss->erp_value); |
@@ -575,7 +576,8 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
575 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | | 576 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | |
576 | WLAN_CAPABILITY_SHORT_PREAMBLE; | 577 | WLAN_CAPABILITY_SHORT_PREAMBLE; |
577 | } | 578 | } |
578 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); | 579 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, |
580 | ifsta->ssid, ifsta->ssid_len); | ||
579 | if (bss) { | 581 | if (bss) { |
580 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 582 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
581 | capab |= WLAN_CAPABILITY_PRIVACY; | 583 | capab |= WLAN_CAPABILITY_PRIVACY; |
@@ -731,7 +733,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, | |||
731 | ifsta->key_management_enabled) | 733 | ifsta->key_management_enabled) |
732 | return 0; | 734 | return 0; |
733 | 735 | ||
734 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); | 736 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, |
737 | ifsta->ssid, ifsta->ssid_len); | ||
735 | if (!bss) | 738 | if (!bss) |
736 | return 0; | 739 | return 0; |
737 | 740 | ||
@@ -1245,7 +1248,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1245 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1248 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1246 | struct ieee80211_sta_bss *bss | 1249 | struct ieee80211_sta_bss *bss |
1247 | = ieee80211_rx_bss_get(dev, ifsta->bssid, | 1250 | = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1248 | local->hw.conf.channel); | 1251 | local->hw.conf.channel, |
1252 | ifsta->ssid, ifsta->ssid_len); | ||
1249 | if (bss) { | 1253 | if (bss) { |
1250 | bss->erp_value = elems.erp_info[0]; | 1254 | bss->erp_value = elems.erp_info[0]; |
1251 | bss->has_erp_value = 1; | 1255 | bss->has_erp_value = 1; |
@@ -1276,7 +1280,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1276 | return; | 1280 | return; |
1277 | } | 1281 | } |
1278 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 1282 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1279 | local->hw.conf.channel); | 1283 | local->hw.conf.channel, |
1284 | ifsta->ssid, ifsta->ssid_len); | ||
1280 | if (bss) { | 1285 | if (bss) { |
1281 | sta->last_rssi = bss->rssi; | 1286 | sta->last_rssi = bss->rssi; |
1282 | sta->last_signal = bss->signal; | 1287 | sta->last_signal = bss->signal; |
@@ -1352,7 +1357,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, | |||
1352 | 1357 | ||
1353 | 1358 | ||
1354 | static struct ieee80211_sta_bss * | 1359 | static struct ieee80211_sta_bss * |
1355 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) | 1360 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, |
1361 | u8 *ssid, u8 ssid_len) | ||
1356 | { | 1362 | { |
1357 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1363 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1358 | struct ieee80211_sta_bss *bss; | 1364 | struct ieee80211_sta_bss *bss; |
@@ -1364,6 +1370,10 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) | |||
1364 | atomic_inc(&bss->users); | 1370 | atomic_inc(&bss->users); |
1365 | memcpy(bss->bssid, bssid, ETH_ALEN); | 1371 | memcpy(bss->bssid, bssid, ETH_ALEN); |
1366 | bss->channel = channel; | 1372 | bss->channel = channel; |
1373 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
1374 | memcpy(bss->ssid, ssid, ssid_len); | ||
1375 | bss->ssid_len = ssid_len; | ||
1376 | } | ||
1367 | 1377 | ||
1368 | spin_lock_bh(&local->sta_bss_lock); | 1378 | spin_lock_bh(&local->sta_bss_lock); |
1369 | /* TODO: order by RSSI? */ | 1379 | /* TODO: order by RSSI? */ |
@@ -1375,7 +1385,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) | |||
1375 | 1385 | ||
1376 | 1386 | ||
1377 | static struct ieee80211_sta_bss * | 1387 | static struct ieee80211_sta_bss * |
1378 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) | 1388 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, |
1389 | u8 *ssid, u8 ssid_len) | ||
1379 | { | 1390 | { |
1380 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1391 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1381 | struct ieee80211_sta_bss *bss; | 1392 | struct ieee80211_sta_bss *bss; |
@@ -1383,8 +1394,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) | |||
1383 | spin_lock_bh(&local->sta_bss_lock); | 1394 | spin_lock_bh(&local->sta_bss_lock); |
1384 | bss = local->sta_bss_hash[STA_HASH(bssid)]; | 1395 | bss = local->sta_bss_hash[STA_HASH(bssid)]; |
1385 | while (bss) { | 1396 | while (bss) { |
1386 | if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && | 1397 | if (!memcmp(bss->bssid, bssid, ETH_ALEN) && |
1387 | bss->channel == channel) { | 1398 | bss->channel == channel && |
1399 | bss->ssid_len == ssid_len && | ||
1400 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
1388 | atomic_inc(&bss->users); | 1401 | atomic_inc(&bss->users); |
1389 | break; | 1402 | break; |
1390 | } | 1403 | } |
@@ -1552,9 +1565,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1552 | else | 1565 | else |
1553 | channel = rx_status->channel; | 1566 | channel = rx_status->channel; |
1554 | 1567 | ||
1555 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); | 1568 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, |
1569 | elems.ssid, elems.ssid_len); | ||
1556 | if (!bss) { | 1570 | if (!bss) { |
1557 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); | 1571 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, |
1572 | elems.ssid, elems.ssid_len); | ||
1558 | if (!bss) | 1573 | if (!bss) |
1559 | return; | 1574 | return; |
1560 | } else { | 1575 | } else { |
@@ -1580,10 +1595,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1580 | 1595 | ||
1581 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1596 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
1582 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1597 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
1583 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
1584 | memcpy(bss->ssid, elems.ssid, elems.ssid_len); | ||
1585 | bss->ssid_len = elems.ssid_len; | ||
1586 | } | ||
1587 | 1598 | ||
1588 | bss->supp_rates_len = 0; | 1599 | bss->supp_rates_len = 0; |
1589 | if (elems.supp_rates) { | 1600 | if (elems.supp_rates) { |
@@ -2381,7 +2392,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2381 | { | 2392 | { |
2382 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2393 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2383 | struct ieee80211_sta_bss *bss; | 2394 | struct ieee80211_sta_bss *bss; |
2384 | struct ieee80211_sub_if_data *sdata; | 2395 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2385 | struct ieee80211_hw_mode *mode; | 2396 | struct ieee80211_hw_mode *mode; |
2386 | u8 bssid[ETH_ALEN], *pos; | 2397 | u8 bssid[ETH_ALEN], *pos; |
2387 | int i; | 2398 | int i; |
@@ -2404,11 +2415,11 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2404 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 2415 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", |
2405 | dev->name, print_mac(mac, bssid)); | 2416 | dev->name, print_mac(mac, bssid)); |
2406 | 2417 | ||
2407 | bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel); | 2418 | bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, |
2419 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | ||
2408 | if (!bss) | 2420 | if (!bss) |
2409 | return -ENOMEM; | 2421 | return -ENOMEM; |
2410 | 2422 | ||
2411 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2412 | mode = local->oper_hw_mode; | 2423 | mode = local->oper_hw_mode; |
2413 | 2424 | ||
2414 | if (local->hw.conf.beacon_int == 0) | 2425 | if (local->hw.conf.beacon_int == 0) |
@@ -2474,7 +2485,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
2474 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); | 2485 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); |
2475 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2486 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2476 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && | 2487 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && |
2477 | (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) { | 2488 | (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, |
2489 | ifsta->ssid, ifsta->ssid_len))) { | ||
2478 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2490 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" |
2479 | " based on configured SSID\n", | 2491 | " based on configured SSID\n", |
2480 | dev->name, print_mac(mac, bssid)); | 2492 | dev->name, print_mac(mac, bssid)); |