From 58a9ac17ed7a78958d03f3b4af107f0ef075cbed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Oct 2007 21:24:07 +0200 Subject: [PATCH] mac80211: fix set_channel regression Adam Baker reported that the prism2 ioctl removal changed behaviour in that now the selection order was the other way around as before. New API is planned but not done yet, so for now just use the first matching channel in any mode as was previous behaviour with an unset next_mode. Signed-off-by: Johannes Berg Acked-by: Michael Wu Signed-off-by: John W. Linville --- net/mac80211/ieee80211_ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index f0224c2311d..6b4b0d5880d 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -306,9 +306,12 @@ int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq) ((chan->chan == channel) || (chan->freq == freq))) { local->oper_channel = chan; local->oper_hw_mode = mode; - set++; + set = 1; + break; } } + if (set) + break; } if (set) { -- cgit v1.2.3 From 1dd84aa213d0f98a91a1ec9be2f750f5f48e75a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 10 Oct 2007 12:03:41 +0200 Subject: [PATCH] mac80211: reorder association debug output There's no reason to warn about an invalid AID field when the association was denied. Signed-off-by: Johannes Berg Acked-by: Michael Wu Signed-off-by: John W. Linville --- net/mac80211/ieee80211_sta.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 1641e8fe44b..8dae26bbfdf 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -1203,15 +1203,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); - aid &= ~(BIT(15) | BIT(14)); printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), - capab_info, status_code, aid); + capab_info, status_code, aid & ~(BIT(15) | BIT(14))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", @@ -1223,6 +1219,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, return; } + if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) + printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " + "set\n", dev->name, aid); + aid &= ~(BIT(15) | BIT(14)); + pos = mgmt->u.assoc_resp.variable; if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) == ParseFailed) { -- cgit v1.2.3 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/mac80211') 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 From cffdd30d20d163343b1c6de25bcb0cc978a1ebf9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 5 Oct 2007 14:23:27 -0400 Subject: [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 --- net/mac80211/ieee80211_sta.c | 54 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 21 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index c1cc79e9f1f..db81aef6177 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -12,7 +12,6 @@ */ /* TODO: - * BSS table: use as the key to support multi-SSID APs * order BSS list by RSSI(?) ("quality of AP") * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, * SSID) @@ -61,7 +60,8 @@ 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, int channel); +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len); 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, @@ -428,7 +428,8 @@ static void ieee80211_set_associated(struct net_device *dev, return; bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->has_erp_value) ieee80211_handle_erp_ie(dev, bss->erp_value); @@ -575,7 +576,8 @@ 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, local->hw.conf.channel); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; @@ -731,7 +733,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, ifsta->key_management_enabled) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; @@ -1245,7 +1248,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, if (elems.erp_info && elems.erp_info_len >= 1) { struct ieee80211_sta_bss *bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; @@ -1276,7 +1280,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, return; } bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { sta->last_rssi = bss->rssi; sta->last_signal = bss->signal; @@ -1352,7 +1357,8 @@ 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, int channel) +ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1364,6 +1370,10 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); bss->channel = channel; + if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { + memcpy(bss->ssid, ssid, ssid_len); + bss->ssid_len = ssid_len; + } spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ @@ -1375,7 +1385,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1383,8 +1394,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) 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 && - bss->channel == channel) { + if (!memcmp(bss->bssid, bssid, ETH_ALEN) && + bss->channel == channel && + bss->ssid_len == ssid_len && + (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { atomic_inc(&bss->users); break; } @@ -1552,9 +1565,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev, else channel = rx_status->channel; - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); + bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, + elems.ssid, elems.ssid_len); if (!bss) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); + bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, + elems.ssid, elems.ssid_len); if (!bss) return; } else { @@ -1580,10 +1595,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); - if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { - memcpy(bss->ssid, elems.ssid, elems.ssid_len); - bss->ssid_len = elems.ssid_len; - } bss->supp_rates_len = 0; if (elems.supp_rates) { @@ -2381,7 +2392,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_hw_mode *mode; u8 bssid[ETH_ALEN], *pos; int i; @@ -2404,11 +2415,11 @@ 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, local->hw.conf.channel); + bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, + sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) return -ENOMEM; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); mode = local->oper_hw_mode; if (local->hw.conf.beacon_int == 0) @@ -2474,7 +2485,8 @@ 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, local->hw.conf.channel))) { + (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len))) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", dev->name, print_mac(mac, bssid)); -- cgit v1.2.3 From 107acb23ba763197d390ae9ffd347f3e2a524d39 Mon Sep 17 00:00:00 2001 From: Bill Moss Date: Wed, 10 Oct 2007 16:23:55 -0400 Subject: [PATCH] mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl This patch fixes the problem of associating with wpa_secured hidden AP. Please try out. The original author of this patch is Bill Moss Signed-off-by: Abhijeet Kolekar Signed-off-by: John W. Linville --- net/mac80211/ieee80211_ioctl.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 6b4b0d5880d..a57fed77db2 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -511,32 +511,40 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, static int ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct iw_scan_req *req = NULL; u8 *ssid = NULL; size_t ssid_len = 0; if (!netif_running(dev)) return -ENETDOWN; - switch (sdata->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.sta.ssid; - ssid_len = sdata->u.sta.ssid_len; - } - break; - case IEEE80211_IF_TYPE_AP: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.ap.ssid; - ssid_len = sdata->u.ap.ssid_len; + if (wrqu->data.length == sizeof(struct iw_scan_req) && + wrqu->data.flags & IW_SCAN_THIS_ESSID) { + req = (struct iw_scan_req *)extra; + ssid = req->essid; + ssid_len = req->essid_len; + } else { + switch (sdata->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_IBSS: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.sta.ssid; + ssid_len = sdata->u.sta.ssid_len; + } + break; + case IEEE80211_IF_TYPE_AP: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.ap.ssid; + ssid_len = sdata->u.ap.ssid_len; + } + break; + default: + return -EOPNOTSUPP; } - break; - default: - return -EOPNOTSUPP; } return ieee80211_sta_req_scan(dev, ssid, ssid_len); -- cgit v1.2.3