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:17:26 -0400 |
commit | 65c107ab3befc37b21d1c970a6159525bc0121b8 (patch) | |
tree | b82fae89b41e9f22f8219f6c06be14c266a04d37 /net/mac80211 | |
parent | 1dd84aa213d0f98a91a1ec9be2f750f5f48e75a0 (diff) |
[PATCH] mac80211: store channel info in sta_bss_list
Some AP equipment "in the wild" uses the same BSSID on multiple channels
(particularly "a" vs. "b/g"). This patch changes the key of sta_bss_list
to include both the BSSID and the channel so as to prevent a BSSID on
one channel from eclipsing the same BSSID on another channel.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 8dae26bbfdf9..c1cc79e9f1f7 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -61,7 +61,7 @@ | |||
61 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | 61 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, |
62 | u8 *ssid, size_t ssid_len); | 62 | u8 *ssid, size_t ssid_len); |
63 | static struct ieee80211_sta_bss * | 63 | static struct ieee80211_sta_bss * |
64 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); | 64 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel); |
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, |
@@ -427,7 +427,8 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
427 | if (sdata->type != IEEE80211_IF_TYPE_STA) | 427 | if (sdata->type != IEEE80211_IF_TYPE_STA) |
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 | if (bss) { | 432 | if (bss) { |
432 | if (bss->has_erp_value) | 433 | if (bss->has_erp_value) |
433 | ieee80211_handle_erp_ie(dev, bss->erp_value); | 434 | ieee80211_handle_erp_ie(dev, bss->erp_value); |
@@ -574,7 +575,7 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
574 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | | 575 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | |
575 | WLAN_CAPABILITY_SHORT_PREAMBLE; | 576 | WLAN_CAPABILITY_SHORT_PREAMBLE; |
576 | } | 577 | } |
577 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 578 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); |
578 | if (bss) { | 579 | if (bss) { |
579 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 580 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
580 | capab |= WLAN_CAPABILITY_PRIVACY; | 581 | capab |= WLAN_CAPABILITY_PRIVACY; |
@@ -722,6 +723,7 @@ static void ieee80211_send_disassoc(struct net_device *dev, | |||
722 | static int ieee80211_privacy_mismatch(struct net_device *dev, | 723 | static int ieee80211_privacy_mismatch(struct net_device *dev, |
723 | struct ieee80211_if_sta *ifsta) | 724 | struct ieee80211_if_sta *ifsta) |
724 | { | 725 | { |
726 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
725 | struct ieee80211_sta_bss *bss; | 727 | struct ieee80211_sta_bss *bss; |
726 | int res = 0; | 728 | int res = 0; |
727 | 729 | ||
@@ -729,7 +731,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, | |||
729 | ifsta->key_management_enabled) | 731 | ifsta->key_management_enabled) |
730 | return 0; | 732 | return 0; |
731 | 733 | ||
732 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 734 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); |
733 | if (!bss) | 735 | if (!bss) |
734 | return 0; | 736 | return 0; |
735 | 737 | ||
@@ -1242,7 +1244,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1242 | * update our stored copy */ | 1244 | * update our stored copy */ |
1243 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1245 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1244 | struct ieee80211_sta_bss *bss | 1246 | struct ieee80211_sta_bss *bss |
1245 | = ieee80211_rx_bss_get(dev, ifsta->bssid); | 1247 | = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1248 | local->hw.conf.channel); | ||
1246 | if (bss) { | 1249 | if (bss) { |
1247 | bss->erp_value = elems.erp_info[0]; | 1250 | bss->erp_value = elems.erp_info[0]; |
1248 | bss->has_erp_value = 1; | 1251 | bss->has_erp_value = 1; |
@@ -1272,7 +1275,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
1272 | " AP\n", dev->name); | 1275 | " AP\n", dev->name); |
1273 | return; | 1276 | return; |
1274 | } | 1277 | } |
1275 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | 1278 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, |
1279 | local->hw.conf.channel); | ||
1276 | if (bss) { | 1280 | if (bss) { |
1277 | sta->last_rssi = bss->rssi; | 1281 | sta->last_rssi = bss->rssi; |
1278 | sta->last_signal = bss->signal; | 1282 | sta->last_signal = bss->signal; |
@@ -1348,7 +1352,7 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, | |||
1348 | 1352 | ||
1349 | 1353 | ||
1350 | static struct ieee80211_sta_bss * | 1354 | static struct ieee80211_sta_bss * |
1351 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | 1355 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) |
1352 | { | 1356 | { |
1353 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1357 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1354 | struct ieee80211_sta_bss *bss; | 1358 | struct ieee80211_sta_bss *bss; |
@@ -1359,6 +1363,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | |||
1359 | atomic_inc(&bss->users); | 1363 | atomic_inc(&bss->users); |
1360 | atomic_inc(&bss->users); | 1364 | atomic_inc(&bss->users); |
1361 | memcpy(bss->bssid, bssid, ETH_ALEN); | 1365 | memcpy(bss->bssid, bssid, ETH_ALEN); |
1366 | bss->channel = channel; | ||
1362 | 1367 | ||
1363 | spin_lock_bh(&local->sta_bss_lock); | 1368 | spin_lock_bh(&local->sta_bss_lock); |
1364 | /* TODO: order by RSSI? */ | 1369 | /* TODO: order by RSSI? */ |
@@ -1370,7 +1375,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) | |||
1370 | 1375 | ||
1371 | 1376 | ||
1372 | static struct ieee80211_sta_bss * | 1377 | static struct ieee80211_sta_bss * |
1373 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) | 1378 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) |
1374 | { | 1379 | { |
1375 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1380 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1376 | struct ieee80211_sta_bss *bss; | 1381 | struct ieee80211_sta_bss *bss; |
@@ -1378,7 +1383,8 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) | |||
1378 | spin_lock_bh(&local->sta_bss_lock); | 1383 | spin_lock_bh(&local->sta_bss_lock); |
1379 | bss = local->sta_bss_hash[STA_HASH(bssid)]; | 1384 | bss = local->sta_bss_hash[STA_HASH(bssid)]; |
1380 | while (bss) { | 1385 | while (bss) { |
1381 | if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { | 1386 | if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && |
1387 | bss->channel == channel) { | ||
1382 | atomic_inc(&bss->users); | 1388 | atomic_inc(&bss->users); |
1383 | break; | 1389 | break; |
1384 | } | 1390 | } |
@@ -1546,9 +1552,9 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1546 | else | 1552 | else |
1547 | channel = rx_status->channel; | 1553 | channel = rx_status->channel; |
1548 | 1554 | ||
1549 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid); | 1555 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); |
1550 | if (!bss) { | 1556 | if (!bss) { |
1551 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid); | 1557 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); |
1552 | if (!bss) | 1558 | if (!bss) |
1553 | return; | 1559 | return; |
1554 | } else { | 1560 | } else { |
@@ -1648,7 +1654,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
1648 | 1654 | ||
1649 | 1655 | ||
1650 | bss->hw_mode = rx_status->phymode; | 1656 | bss->hw_mode = rx_status->phymode; |
1651 | bss->channel = channel; | ||
1652 | bss->freq = rx_status->freq; | 1657 | bss->freq = rx_status->freq; |
1653 | if (channel != rx_status->channel && | 1658 | if (channel != rx_status->channel && |
1654 | (bss->hw_mode == MODE_IEEE80211G || | 1659 | (bss->hw_mode == MODE_IEEE80211G || |
@@ -2399,7 +2404,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2399 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 2404 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", |
2400 | dev->name, print_mac(mac, bssid)); | 2405 | dev->name, print_mac(mac, bssid)); |
2401 | 2406 | ||
2402 | bss = ieee80211_rx_bss_add(dev, bssid); | 2407 | bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel); |
2403 | if (!bss) | 2408 | if (!bss) |
2404 | return -ENOMEM; | 2409 | return -ENOMEM; |
2405 | 2410 | ||
@@ -2410,7 +2415,6 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
2410 | local->hw.conf.beacon_int = 100; | 2415 | local->hw.conf.beacon_int = 100; |
2411 | bss->beacon_int = local->hw.conf.beacon_int; | 2416 | bss->beacon_int = local->hw.conf.beacon_int; |
2412 | bss->hw_mode = local->hw.conf.phymode; | 2417 | bss->hw_mode = local->hw.conf.phymode; |
2413 | bss->channel = local->hw.conf.channel; | ||
2414 | bss->freq = local->hw.conf.freq; | 2418 | bss->freq = local->hw.conf.freq; |
2415 | bss->last_update = jiffies; | 2419 | bss->last_update = jiffies; |
2416 | bss->capability = WLAN_CAPABILITY_IBSS; | 2420 | bss->capability = WLAN_CAPABILITY_IBSS; |
@@ -2470,7 +2474,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
2470 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); | 2474 | "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); |
2471 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2475 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2472 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && | 2476 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && |
2473 | (bss = ieee80211_rx_bss_get(dev, bssid))) { | 2477 | (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) { |
2474 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2478 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" |
2475 | " based on configured SSID\n", | 2479 | " based on configured SSID\n", |
2476 | dev->name, print_mac(mac, bssid)); | 2480 | dev->name, print_mac(mac, bssid)); |