aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-10-18 00:14:35 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-18 00:14:35 -0400
commitfe537c0ee86b27fbe0690a7869815da80f492dbd (patch)
tree6433cf72942bdee384c9052f5ec27f14a5787ba0 /net/mac80211
parentc95477090a2ace6d241c184adc3fbfcab9c61ceb (diff)
parent107acb23ba763197d390ae9ffd347f3e2a524d39 (diff)
Merge branch 'fixes-davem' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_ioctl.c45
-rw-r--r--net/mac80211/ieee80211_sta.c71
2 files changed, 72 insertions, 44 deletions
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index f0224c2311d2..a57fed77db27 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)
306 ((chan->chan == channel) || (chan->freq == freq))) { 306 ((chan->chan == channel) || (chan->freq == freq))) {
307 local->oper_channel = chan; 307 local->oper_channel = chan;
308 local->oper_hw_mode = mode; 308 local->oper_hw_mode = mode;
309 set++; 309 set = 1;
310 break;
310 } 311 }
311 } 312 }
313 if (set)
314 break;
312 } 315 }
313 316
314 if (set) { 317 if (set) {
@@ -508,32 +511,40 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
508 511
509static int ieee80211_ioctl_siwscan(struct net_device *dev, 512static int ieee80211_ioctl_siwscan(struct net_device *dev,
510 struct iw_request_info *info, 513 struct iw_request_info *info,
511 struct iw_point *data, char *extra) 514 union iwreq_data *wrqu, char *extra)
512{ 515{
513 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 516 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
514 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 517 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
518 struct iw_scan_req *req = NULL;
515 u8 *ssid = NULL; 519 u8 *ssid = NULL;
516 size_t ssid_len = 0; 520 size_t ssid_len = 0;
517 521
518 if (!netif_running(dev)) 522 if (!netif_running(dev))
519 return -ENETDOWN; 523 return -ENETDOWN;
520 524
521 switch (sdata->type) { 525 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
522 case IEEE80211_IF_TYPE_STA: 526 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
523 case IEEE80211_IF_TYPE_IBSS: 527 req = (struct iw_scan_req *)extra;
524 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { 528 ssid = req->essid;
525 ssid = sdata->u.sta.ssid; 529 ssid_len = req->essid_len;
526 ssid_len = sdata->u.sta.ssid_len; 530 } else {
527 } 531 switch (sdata->type) {
528 break; 532 case IEEE80211_IF_TYPE_STA:
529 case IEEE80211_IF_TYPE_AP: 533 case IEEE80211_IF_TYPE_IBSS:
530 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { 534 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
531 ssid = sdata->u.ap.ssid; 535 ssid = sdata->u.sta.ssid;
532 ssid_len = sdata->u.ap.ssid_len; 536 ssid_len = sdata->u.sta.ssid_len;
537 }
538 break;
539 case IEEE80211_IF_TYPE_AP:
540 if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
541 ssid = sdata->u.ap.ssid;
542 ssid_len = sdata->u.ap.ssid_len;
543 }
544 break;
545 default:
546 return -EOPNOTSUPP;
533 } 547 }
534 break;
535 default:
536 return -EOPNOTSUPP;
537 } 548 }
538 549
539 return ieee80211_sta_req_scan(dev, ssid, ssid_len); 550 return ieee80211_sta_req_scan(dev, ssid, ssid_len);
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 1641e8fe44b7..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 @@
61static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, 60static 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);
63static struct ieee80211_sta_bss * 62static struct ieee80211_sta_bss *
64ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); 63ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
64 u8 *ssid, u8 ssid_len);
65static void ieee80211_rx_bss_put(struct net_device *dev, 65static void ieee80211_rx_bss_put(struct net_device *dev,
66 struct ieee80211_sta_bss *bss); 66 struct ieee80211_sta_bss *bss);
67static int ieee80211_sta_find_ibss(struct net_device *dev, 67static int ieee80211_sta_find_ibss(struct net_device *dev,
@@ -427,7 +427,9 @@ 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,
432 ifsta->ssid, ifsta->ssid_len);
431 if (bss) { 433 if (bss) {
432 if (bss->has_erp_value) 434 if (bss->has_erp_value)
433 ieee80211_handle_erp_ie(dev, bss->erp_value); 435 ieee80211_handle_erp_ie(dev, bss->erp_value);
@@ -574,7 +576,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
574 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | 576 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
575 WLAN_CAPABILITY_SHORT_PREAMBLE; 577 WLAN_CAPABILITY_SHORT_PREAMBLE;
576 } 578 }
577 bss = ieee80211_rx_bss_get(dev, ifsta->bssid); 579 bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
580 ifsta->ssid, ifsta->ssid_len);
578 if (bss) { 581 if (bss) {
579 if (bss->capability & WLAN_CAPABILITY_PRIVACY) 582 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
580 capab |= WLAN_CAPABILITY_PRIVACY; 583 capab |= WLAN_CAPABILITY_PRIVACY;
@@ -722,6 +725,7 @@ static void ieee80211_send_disassoc(struct net_device *dev,
722static int ieee80211_privacy_mismatch(struct net_device *dev, 725static int ieee80211_privacy_mismatch(struct net_device *dev,
723 struct ieee80211_if_sta *ifsta) 726 struct ieee80211_if_sta *ifsta)
724{ 727{
728 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
725 struct ieee80211_sta_bss *bss; 729 struct ieee80211_sta_bss *bss;
726 int res = 0; 730 int res = 0;
727 731
@@ -729,7 +733,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
729 ifsta->key_management_enabled) 733 ifsta->key_management_enabled)
730 return 0; 734 return 0;
731 735
732 bss = ieee80211_rx_bss_get(dev, ifsta->bssid); 736 bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
737 ifsta->ssid, ifsta->ssid_len);
733 if (!bss) 738 if (!bss)
734 return 0; 739 return 0;
735 740
@@ -1203,15 +1208,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1203 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); 1208 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
1204 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 1209 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
1205 aid = le16_to_cpu(mgmt->u.assoc_resp.aid); 1210 aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
1206 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1207 printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
1208 "set\n", dev->name, aid);
1209 aid &= ~(BIT(15) | BIT(14));
1210 1211
1211 printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " 1212 printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
1212 "status=%d aid=%d)\n", 1213 "status=%d aid=%d)\n",
1213 dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), 1214 dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
1214 capab_info, status_code, aid); 1215 capab_info, status_code, aid & ~(BIT(15) | BIT(14)));
1215 1216
1216 if (status_code != WLAN_STATUS_SUCCESS) { 1217 if (status_code != WLAN_STATUS_SUCCESS) {
1217 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", 1218 printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
@@ -1223,6 +1224,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1223 return; 1224 return;
1224 } 1225 }
1225 1226
1227 if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1228 printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
1229 "set\n", dev->name, aid);
1230 aid &= ~(BIT(15) | BIT(14));
1231
1226 pos = mgmt->u.assoc_resp.variable; 1232 pos = mgmt->u.assoc_resp.variable;
1227 if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) 1233 if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
1228 == ParseFailed) { 1234 == ParseFailed) {
@@ -1241,7 +1247,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1241 * update our stored copy */ 1247 * update our stored copy */
1242 if (elems.erp_info && elems.erp_info_len >= 1) { 1248 if (elems.erp_info && elems.erp_info_len >= 1) {
1243 struct ieee80211_sta_bss *bss 1249 struct ieee80211_sta_bss *bss
1244 = ieee80211_rx_bss_get(dev, ifsta->bssid); 1250 = ieee80211_rx_bss_get(dev, ifsta->bssid,
1251 local->hw.conf.channel,
1252 ifsta->ssid, ifsta->ssid_len);
1245 if (bss) { 1253 if (bss) {
1246 bss->erp_value = elems.erp_info[0]; 1254 bss->erp_value = elems.erp_info[0];
1247 bss->has_erp_value = 1; 1255 bss->has_erp_value = 1;
@@ -1271,7 +1279,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1271 " AP\n", dev->name); 1279 " AP\n", dev->name);
1272 return; 1280 return;
1273 } 1281 }
1274 bss = ieee80211_rx_bss_get(dev, ifsta->bssid); 1282 bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
1283 local->hw.conf.channel,
1284 ifsta->ssid, ifsta->ssid_len);
1275 if (bss) { 1285 if (bss) {
1276 sta->last_rssi = bss->rssi; 1286 sta->last_rssi = bss->rssi;
1277 sta->last_signal = bss->signal; 1287 sta->last_signal = bss->signal;
@@ -1347,7 +1357,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
1347 1357
1348 1358
1349static struct ieee80211_sta_bss * 1359static struct ieee80211_sta_bss *
1350ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) 1360ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
1361 u8 *ssid, u8 ssid_len)
1351{ 1362{
1352 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1363 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1353 struct ieee80211_sta_bss *bss; 1364 struct ieee80211_sta_bss *bss;
@@ -1358,6 +1369,11 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
1358 atomic_inc(&bss->users); 1369 atomic_inc(&bss->users);
1359 atomic_inc(&bss->users); 1370 atomic_inc(&bss->users);
1360 memcpy(bss->bssid, bssid, ETH_ALEN); 1371 memcpy(bss->bssid, bssid, ETH_ALEN);
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 }
1361 1377
1362 spin_lock_bh(&local->sta_bss_lock); 1378 spin_lock_bh(&local->sta_bss_lock);
1363 /* TODO: order by RSSI? */ 1379 /* TODO: order by RSSI? */
@@ -1369,7 +1385,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
1369 1385
1370 1386
1371static struct ieee80211_sta_bss * 1387static struct ieee80211_sta_bss *
1372ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) 1388ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
1389 u8 *ssid, u8 ssid_len)
1373{ 1390{
1374 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1391 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1375 struct ieee80211_sta_bss *bss; 1392 struct ieee80211_sta_bss *bss;
@@ -1377,7 +1394,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
1377 spin_lock_bh(&local->sta_bss_lock); 1394 spin_lock_bh(&local->sta_bss_lock);
1378 bss = local->sta_bss_hash[STA_HASH(bssid)]; 1395 bss = local->sta_bss_hash[STA_HASH(bssid)];
1379 while (bss) { 1396 while (bss) {
1380 if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { 1397 if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
1398 bss->channel == channel &&
1399 bss->ssid_len == ssid_len &&
1400 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
1381 atomic_inc(&bss->users); 1401 atomic_inc(&bss->users);
1382 break; 1402 break;
1383 } 1403 }
@@ -1545,9 +1565,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1545 else 1565 else
1546 channel = rx_status->channel; 1566 channel = rx_status->channel;
1547 1567
1548 bss = ieee80211_rx_bss_get(dev, mgmt->bssid); 1568 bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
1569 elems.ssid, elems.ssid_len);
1549 if (!bss) { 1570 if (!bss) {
1550 bss = ieee80211_rx_bss_add(dev, mgmt->bssid); 1571 bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
1572 elems.ssid, elems.ssid_len);
1551 if (!bss) 1573 if (!bss)
1552 return; 1574 return;
1553 } else { 1575 } else {
@@ -1573,10 +1595,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1573 1595
1574 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 1596 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
1575 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 1597 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
1576 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
1577 memcpy(bss->ssid, elems.ssid, elems.ssid_len);
1578 bss->ssid_len = elems.ssid_len;
1579 }
1580 1598
1581 bss->supp_rates_len = 0; 1599 bss->supp_rates_len = 0;
1582 if (elems.supp_rates) { 1600 if (elems.supp_rates) {
@@ -1647,7 +1665,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1647 1665
1648 1666
1649 bss->hw_mode = rx_status->phymode; 1667 bss->hw_mode = rx_status->phymode;
1650 bss->channel = channel;
1651 bss->freq = rx_status->freq; 1668 bss->freq = rx_status->freq;
1652 if (channel != rx_status->channel && 1669 if (channel != rx_status->channel &&
1653 (bss->hw_mode == MODE_IEEE80211G || 1670 (bss->hw_mode == MODE_IEEE80211G ||
@@ -2375,7 +2392,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
2375{ 2392{
2376 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 2393 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2377 struct ieee80211_sta_bss *bss; 2394 struct ieee80211_sta_bss *bss;
2378 struct ieee80211_sub_if_data *sdata; 2395 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2379 struct ieee80211_hw_mode *mode; 2396 struct ieee80211_hw_mode *mode;
2380 u8 bssid[ETH_ALEN], *pos; 2397 u8 bssid[ETH_ALEN], *pos;
2381 int i; 2398 int i;
@@ -2398,18 +2415,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
2398 printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", 2415 printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
2399 dev->name, print_mac(mac, bssid)); 2416 dev->name, print_mac(mac, bssid));
2400 2417
2401 bss = ieee80211_rx_bss_add(dev, bssid); 2418 bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
2419 sdata->u.sta.ssid, sdata->u.sta.ssid_len);
2402 if (!bss) 2420 if (!bss)
2403 return -ENOMEM; 2421 return -ENOMEM;
2404 2422
2405 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2406 mode = local->oper_hw_mode; 2423 mode = local->oper_hw_mode;
2407 2424
2408 if (local->hw.conf.beacon_int == 0) 2425 if (local->hw.conf.beacon_int == 0)
2409 local->hw.conf.beacon_int = 100; 2426 local->hw.conf.beacon_int = 100;
2410 bss->beacon_int = local->hw.conf.beacon_int; 2427 bss->beacon_int = local->hw.conf.beacon_int;
2411 bss->hw_mode = local->hw.conf.phymode; 2428 bss->hw_mode = local->hw.conf.phymode;
2412 bss->channel = local->hw.conf.channel;
2413 bss->freq = local->hw.conf.freq; 2429 bss->freq = local->hw.conf.freq;
2414 bss->last_update = jiffies; 2430 bss->last_update = jiffies;
2415 bss->capability = WLAN_CAPABILITY_IBSS; 2431 bss->capability = WLAN_CAPABILITY_IBSS;
@@ -2469,7 +2485,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
2469 "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); 2485 "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
2470#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 2486#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2471 if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && 2487 if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
2472 (bss = ieee80211_rx_bss_get(dev, bssid))) { 2488 (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
2489 ifsta->ssid, ifsta->ssid_len))) {
2473 printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" 2490 printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
2474 " based on configured SSID\n", 2491 " based on configured SSID\n",
2475 dev->name, print_mac(mac, bssid)); 2492 dev->name, print_mac(mac, bssid));