scan.c revision c2b13452b283f9c4a5b02a6b53ed6416ebf4c03c
10a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg/* 25484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * Scanning implementation 35484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * 40a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> 50a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Copyright 2004, Instant802 Networks, Inc. 60a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Copyright 2005, Devicescape Software, Inc. 70a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 80a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 90a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * 100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * This program is free software; you can redistribute it and/or modify 110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * it under the terms of the GNU General Public License version 2 as 120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * published by the Free Software Foundation. 130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 155484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg/* TODO: 165484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * order BSS list by RSSI(?) ("quality of AP") 175484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, 185484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * SSID) 195484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg */ 205484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#include <linux/wireless.h> 220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#include <linux/if_arp.h> 230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#include <net/mac80211.h> 240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#include <net/iw_handler.h> 250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 260a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#include "ieee80211_i.h" 275484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#include "mesh.h" 280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#define IEEE80211_PROBE_DELAY (HZ / 33) 300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#define IEEE80211_CHANNEL_TIME (HZ / 33) 310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) 320a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 335484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergvoid ieee80211_rx_bss_list_init(struct ieee80211_local *local) 345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 35c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_init(&local->bss_lock); 36c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg INIT_LIST_HEAD(&local->bss_list); 375484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 385484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 395484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergvoid ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) 405484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 41c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss, *tmp; 425484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 43c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg list_for_each_entry_safe(bss, tmp, &local->bss_list, list) 445484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg ieee80211_rx_bss_put(local, bss); 455484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 465484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 47c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstruct ieee80211_bss * 485484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, 495484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg u8 *ssid, u8 ssid_len) 505484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 51c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 525484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 53c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 54c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg bss = local->bss_hash[STA_HASH(bssid)]; 555484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg while (bss) { 565484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss_mesh_cfg(bss) && 575484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg !memcmp(bss->bssid, bssid, ETH_ALEN) && 585484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->freq == freq && 595484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->ssid_len == ssid_len && 605484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { 615484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg atomic_inc(&bss->users); 625484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg break; 635484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 645484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = bss->hnext; 655484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 66c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 675484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return bss; 685484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 695484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 70c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg/* Caller must hold local->bss_lock */ 715484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergstatic void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, 72c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss) 735484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 745484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg u8 hash_idx; 755484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 765484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (bss_mesh_cfg(bss)) 775484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg hash_idx = mesh_id_hash(bss_mesh_id(bss), 785484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss_mesh_id_len(bss)); 795484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg else 805484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg hash_idx = STA_HASH(bss->bssid); 815484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 82c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg bss->hnext = local->bss_hash[hash_idx]; 83c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->bss_hash[hash_idx] = bss; 845484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 855484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 86c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg/* Caller must hold local->bss_lock */ 875484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergstatic void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, 88c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss) 895484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 90c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *b, *prev = NULL; 91c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg b = local->bss_hash[STA_HASH(bss->bssid)]; 925484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg while (b) { 935484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (b == bss) { 945484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!prev) 95c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->bss_hash[STA_HASH(bss->bssid)] = 965484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->hnext; 975484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg else 985484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg prev->hnext = bss->hnext; 995484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg break; 1005484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1015484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg prev = b; 1025484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg b = b->hnext; 1035484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1045484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 1055484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 106c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstruct ieee80211_bss * 1075484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, 1085484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg u8 *ssid, u8 ssid_len) 1095484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 110c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 1115484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1125484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = kzalloc(sizeof(*bss), GFP_ATOMIC); 1135484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss) 1145484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 1155484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg atomic_set(&bss->users, 2); 1165484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(bss->bssid, bssid, ETH_ALEN); 1175484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->freq = freq; 1185484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { 1195484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(bss->ssid, ssid, ssid_len); 1205484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->ssid_len = ssid_len; 1215484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1225484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 123c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 1245484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* TODO: order by RSSI? */ 125c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg list_add_tail(&bss->list, &local->bss_list); 1265484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg __ieee80211_rx_bss_hash_add(local, bss); 127c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 1285484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return bss; 1295484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 1305484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1315484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#ifdef CONFIG_MAC80211_MESH 132c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstatic struct ieee80211_bss * 1335484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, 1345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg u8 *mesh_cfg, int freq) 1355484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 136c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 1375484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 138c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 139c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; 1405484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg while (bss) { 1415484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (bss_mesh_cfg(bss) && 1425484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && 1435484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->freq == freq && 1445484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg mesh_id_len == bss->mesh_id_len && 1455484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, 1465484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg mesh_id_len))) { 1475484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg atomic_inc(&bss->users); 1485484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg break; 1495484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1505484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = bss->hnext; 1515484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 152c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 1535484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return bss; 1545484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 1555484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 156c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstatic struct ieee80211_bss * 1575484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, 1585484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg u8 *mesh_cfg, int mesh_config_len, int freq) 1595484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 160c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 1615484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1625484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (mesh_config_len != MESH_CFG_LEN) 1635484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 1645484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1655484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = kzalloc(sizeof(*bss), GFP_ATOMIC); 1665484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss) 1675484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 1685484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1695484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); 1705484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss->mesh_cfg) { 1715484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss); 1725484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 1735484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1745484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1755484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { 1765484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); 1775484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss->mesh_id) { 1785484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss->mesh_cfg); 1795484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss); 1805484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 1815484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1825484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(bss->mesh_id, mesh_id, mesh_id_len); 1835484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 1845484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 1855484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg atomic_set(&bss->users, 2); 1865484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); 1875484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->mesh_id_len = mesh_id_len; 1885484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->freq = freq; 189c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 1905484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* TODO: order by RSSI? */ 191c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg list_add_tail(&bss->list, &local->bss_list); 1925484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg __ieee80211_rx_bss_hash_add(local, bss); 193c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 1945484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return bss; 1955484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 1965484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif 1975484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 198c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstatic void ieee80211_rx_bss_free(struct ieee80211_bss *bss) 1995484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 2005484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss->ies); 2015484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss_mesh_id(bss)); 2025484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss_mesh_cfg(bss)); 2035484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss); 2045484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 2055484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2065484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergvoid ieee80211_rx_bss_put(struct ieee80211_local *local, 207c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss) 2085484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 2095484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg local_bh_disable(); 210c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { 2115484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg local_bh_enable(); 2125484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return; 2135484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2145484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2155484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg __ieee80211_rx_bss_hash_del(local, bss); 2165484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg list_del(&bss->list); 217c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 2185484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg ieee80211_rx_bss_free(bss); 2195484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 2205484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 221c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstruct ieee80211_bss * 2225484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Bergieee80211_bss_info_update(struct ieee80211_local *local, 2235484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg struct ieee80211_rx_status *rx_status, 2245484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg struct ieee80211_mgmt *mgmt, 2255484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg size_t len, 2265484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg struct ieee802_11_elems *elems, 2275484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg int freq, bool beacon) 2285484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg{ 229c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 2305484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg int clen; 2315484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2325484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#ifdef CONFIG_MAC80211_MESH 2335484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->mesh_config) 2345484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, 2355484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->mesh_id_len, elems->mesh_config, freq); 2365484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg else 2375484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif 2385484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, 2395484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->ssid, elems->ssid_len); 2405484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss) { 2415484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#ifdef CONFIG_MAC80211_MESH 2425484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->mesh_config) 2435484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, 2445484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->mesh_id_len, elems->mesh_config, 2455484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->mesh_config_len, freq); 2465484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg else 2475484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif 2485484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, 2495484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->ssid, elems->ssid_len); 2505484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss) 2515484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return NULL; 2525484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } else { 2535484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#if 0 2545484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* TODO: order by RSSI? */ 255c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 256c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg list_move_tail(&bss->list, &local->bss_list); 257c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 2585484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg#endif 2595484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2605484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2615484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* save the ERP value so that it is available at association time */ 2625484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->erp_info && elems->erp_info_len >= 1) { 2635484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->erp_value = elems->erp_info[0]; 2645484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->has_erp_value = 1; 2655484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2665484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2675484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 2685484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 2695484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2705484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->tim) { 2715484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg struct ieee80211_tim_ie *tim_ie = 2725484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg (struct ieee80211_tim_ie *)elems->tim; 2735484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->dtim_period = tim_ie->dtim_period; 2745484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2755484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2765484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* set default value for buggy APs */ 2775484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!elems->tim || bss->dtim_period == 0) 2785484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->dtim_period = 1; 2795484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2805484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->supp_rates_len = 0; 2815484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->supp_rates) { 2825484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 2835484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (clen > elems->supp_rates_len) 2845484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg clen = elems->supp_rates_len; 2855484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, 2865484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg clen); 2875484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->supp_rates_len += clen; 2885484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2895484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (elems->ext_supp_rates) { 2905484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 2915484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (clen > elems->ext_supp_rates_len) 2925484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg clen = elems->ext_supp_rates_len; 2935484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(&bss->supp_rates[bss->supp_rates_len], 2945484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg elems->ext_supp_rates, clen); 2955484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->supp_rates_len += clen; 2965484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 2975484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 2985484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->band = rx_status->band; 2995484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 3005484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); 3015484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->last_update = jiffies; 3025484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->signal = rx_status->signal; 3035484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->noise = rx_status->noise; 3045484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->qual = rx_status->qual; 3055484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->wmm_used = elems->wmm_param || elems->wmm_info; 3065484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 3075484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!beacon) 3085484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->last_probe_resp = jiffies; 3095484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 3105484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg /* 3115484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * For probe responses, or if we don't have any information yet, 3125484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg * use the IEs from the beacon. 3135484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg */ 3145484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (!bss->ies || !beacon) { 3155484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (bss->ies == NULL || bss->ies_len < elems->total_len) { 3165484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg kfree(bss->ies); 3175484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); 3185484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 3195484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg if (bss->ies) { 3205484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg memcpy(bss->ies, elems->ie_start, elems->total_len); 3215484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->ies_len = elems->total_len; 3225484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } else 3235484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg bss->ies_len = 0; 3245484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg } 3255484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg 3265484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg return bss; 3275484e23749e78d5a4f56928efaf3c4b0d862b7a6Johannes Berg} 3280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 32998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Bergieee80211_rx_result 330c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 331c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_rx_status *rx_status) 33298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg{ 33398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct ieee80211_mgmt *mgmt; 334c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 33598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg u8 *elements; 33698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct ieee80211_channel *channel; 33798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg size_t baselen; 33898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg int freq; 33998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg __le16 fc; 34098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg bool presp, beacon = false; 34198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg struct ieee802_11_elems elems; 34298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 34398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (skb->len < 2) 34498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_DROP_UNUSABLE; 34598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 34698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg mgmt = (struct ieee80211_mgmt *) skb->data; 34798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg fc = mgmt->frame_control; 34898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 34998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (ieee80211_is_ctl(fc)) 35098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_CONTINUE; 35198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 35298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (skb->len < 24) 35398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_DROP_MONITOR; 35498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 35598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg presp = ieee80211_is_probe_resp(fc); 35698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (presp) { 35798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg /* ignore ProbeResp to foreign address */ 35898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) 35998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_DROP_MONITOR; 36098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 36198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg presp = true; 36298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg elements = mgmt->u.probe_resp.variable; 36398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); 36498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg } else { 36598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg beacon = ieee80211_is_beacon(fc); 36698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); 36798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg elements = mgmt->u.beacon.variable; 36898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg } 36998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 37098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (!presp && !beacon) 37198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_CONTINUE; 37298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 37398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (baselen > skb->len) 37498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_DROP_MONITOR; 37598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 37698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg ieee802_11_parse_elems(elements, skb->len - baselen, &elems); 37798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 37898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (elems.ds_params && elems.ds_params_len == 1) 37998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg freq = ieee80211_channel_to_frequency(elems.ds_params[0]); 38098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg else 38198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg freq = rx_status->freq; 38298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 38398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); 38498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 38598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) 38698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_DROP_MONITOR; 38798c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 38898c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg bss = ieee80211_bss_info_update(sdata->local, rx_status, 38998c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg mgmt, skb->len, &elems, 39098c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg freq, beacon); 39198c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg ieee80211_rx_bss_put(sdata->local, bss); 39298c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 39398c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg dev_kfree_skb(skb); 39498c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg return RX_QUEUED; 39598c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg} 39698c8fccfaea838e62ffde2f2e44568844e0e5472Johannes Berg 3970a51b27e956bd9580296c48191b78175ed8b5971Johannes Bergstatic void ieee80211_send_nullfunc(struct ieee80211_local *local, 3980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_sub_if_data *sdata, 3990a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg int powersave) 4000a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 4010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct sk_buff *skb; 4020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_hdr *nullfunc; 4030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg __le16 fc; 4040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4050a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); 4060a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (!skb) { 4070a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " 4080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "frame\n", sdata->dev->name); 4090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return; 4100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 4110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skb_reserve(skb, local->hw.extra_tx_headroom); 4120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); 4140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(nullfunc, 0, 24); 4150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | 4160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IEEE80211_FCTL_TODS); 4170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (powersave) 4180a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_PM); 4190a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg nullfunc->frame_control = fc; 4200a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); 4210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); 4220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); 4230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 424e50db65c0dad109aae77c353305853b31555b228Johannes Berg ieee80211_tx_skb(sdata, skb, 0); 4250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 4260a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4270a51b27e956bd9580296c48191b78175ed8b5971Johannes Bergvoid ieee80211_scan_completed(struct ieee80211_hw *hw) 4280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 4290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_local *local = hw_to_local(hw); 4300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_sub_if_data *sdata; 4310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg union iwreq_data wrqu; 4320a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 433c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) 4345bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg return; 4355bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 4360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->last_scan_completed = jiffies; 4370a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&wrqu, 0, sizeof(wrqu)); 4385bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 4395bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg /* 4405bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * local->scan_sdata could have been NULLed by the interface 4415bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * down code in case we were scanning on an interface that is 4425bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * being taken down. 4435bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg */ 4445bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg sdata = local->scan_sdata; 4455bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg if (sdata) 4465bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); 4470a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 448c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (local->hw_scanning) { 449c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->hw_scanning = false; 4500a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ieee80211_hw_config(local)) 4510a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg printk(KERN_DEBUG "%s: failed to restore operational " 4520a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "channel after scan\n", wiphy_name(local->hw.wiphy)); 4530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4540a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg goto done; 4550a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 4560a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 457c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->sw_scanning = false; 4580a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ieee80211_hw_config(local)) 4590a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg printk(KERN_DEBUG "%s: failed to restore operational " 4600a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "channel after scan\n", wiphy_name(local->hw.wiphy)); 4610a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4620a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4630a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_lock_bh(local->mdev); 4640a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_addr_lock(local->mdev); 4650a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; 4660a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->ops->configure_filter(local_to_hw(local), 4670a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg FIF_BCN_PRBRESP_PROMISC, 4680a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &local->filter_flags, 4690a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->mdev->mc_count, 4700a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->mdev->mc_list); 4710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4720a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_addr_unlock(local->mdev); 4730a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_unlock_bh(local->mdev); 4740a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4750a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg rcu_read_lock(); 4760a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 4770a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* Tell AP we're back */ 4780a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { 4790a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { 4800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ieee80211_send_nullfunc(local, sdata, 0); 4810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_wake_all_queues(sdata->dev); 4820a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 4830a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } else 4840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_wake_all_queues(sdata->dev); 4850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 4860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg rcu_read_unlock(); 4870a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg done: 4890a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ieee80211_mlme_notify_scan_completed(local); 490472dbc45dc1966284de72d7de15690c17ed2cf33Johannes Berg ieee80211_mesh_notify_scan_completed(local); 4910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 4920a51b27e956bd9580296c48191b78175ed8b5971Johannes BergEXPORT_SYMBOL(ieee80211_scan_completed); 4930a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 4940a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 495c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergvoid ieee80211_scan_work(struct work_struct *work) 4960a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 4970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_local *local = 4980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg container_of(work, struct ieee80211_local, scan_work.work); 4990a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_sub_if_data *sdata = local->scan_sdata; 5000a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_supported_band *sband; 5010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_channel *chan; 5020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg int skip; 5030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg unsigned long next_delay = 0; 5040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5055bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg /* 5065bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg * Avoid re-scheduling when the sdata is going away. 5075bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg */ 5085bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg if (!netif_running(sdata->dev)) 5090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return; 5100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg switch (local->scan_state) { 5120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg case SCAN_SET_CHANNEL: 5130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 5140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * Get current scan band. scan_band may be IEEE80211_NUM_BANDS 5150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * after we successfully scanned the last channel of the last 5160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * band (and the last band is supported by the hw) 5170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 5180a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->scan_band < IEEE80211_NUM_BANDS) 5190a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sband = local->hw.wiphy->bands[local->scan_band]; 5200a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg else 5210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sband = NULL; 5220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 5240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * If we are at an unsupported band and have more bands 5250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * left to scan, advance to the next supported one. 5260a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 5270a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { 5280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_band++; 5290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sband = local->hw.wiphy->bands[local->scan_band]; 5300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_channel_idx = 0; 5310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5320a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5330a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* if no more bands/channels left, complete scan */ 5340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (!sband || local->scan_channel_idx >= sband->n_channels) { 5350a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ieee80211_scan_completed(local_to_hw(local)); 5360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return; 5370a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5380a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skip = 0; 5390a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg chan = &sband->channels[local->scan_channel_idx]; 5400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (chan->flags & IEEE80211_CHAN_DISABLED || 5420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && 5430a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg chan->flags & IEEE80211_CHAN_NO_IBSS)) 5440a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skip = 1; 5450a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (!skip) { 5470a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_channel = chan; 5480a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ieee80211_hw_config(local)) { 5490a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg printk(KERN_DEBUG "%s: failed to set freq to " 5500a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "%d MHz for scan\n", wiphy_name(local->hw.wiphy), 5510a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg chan->center_freq); 5520a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg skip = 1; 5530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5540a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5550a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5560a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* advance state machine to next channel/band */ 5570a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_channel_idx++; 5580a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->scan_channel_idx >= sband->n_channels) { 5590a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 5600a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * scan_band may end up == IEEE80211_NUM_BANDS, but 5610a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * we'll catch that case above and complete the scan 5620a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * if that is the case. 5630a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 5640a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_band++; 5650a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_channel_idx = 0; 5660a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5670a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5680a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (skip) 5690a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg break; 5700a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg next_delay = IEEE80211_PROBE_DELAY + 5720a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg usecs_to_jiffies(local->hw.channel_change_time); 5730a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_state = SCAN_SEND_PROBE; 5740a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg break; 5750a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg case SCAN_SEND_PROBE: 5760a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; 5770a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_state = SCAN_SET_CHANNEL; 5780a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5790a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) 5800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg break; 5810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, 5820a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_ssid_len); 5830a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg next_delay = IEEE80211_CHANNEL_TIME; 5840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg break; 5850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 5860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5875bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg queue_delayed_work(local->hw.workqueue, &local->scan_work, 5885bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg next_delay); 5890a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 5900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 592c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergint ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, 593c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg u8 *ssid, size_t ssid_len) 5940a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 5950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_local *local = scan_sdata->local; 5960a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_sub_if_data *sdata; 5970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 5980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ssid_len > IEEE80211_MAX_SSID_LEN) 5990a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return -EINVAL; 6000a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) 6020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS 6030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * BSSID: MACAddress 6040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * SSID 6050a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * ScanType: ACTIVE, PASSIVE 6060a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * ProbeDelay: delay (in microseconds) to be used prior to transmitting 6070a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * a Probe frame during active scanning 6080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * ChannelList 6090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * MinChannelTime (>= ProbeDelay), in TU 6100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * MaxChannelTime: (>= MinChannelTime), in TU 6110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 6120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* MLME-SCAN.confirm 6140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * BSSDescriptionSet 6150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * ResultCode: SUCCESS, INVALID_PARAMETERS 6160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 6170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 618c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (local->sw_scanning || local->hw_scanning) { 6190a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->scan_sdata == scan_sdata) 6200a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return 0; 6210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return -EBUSY; 6220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->ops->hw_scan) { 6255bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg int rc; 6265bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg 627c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->hw_scanning = true; 6285bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); 6295bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg if (rc) { 630c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->hw_scanning = false; 6315bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg return rc; 6320a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6335bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg local->scan_sdata = scan_sdata; 6345bc75728fd43bb15b46f16ef465bcf9d487393cfJohannes Berg return 0; 6350a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 637c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg local->sw_scanning = true; 6380a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6390a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg rcu_read_lock(); 6400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 6410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { 6420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { 6430a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_stop_all_queues(sdata->dev); 6440a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ieee80211_send_nullfunc(local, sdata, 1); 6450a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } else 6470a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_tx_stop_all_queues(sdata->dev); 6480a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6490a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg rcu_read_unlock(); 6500a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6510a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ssid) { 6520a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_ssid_len = ssid_len; 6530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(local->scan_ssid, ssid, ssid_len); 6540a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } else 6550a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_ssid_len = 0; 6560a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_state = SCAN_SET_CHANNEL; 6570a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_channel_idx = 0; 6580a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_band = IEEE80211_BAND_2GHZ; 6590a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->scan_sdata = scan_sdata; 6600a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6610a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_addr_lock_bh(local->mdev); 6620a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; 6630a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->ops->configure_filter(local_to_hw(local), 6640a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg FIF_BCN_PRBRESP_PROMISC, 6650a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &local->filter_flags, 6660a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->mdev->mc_count, 6670a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg local->mdev->mc_list); 6680a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg netif_addr_unlock_bh(local->mdev); 6690a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6700a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* TODO: start scan as soon as all nullfunc frames are ACKed */ 6710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg queue_delayed_work(local->hw.workqueue, &local->scan_work, 6720a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IEEE80211_CHANNEL_TIME); 6730a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6740a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return 0; 6750a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 6760a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6770a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 678c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergint ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, 679c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg u8 *ssid, size_t ssid_len) 6800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 6810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct ieee80211_local *local = sdata->local; 6829116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg struct ieee80211_if_sta *ifsta; 6830a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (sdata->vif.type != IEEE80211_IF_TYPE_STA) 685c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg return ieee80211_start_scan(sdata, ssid, ssid_len); 6860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6879116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg /* 6889116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg * STA has a state machine that might need to defer scanning 6899116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg * while it's trying to associate/authenticate, therefore we 6909116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg * queue it up to the state machine in that case. 6919116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg */ 6929116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg 693c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg if (local->sw_scanning || local->hw_scanning) { 6940a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (local->scan_sdata == sdata) 6950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return 0; 6960a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return -EBUSY; 6970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 6980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 6999116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg ifsta = &sdata->u.sta; 7009116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg 7010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg ifsta->scan_ssid_len = ssid_len; 7020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (ssid_len) 7030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(ifsta->scan_ssid, ssid, ssid_len); 7040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); 7050a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg queue_work(local->hw.workqueue, &ifsta->work); 7069116dd01120e249dc2e84e6edecd7ad7f828680fJohannes Berg 7070a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return 0; 7080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 7090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 711c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergstatic void ieee80211_scan_add_ies(struct iw_request_info *info, 712c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss, 713c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg char **current_ev, char *end_buf) 7140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 7150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg u8 *pos, *end, *next; 7160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct iw_event iwe; 7170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7180a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss == NULL || bss->ies == NULL) 7190a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return; 7200a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* 7220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * If needed, fragment the IEs buffer (at IE boundaries) into short 7230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. 7240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg */ 7250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg pos = bss->ies; 7260a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end = pos + bss->ies_len; 7270a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg while (end - pos > IW_GENERIC_IE_MAX) { 7290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg next = pos + 2 + pos[1]; 7300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) 7310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg next = next + 2 + next[1]; 7320a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7330a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 7340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVGENIE; 7350a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = next - pos; 7360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *current_ev = iwe_stream_add_point(info, *current_ev, 7370a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, &iwe, pos); 7380a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7390a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg pos = next; 7400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 7410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (end > pos) { 7430a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 7440a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVGENIE; 7450a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = end - pos; 7460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg *current_ev = iwe_stream_add_point(info, *current_ev, 7470a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, &iwe, pos); 7480a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 7490a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 7500a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7510a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7520a51b27e956bd9580296c48191b78175ed8b5971Johannes Bergstatic char * 753c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergieee80211_scan_result(struct ieee80211_local *local, 754c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct iw_request_info *info, 755c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss, 756c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg char *current_ev, char *end_buf) 7570a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 7580a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg struct iw_event iwe; 7590a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg char *buf; 7600a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7610a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (time_after(jiffies, 7620a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) 7630a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return current_ev; 7640a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7650a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 7660a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWAP; 7670a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 7680a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); 7690a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 7700a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IW_EV_ADDR_LEN); 7710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7720a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 7730a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWESSID; 7740a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss_mesh_cfg(bss)) { 7750a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = bss_mesh_id_len(bss); 7760a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.flags = 1; 7770a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, end_buf, 7780a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, bss_mesh_id(bss)); 7790a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } else { 7800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = bss->ssid_len; 7810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.flags = 1; 7820a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, end_buf, 7830a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, bss->ssid); 7840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 7850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 7860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) 7870a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg || bss_mesh_cfg(bss)) { 7880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 7890a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWMODE; 7900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss_mesh_cfg(bss)) 7910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.mode = IW_MODE_MESH; 7920a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg else if (bss->capability & WLAN_CAPABILITY_ESS) 7930a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.mode = IW_MODE_MASTER; 7940a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg else 7950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.mode = IW_MODE_ADHOC; 7960a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_event(info, current_ev, end_buf, 7970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, IW_EV_UINT_LEN); 7980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 7990a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8000a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWFREQ; 8020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); 8030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.freq.e = 0; 8040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 8050a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IW_EV_FREQ_LEN); 8060a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8070a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWFREQ; 8090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.freq.m = bss->freq; 8100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.freq.e = 6; 8110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 8120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IW_EV_FREQ_LEN); 8130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVQUAL; 8150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.qual.qual = bss->qual; 8160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.qual.level = bss->signal; 8170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.qual.noise = bss->noise; 8180a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.qual.updated = local->wstats_flags; 8190a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, 8200a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg IW_EV_QUAL_LEN); 8210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWENCODE; 8240a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss->capability & WLAN_CAPABILITY_PRIVACY) 8250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 8260a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg else 8270a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.flags = IW_ENCODE_DISABLED; 8280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = 0; 8290a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, end_buf, 8300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, ""); 8310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 832c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); 8330a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss->supp_rates_len > 0) { 8350a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* display all supported rates in readable format */ 8360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg char *p = current_ev + iwe_stream_lcp_len(info); 8370a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg int i; 8380a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8390a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8400a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = SIOCGIWRATE; 8410a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg /* Those two flags are ignored... */ 8420a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 8430a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8440a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg for (i = 0; i < bss->supp_rates_len; i++) { 8450a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.bitrate.value = ((bss->supp_rates[i] & 8460a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 0x7f) * 500000); 8470a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg p = iwe_stream_add_value(info, current_ev, p, 8480a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, &iwe, IW_EV_PARAM_LEN); 8490a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 8500a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = p; 8510a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 8520a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8530a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg buf = kmalloc(30, GFP_ATOMIC); 8540a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (buf) { 8550a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8560a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVCUSTOM; 8570a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); 8580a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 8590a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, end_buf, 8600a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 8610a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8620a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVCUSTOM; 8630a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, " Last beacon: %dms ago", 8640a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg jiffies_to_msecs(jiffies - bss->last_update)); 8650a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 8660a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 8670a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, &iwe, buf); 8680a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg kfree(buf); 8690a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 8700a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 8710a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (bss_mesh_cfg(bss)) { 8720a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg u8 *cfg = bss_mesh_cfg(bss); 8730a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg buf = kmalloc(50, GFP_ATOMIC); 8740a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (buf) { 8750a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg memset(&iwe, 0, sizeof(iwe)); 8760a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.cmd = IWEVCUSTOM; 8770a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "Mesh network (version %d)", cfg[0]); 8780a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 8790a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 8800a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, 8810a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 8820a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "Path Selection Protocol ID: " 8830a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], 8840a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg cfg[4]); 8850a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 8860a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 8870a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, 8880a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 8890a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "Path Selection Metric ID: " 8900a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], 8910a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg cfg[8]); 8920a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 8930a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 8940a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, 8950a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 8960a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "Congestion Control Mode ID: " 8970a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "0x%02X%02X%02X%02X", cfg[9], cfg[10], 8980a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg cfg[11], cfg[12]); 8990a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 9000a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 9010a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, 9020a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 9030a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg sprintf(buf, "Channel Precedence: " 9040a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg "0x%02X%02X%02X%02X", cfg[13], cfg[14], 9050a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg cfg[15], cfg[16]); 9060a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg iwe.u.data.length = strlen(buf); 9070a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev = iwe_stream_add_point(info, current_ev, 9080a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg end_buf, 9090a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg &iwe, buf); 9100a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg kfree(buf); 9110a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 9120a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 9130a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 9140a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return current_ev; 9150a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 9160a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 9170a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 918c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Bergint ieee80211_scan_results(struct ieee80211_local *local, 919c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct iw_request_info *info, 920c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg char *buf, size_t len) 9210a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg{ 9220a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg char *current_ev = buf; 9230a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg char *end_buf = buf + len; 924c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg struct ieee80211_bss *bss; 9250a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg 926c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_lock_bh(&local->bss_lock); 927c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg list_for_each_entry(bss, &local->bss_list, list) { 9280a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg if (buf + len - current_ev <= IW_EV_ADDR_LEN) { 929c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 9300a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return -E2BIG; 9310a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 932c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg current_ev = ieee80211_scan_result(local, info, bss, 9330a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg current_ev, end_buf); 9340a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg } 935c2b13452b283f9c4a5b02a6b53ed6416ebf4c03cJohannes Berg spin_unlock_bh(&local->bss_lock); 9360a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg return current_ev - buf; 9370a51b27e956bd9580296c48191b78175ed8b5971Johannes Berg} 938