From 65c107ab3befc37b21d1c970a6159525bc0121b8 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 5 Oct 2007 14:23:27 -0400 Subject: [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 --- net/mac80211/ieee80211_sta.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'net') diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 8dae26bbfdf..c1cc79e9f1f 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -61,7 +61,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel); static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss); static int ieee80211_sta_find_ibss(struct net_device *dev, @@ -427,7 +427,8 @@ static void ieee80211_set_associated(struct net_device *dev, if (sdata->type != IEEE80211_IF_TYPE_STA) return; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { if (bss->has_erp_value) ieee80211_handle_erp_ie(dev, bss->erp_value); @@ -574,7 +575,7 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; @@ -722,6 +723,7 @@ static void ieee80211_send_disassoc(struct net_device *dev, static int ieee80211_privacy_mismatch(struct net_device *dev, struct ieee80211_if_sta *ifsta) { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; int res = 0; @@ -729,7 +731,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, ifsta->key_management_enabled) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); if (!bss) return 0; @@ -1242,7 +1244,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, * update our stored copy */ if (elems.erp_info && elems.erp_info_len >= 1) { struct ieee80211_sta_bss *bss - = ieee80211_rx_bss_get(dev, ifsta->bssid); + = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; @@ -1272,7 +1275,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, " AP\n", dev->name); return; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { sta->last_rssi = bss->rssi; sta->last_signal = bss->signal; @@ -1348,7 +1352,7 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) +ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1359,6 +1363,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) atomic_inc(&bss->users); atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); + bss->channel = channel; spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ @@ -1370,7 +1375,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1378,7 +1383,8 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) spin_lock_bh(&local->sta_bss_lock); bss = local->sta_bss_hash[STA_HASH(bssid)]; while (bss) { - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { + if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && + bss->channel == channel) { atomic_inc(&bss->users); break; } @@ -1546,9 +1552,9 @@ static void ieee80211_rx_bss_info(struct net_device *dev, else channel = rx_status->channel; - bss = ieee80211_rx_bss_get(dev, mgmt->bssid); + bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); if (!bss) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid); + bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); if (!bss) return; } else { @@ -1648,7 +1654,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->hw_mode = rx_status->phymode; - bss->channel = channel; bss->freq = rx_status->freq; if (channel != rx_status->channel && (bss->hw_mode == MODE_IEEE80211G || @@ -2399,7 +2404,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(dev, bssid); + bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel); if (!bss) return -ENOMEM; @@ -2410,7 +2415,6 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, local->hw.conf.beacon_int = 100; bss->beacon_int = local->hw.conf.beacon_int; bss->hw_mode = local->hw.conf.phymode; - bss->channel = local->hw.conf.channel; bss->freq = local->hw.conf.freq; bss->last_update = jiffies; bss->capability = WLAN_CAPABILITY_IBSS; @@ -2470,7 +2474,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid))) { + (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", dev->name, print_mac(mac, bssid)); -- cgit v1.2.3