aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h42
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/mesh.c10
-rw-r--r--net/mac80211/mesh.h1
-rw-r--r--net/mac80211/mlme.c213
-rw-r--r--net/mac80211/scan.c253
-rw-r--r--net/mac80211/spectmgmt.c7
7 files changed, 114 insertions, 418 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 87d63fe61bf9..678278344d79 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -72,43 +72,36 @@ struct ieee80211_fragment_entry {
72 72
73 73
74struct ieee80211_bss { 74struct ieee80211_bss {
75 struct list_head list; 75 /* Yes, this is a hack */
76 struct ieee80211_bss *hnext; 76 struct cfg80211_bss cbss;
77 size_t ssid_len;
78 77
79 atomic_t users; 78 /* don't want to look up all the time */
80 79 size_t ssid_len;
81 u8 bssid[ETH_ALEN];
82 u8 ssid[IEEE80211_MAX_SSID_LEN]; 80 u8 ssid[IEEE80211_MAX_SSID_LEN];
81
83 u8 dtim_period; 82 u8 dtim_period;
84 u16 capability; /* host byte order */ 83
85 enum ieee80211_band band;
86 int freq;
87 int signal, noise, qual;
88 u8 *ies; /* all information elements from the last Beacon or Probe
89 * Response frames; note Beacon frame is not allowed to
90 * override values from Probe Response */
91 size_t ies_len;
92 bool wmm_used; 84 bool wmm_used;
85
86 unsigned long last_probe_resp;
87
93#ifdef CONFIG_MAC80211_MESH 88#ifdef CONFIG_MAC80211_MESH
94 u8 *mesh_id; 89 u8 *mesh_id;
95 size_t mesh_id_len; 90 size_t mesh_id_len;
96 u8 *mesh_cfg; 91 u8 *mesh_cfg;
97#endif 92#endif
93
98#define IEEE80211_MAX_SUPP_RATES 32 94#define IEEE80211_MAX_SUPP_RATES 32
99 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 95 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
100 size_t supp_rates_len; 96 size_t supp_rates_len;
101 u64 timestamp;
102 int beacon_int;
103 97
104 unsigned long last_probe_resp; 98 /*
105 unsigned long last_update; 99 * During assocation, we save an ERP value from a probe response so
106
107 /* during assocation, we save an ERP value from a probe response so
108 * that we can feed ERP info to the driver when handling the 100 * that we can feed ERP info to the driver when handling the
109 * association completes. these fields probably won't be up-to-date 101 * association completes. these fields probably won't be up-to-date
110 * otherwise, you probably don't want to use them. */ 102 * otherwise, you probably don't want to use them.
111 int has_erp_value; 103 */
104 bool has_erp_value;
112 u8 erp_value; 105 u8 erp_value;
113}; 106};
114 107
@@ -668,9 +661,6 @@ struct ieee80211_local {
668 struct ieee80211_sub_if_data *scan_sdata; 661 struct ieee80211_sub_if_data *scan_sdata;
669 enum nl80211_channel_type oper_channel_type; 662 enum nl80211_channel_type oper_channel_type;
670 struct ieee80211_channel *oper_channel, *csa_channel; 663 struct ieee80211_channel *oper_channel, *csa_channel;
671 struct list_head bss_list;
672 struct ieee80211_bss *bss_hash[STA_HASH_SIZE];
673 spinlock_t bss_lock;
674 664
675 /* SNMP counters */ 665 /* SNMP counters */
676 /* dot11CountersTable */ 666 /* dot11CountersTable */
@@ -936,8 +926,6 @@ ieee80211_rx_result
936ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, 926ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
937 struct sk_buff *skb, 927 struct sk_buff *skb,
938 struct ieee80211_rx_status *rx_status); 928 struct ieee80211_rx_status *rx_status);
939void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
940void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
941int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, 929int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
942 char *ie, size_t len); 930 char *ie, size_t len);
943 931
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 954edfbb6b6f..b4973a1b6595 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -734,6 +734,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
734 734
735 wiphy->privid = mac80211_wiphy_privid; 735 wiphy->privid = mac80211_wiphy_privid;
736 wiphy->max_scan_ssids = 4; 736 wiphy->max_scan_ssids = 4;
737 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
738 wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
739 sizeof(struct cfg80211_bss);
737 740
738 local = wiphy_priv(wiphy); 741 local = wiphy_priv(wiphy);
739 local->hw.wiphy = wiphy; 742 local->hw.wiphy = wiphy;
@@ -877,8 +880,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
877 mpriv->local = local; 880 mpriv->local = local;
878 local->mdev = mdev; 881 local->mdev = mdev;
879 882
880 ieee80211_rx_bss_list_init(local);
881
882 local->hw.workqueue = 883 local->hw.workqueue =
883 create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); 884 create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
884 if (!local->hw.workqueue) { 885 if (!local->hw.workqueue) {
@@ -1018,7 +1019,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1018 1019
1019 rtnl_unlock(); 1020 rtnl_unlock();
1020 1021
1021 ieee80211_rx_bss_list_deinit(local);
1022 ieee80211_clear_tx_pending(local); 1022 ieee80211_clear_tx_pending(local);
1023 sta_info_stop(local); 1023 sta_info_stop(local);
1024 rate_control_deinitialize(local); 1024 rate_control_deinitialize(local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8a1fcaeee4f2..9a3e5de0410a 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -275,16 +275,6 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_t
275 & tbl->hash_mask; 275 & tbl->hash_mask;
276} 276}
277 277
278u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
279{
280 if (!mesh_id_len)
281 return 1;
282 else if (mesh_id_len == 1)
283 return (u8) mesh_id[0];
284 else
285 return (u8) (mesh_id[0] + 2 * mesh_id[1]);
286}
287
288struct mesh_table *mesh_table_alloc(int size_order) 278struct mesh_table *mesh_table_alloc(int size_order)
289{ 279{
290 int i; 280 int i;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 9e064ee98ee0..d891d7ddccd7 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -196,7 +196,6 @@ struct mesh_rmc {
196 196
197/* Public interfaces */ 197/* Public interfaces */
198/* Various */ 198/* Various */
199u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
200int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); 199int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
201int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 200int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
202 struct ieee80211_sub_if_data *sdata); 201 struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c5991ec047be..c51860f66731 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -55,10 +55,10 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
55{ 55{
56 u8 *end, *pos; 56 u8 *end, *pos;
57 57
58 pos = bss->ies; 58 pos = bss->cbss.information_elements;
59 if (pos == NULL) 59 if (pos == NULL)
60 return NULL; 60 return NULL;
61 end = pos + bss->ies_len; 61 end = pos + bss->cbss.len_information_elements;
62 62
63 while (pos + 1 < end) { 63 while (pos + 1 < end) {
64 if (pos + 2 + pos[1] > end) 64 if (pos + 2 + pos[1] > end)
@@ -289,7 +289,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
289 local->hw.conf.channel->center_freq, 289 local->hw.conf.channel->center_freq,
290 ifsta->ssid, ifsta->ssid_len); 290 ifsta->ssid, ifsta->ssid_len);
291 if (bss) { 291 if (bss) {
292 if (bss->capability & WLAN_CAPABILITY_PRIVACY) 292 if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
293 capab |= WLAN_CAPABILITY_PRIVACY; 293 capab |= WLAN_CAPABILITY_PRIVACY;
294 if (bss->wmm_used) 294 if (bss->wmm_used)
295 wmm = 1; 295 wmm = 1;
@@ -300,7 +300,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
300 * b-only mode) */ 300 * b-only mode) */
301 rates_len = ieee80211_compatible_rates(bss, sband, &rates); 301 rates_len = ieee80211_compatible_rates(bss, sband, &rates);
302 302
303 if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && 303 if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
304 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) 304 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
305 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; 305 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
306 306
@@ -816,12 +816,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
816 ifsta->ssid, ifsta->ssid_len); 816 ifsta->ssid, ifsta->ssid_len);
817 if (bss) { 817 if (bss) {
818 /* set timing information */ 818 /* set timing information */
819 sdata->vif.bss_conf.beacon_int = bss->beacon_int; 819 sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
820 sdata->vif.bss_conf.timestamp = bss->timestamp; 820 sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
821 sdata->vif.bss_conf.dtim_period = bss->dtim_period; 821 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
822 822
823 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 823 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
824 bss->capability, bss->has_erp_value, bss->erp_value); 824 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
825 825
826 ieee80211_rx_bss_put(local, bss); 826 ieee80211_rx_bss_put(local, bss);
827 } 827 }
@@ -1041,7 +1041,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
1041 if (!bss) 1041 if (!bss)
1042 return 0; 1042 return 0;
1043 1043
1044 bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); 1044 bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
1045 wep_privacy = !!ieee80211_sta_wep_configured(sdata); 1045 wep_privacy = !!ieee80211_sta_wep_configured(sdata);
1046 privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); 1046 privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
1047 1047
@@ -1416,8 +1416,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1416 /* Add STA entry for the AP */ 1416 /* Add STA entry for the AP */
1417 sta = sta_info_get(local, ifsta->bssid); 1417 sta = sta_info_get(local, ifsta->bssid);
1418 if (!sta) { 1418 if (!sta) {
1419 struct ieee80211_bss *bss;
1420
1421 newsta = true; 1419 newsta = true;
1422 1420
1423 sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); 1421 sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
@@ -1427,15 +1425,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1427 rcu_read_unlock(); 1425 rcu_read_unlock();
1428 return; 1426 return;
1429 } 1427 }
1430 bss = ieee80211_rx_bss_get(local, ifsta->bssid,
1431 local->hw.conf.channel->center_freq,
1432 ifsta->ssid, ifsta->ssid_len);
1433 if (bss) {
1434 sta->last_signal = bss->signal;
1435 sta->last_qual = bss->qual;
1436 sta->last_noise = bss->noise;
1437 ieee80211_rx_bss_put(local, bss);
1438 }
1439 1428
1440 /* update new sta with its last rx activity */ 1429 /* update new sta with its last rx activity */
1441 sta->last_rx = jiffies; 1430 sta->last_rx = jiffies;
@@ -1691,10 +1680,11 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
1691 struct ieee80211_bss *bss) 1680 struct ieee80211_bss *bss)
1692{ 1681{
1693 return __ieee80211_sta_join_ibss(sdata, ifsta, 1682 return __ieee80211_sta_join_ibss(sdata, ifsta,
1694 bss->bssid, bss->beacon_int, 1683 bss->cbss.bssid,
1695 bss->freq, 1684 bss->cbss.beacon_interval,
1685 bss->cbss.channel->center_freq,
1696 bss->supp_rates_len, bss->supp_rates, 1686 bss->supp_rates_len, bss->supp_rates,
1697 bss->capability); 1687 bss->cbss.capability);
1698} 1688}
1699 1689
1700static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 1690static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -1769,7 +1759,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1769 } 1759 }
1770 1760
1771 /* was just updated in ieee80211_bss_info_update */ 1761 /* was just updated in ieee80211_bss_info_update */
1772 beacon_timestamp = bss->timestamp; 1762 beacon_timestamp = bss->cbss.tsf;
1773 1763
1774 /* 1764 /*
1775 * In STA mode, the remaining parameters should not be overridden 1765 * In STA mode, the remaining parameters should not be overridden
@@ -1784,8 +1774,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1784 /* check if we need to merge IBSS */ 1774 /* check if we need to merge IBSS */
1785 if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && 1775 if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
1786 (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) && 1776 (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
1787 bss->capability & WLAN_CAPABILITY_IBSS && 1777 bss->cbss.capability & WLAN_CAPABILITY_IBSS &&
1788 bss->freq == local->oper_channel->center_freq && 1778 bss->cbss.channel == local->oper_channel &&
1789 elems->ssid_len == sdata->u.sta.ssid_len && 1779 elems->ssid_len == sdata->u.sta.ssid_len &&
1790 memcmp(elems->ssid, sdata->u.sta.ssid, 1780 memcmp(elems->ssid, sdata->u.sta.ssid,
1791 sdata->u.sta.ssid_len) == 0) { 1781 sdata->u.sta.ssid_len) == 0) {
@@ -2230,37 +2220,6 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
2230 netif_carrier_off(sdata->dev); 2220 netif_carrier_off(sdata->dev);
2231} 2221}
2232 2222
2233
2234static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
2235 const char *ssid, int ssid_len)
2236{
2237 int tmp, hidden_ssid;
2238
2239 if (ssid_len == ifsta->ssid_len &&
2240 !memcmp(ifsta->ssid, ssid, ssid_len))
2241 return 1;
2242
2243 if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
2244 return 0;
2245
2246 hidden_ssid = 1;
2247 tmp = ssid_len;
2248 while (tmp--) {
2249 if (ssid[tmp] != '\0') {
2250 hidden_ssid = 0;
2251 break;
2252 }
2253 }
2254
2255 if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0))
2256 return 1;
2257
2258 if (ssid_len == 1 && ssid[0] == ' ')
2259 return 1;
2260
2261 return 0;
2262}
2263
2264static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, 2223static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
2265 struct ieee80211_if_sta *ifsta) 2224 struct ieee80211_if_sta *ifsta)
2266{ 2225{
@@ -2319,8 +2278,6 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
2319{ 2278{
2320 struct ieee80211_local *local = sdata->local; 2279 struct ieee80211_local *local = sdata->local;
2321 struct ieee80211_bss *bss; 2280 struct ieee80211_bss *bss;
2322 int found = 0;
2323 u8 bssid[ETH_ALEN];
2324 int active_ibss; 2281 int active_ibss;
2325 2282
2326 if (ifsta->ssid_len == 0) 2283 if (ifsta->ssid_len == 0)
@@ -2331,56 +2288,39 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
2331 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", 2288 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
2332 sdata->dev->name, active_ibss); 2289 sdata->dev->name, active_ibss);
2333#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 2290#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2334 spin_lock_bh(&local->bss_lock); 2291
2335 list_for_each_entry(bss, &local->bss_list, list) { 2292 if (active_ibss)
2336 if (ifsta->ssid_len != bss->ssid_len || 2293 return 0;
2337 memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 2294
2338 || !(bss->capability & WLAN_CAPABILITY_IBSS)) 2295 if (ifsta->flags & IEEE80211_STA_BSSID_SET)
2339 continue; 2296 bss = ieee80211_rx_bss_get(local, ifsta->bssid, 0,
2340 if ((ifsta->flags & IEEE80211_STA_BSSID_SET) && 2297 ifsta->ssid, ifsta->ssid_len);
2341 memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) != 0) 2298 else
2342 continue; 2299 bss = (void *)cfg80211_get_ibss(local->hw.wiphy,
2343#ifdef CONFIG_MAC80211_IBSS_DEBUG 2300 NULL,
2344 printk(KERN_DEBUG " bssid=%pM found\n", bss->bssid); 2301 ifsta->ssid, ifsta->ssid_len);
2345#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2346 memcpy(bssid, bss->bssid, ETH_ALEN);
2347 found = 1;
2348 if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
2349 break;
2350 }
2351 spin_unlock_bh(&local->bss_lock);
2352 2302
2353#ifdef CONFIG_MAC80211_IBSS_DEBUG 2303#ifdef CONFIG_MAC80211_IBSS_DEBUG
2354 if (found) 2304 if (bss)
2355 printk(KERN_DEBUG " sta_find_ibss: selected %pM current " 2305 printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
2356 "%pM\n", bssid, ifsta->bssid); 2306 "%pM\n", bss->cbss.bssid, ifsta->bssid);
2357#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 2307#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2358 2308
2359 if (found && 2309 if (bss &&
2360 ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) || 2310 (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) ||
2361 memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) { 2311 memcmp(ifsta->bssid, bss->cbss.bssid, ETH_ALEN))) {
2362 int ret; 2312 int ret;
2363 int search_freq;
2364
2365 if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
2366 search_freq = bss->freq;
2367 else
2368 search_freq = local->hw.conf.channel->center_freq;
2369
2370 bss = ieee80211_rx_bss_get(local, bssid, search_freq,
2371 ifsta->ssid, ifsta->ssid_len);
2372 if (!bss)
2373 goto dont_join;
2374 2313
2375 printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" 2314 printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
2376 " based on configured SSID\n", 2315 " based on configured SSID\n",
2377 sdata->dev->name, bssid); 2316 sdata->dev->name, bss->cbss.bssid);
2317
2378 ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); 2318 ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
2379 ieee80211_rx_bss_put(local, bss); 2319 ieee80211_rx_bss_put(local, bss);
2380 return ret; 2320 return ret;
2381 } 2321 } else if (bss)
2322 ieee80211_rx_bss_put(local, bss);
2382 2323
2383dont_join:
2384#ifdef CONFIG_MAC80211_IBSS_DEBUG 2324#ifdef CONFIG_MAC80211_IBSS_DEBUG
2385 printk(KERN_DEBUG " did not try to join ibss\n"); 2325 printk(KERN_DEBUG " did not try to join ibss\n");
2386#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 2326#endif /* CONFIG_MAC80211_IBSS_DEBUG */
@@ -2436,51 +2376,44 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2436 struct ieee80211_if_sta *ifsta) 2376 struct ieee80211_if_sta *ifsta)
2437{ 2377{
2438 struct ieee80211_local *local = sdata->local; 2378 struct ieee80211_local *local = sdata->local;
2439 struct ieee80211_bss *bss, *selected = NULL; 2379 struct ieee80211_bss *bss;
2440 int top_rssi = 0, freq; 2380 u8 *bssid = ifsta->bssid, *ssid = ifsta->ssid;
2441 2381 u8 ssid_len = ifsta->ssid_len;
2442 spin_lock_bh(&local->bss_lock); 2382 u16 capa_mask = WLAN_CAPABILITY_ESS;
2443 freq = local->oper_channel->center_freq; 2383 u16 capa_val = WLAN_CAPABILITY_ESS;
2444 list_for_each_entry(bss, &local->bss_list, list) { 2384 struct ieee80211_channel *chan = local->oper_channel;
2445 if (!(bss->capability & WLAN_CAPABILITY_ESS)) 2385
2446 continue; 2386 if (ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
2447 2387 IEEE80211_STA_AUTO_BSSID_SEL |
2448 if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | 2388 IEEE80211_STA_AUTO_CHANNEL_SEL)) {
2449 IEEE80211_STA_AUTO_BSSID_SEL | 2389 capa_mask |= WLAN_CAPABILITY_PRIVACY;
2450 IEEE80211_STA_AUTO_CHANNEL_SEL)) && 2390 if (sdata->default_key)
2451 (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ 2391 capa_val |= WLAN_CAPABILITY_PRIVACY;
2452 !!sdata->default_key))
2453 continue;
2454
2455 if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
2456 bss->freq != freq)
2457 continue;
2458
2459 if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
2460 memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
2461 continue;
2462
2463 if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
2464 !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
2465 continue;
2466
2467 if (!selected || top_rssi < bss->signal) {
2468 selected = bss;
2469 top_rssi = bss->signal;
2470 }
2471 } 2392 }
2472 if (selected)
2473 atomic_inc(&selected->users);
2474 spin_unlock_bh(&local->bss_lock);
2475 2393
2476 if (selected) { 2394 if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
2477 ieee80211_set_freq(sdata, selected->freq); 2395 chan = NULL;
2396
2397 if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
2398 bssid = NULL;
2399
2400 if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) {
2401 ssid = NULL;
2402 ssid_len = 0;
2403 }
2404
2405 bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
2406 bssid, ssid, ssid_len,
2407 capa_mask, capa_val);
2408
2409 if (bss) {
2410 ieee80211_set_freq(sdata, bss->cbss.channel->center_freq);
2478 if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) 2411 if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
2479 ieee80211_sta_set_ssid(sdata, selected->ssid, 2412 ieee80211_sta_set_ssid(sdata, bss->ssid,
2480 selected->ssid_len); 2413 bss->ssid_len);
2481 ieee80211_sta_set_bssid(sdata, selected->bssid); 2414 ieee80211_sta_set_bssid(sdata, bss->cbss.bssid);
2482 ieee80211_sta_def_wmm_params(sdata, selected->supp_rates_len, 2415 ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
2483 selected->supp_rates); 2416 bss->supp_rates);
2484 if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED) 2417 if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED)
2485 sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED; 2418 sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED;
2486 else 2419 else
@@ -2489,14 +2422,14 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2489 /* Send out direct probe if no probe resp was received or 2422 /* Send out direct probe if no probe resp was received or
2490 * the one we have is outdated 2423 * the one we have is outdated
2491 */ 2424 */
2492 if (!selected->last_probe_resp || 2425 if (!bss->last_probe_resp ||
2493 time_after(jiffies, selected->last_probe_resp 2426 time_after(jiffies, bss->last_probe_resp
2494 + IEEE80211_SCAN_RESULT_EXPIRE)) 2427 + IEEE80211_SCAN_RESULT_EXPIRE))
2495 ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; 2428 ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
2496 else 2429 else
2497 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; 2430 ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
2498 2431
2499 ieee80211_rx_bss_put(local, selected); 2432 ieee80211_rx_bss_put(local, bss);
2500 ieee80211_sta_reset_auth(sdata, ifsta); 2433 ieee80211_sta_reset_auth(sdata, ifsta);
2501 return 0; 2434 return 0;
2502 } else { 2435 } else {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index fc88e2e2f923..f883ab9f1e6e 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -12,10 +12,7 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15/* TODO: 15/* TODO: figure out how to avoid that the "current BSS" expires */
16 * figure out how to avoid that the "current BSS" expires
17 * use cfg80211's BSS handling
18 */
19 16
20#include <linux/wireless.h> 17#include <linux/wireless.h>
21#include <linux/if_arp.h> 18#include <linux/if_arp.h>
@@ -30,192 +27,29 @@
30#define IEEE80211_CHANNEL_TIME (HZ / 33) 27#define IEEE80211_CHANNEL_TIME (HZ / 33)
31#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) 28#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
32 29
33void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
34{
35 spin_lock_init(&local->bss_lock);
36 INIT_LIST_HEAD(&local->bss_list);
37}
38
39void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
40{
41 struct ieee80211_bss *bss, *tmp;
42
43 list_for_each_entry_safe(bss, tmp, &local->bss_list, list)
44 ieee80211_rx_bss_put(local, bss);
45}
46
47struct ieee80211_bss * 30struct ieee80211_bss *
48ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, 31ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
49 u8 *ssid, u8 ssid_len) 32 u8 *ssid, u8 ssid_len)
50{ 33{
51 struct ieee80211_bss *bss; 34 return (void *)cfg80211_get_bss(local->hw.wiphy,
52 35 ieee80211_get_channel(local->hw.wiphy,
53 spin_lock_bh(&local->bss_lock); 36 freq),
54 bss = local->bss_hash[STA_HASH(bssid)]; 37 bssid, ssid, ssid_len,
55 while (bss) { 38 0, 0);
56 if (!bss_mesh_cfg(bss) &&
57 !memcmp(bss->bssid, bssid, ETH_ALEN) &&
58 bss->freq == freq &&
59 bss->ssid_len == ssid_len &&
60 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
61 atomic_inc(&bss->users);
62 break;
63 }
64 bss = bss->hnext;
65 }
66 spin_unlock_bh(&local->bss_lock);
67 return bss;
68}
69
70/* Caller must hold local->bss_lock */
71static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
72 struct ieee80211_bss *bss)
73{
74 u8 hash_idx;
75
76 if (bss_mesh_cfg(bss))
77 hash_idx = mesh_id_hash(bss_mesh_id(bss),
78 bss_mesh_id_len(bss));
79 else
80 hash_idx = STA_HASH(bss->bssid);
81
82 bss->hnext = local->bss_hash[hash_idx];
83 local->bss_hash[hash_idx] = bss;
84}
85
86/* Caller must hold local->bss_lock */
87static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
88 struct ieee80211_bss *bss)
89{
90 struct ieee80211_bss *b, *prev = NULL;
91 b = local->bss_hash[STA_HASH(bss->bssid)];
92 while (b) {
93 if (b == bss) {
94 if (!prev)
95 local->bss_hash[STA_HASH(bss->bssid)] =
96 bss->hnext;
97 else
98 prev->hnext = bss->hnext;
99 break;
100 }
101 prev = b;
102 b = b->hnext;
103 }
104}
105
106static struct ieee80211_bss *
107ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
108 u8 *ssid, u8 ssid_len)
109{
110 struct ieee80211_bss *bss;
111
112 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
113 if (!bss)
114 return NULL;
115 atomic_set(&bss->users, 2);
116 memcpy(bss->bssid, bssid, ETH_ALEN);
117 bss->freq = freq;
118 if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
119 memcpy(bss->ssid, ssid, ssid_len);
120 bss->ssid_len = ssid_len;
121 }
122
123 spin_lock_bh(&local->bss_lock);
124 /* TODO: order by RSSI? */
125 list_add_tail(&bss->list, &local->bss_list);
126 __ieee80211_rx_bss_hash_add(local, bss);
127 spin_unlock_bh(&local->bss_lock);
128 return bss;
129}
130
131#ifdef CONFIG_MAC80211_MESH
132static struct ieee80211_bss *
133ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
134 u8 *mesh_cfg, int freq)
135{
136 struct ieee80211_bss *bss;
137
138 spin_lock_bh(&local->bss_lock);
139 bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
140 while (bss) {
141 if (bss_mesh_cfg(bss) &&
142 !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
143 bss->freq == freq &&
144 mesh_id_len == bss->mesh_id_len &&
145 (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
146 mesh_id_len))) {
147 atomic_inc(&bss->users);
148 break;
149 }
150 bss = bss->hnext;
151 }
152 spin_unlock_bh(&local->bss_lock);
153 return bss;
154} 39}
155 40
156static struct ieee80211_bss * 41static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
157ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
158 u8 *mesh_cfg, int mesh_config_len, int freq)
159{ 42{
160 struct ieee80211_bss *bss; 43 struct ieee80211_bss *bss = (void *)cbss;
161
162 if (mesh_config_len != IEEE80211_MESH_CONFIG_LEN)
163 return NULL;
164
165 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
166 if (!bss)
167 return NULL;
168
169 bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
170 if (!bss->mesh_cfg) {
171 kfree(bss);
172 return NULL;
173 }
174
175 if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
176 bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
177 if (!bss->mesh_id) {
178 kfree(bss->mesh_cfg);
179 kfree(bss);
180 return NULL;
181 }
182 memcpy(bss->mesh_id, mesh_id, mesh_id_len);
183 }
184
185 atomic_set(&bss->users, 2);
186 memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
187 bss->mesh_id_len = mesh_id_len;
188 bss->freq = freq;
189 spin_lock_bh(&local->bss_lock);
190 /* TODO: order by RSSI? */
191 list_add_tail(&bss->list, &local->bss_list);
192 __ieee80211_rx_bss_hash_add(local, bss);
193 spin_unlock_bh(&local->bss_lock);
194 return bss;
195}
196#endif
197 44
198static void ieee80211_rx_bss_free(struct ieee80211_bss *bss)
199{
200 kfree(bss->ies);
201 kfree(bss_mesh_id(bss)); 45 kfree(bss_mesh_id(bss));
202 kfree(bss_mesh_cfg(bss)); 46 kfree(bss_mesh_cfg(bss));
203 kfree(bss);
204} 47}
205 48
206void ieee80211_rx_bss_put(struct ieee80211_local *local, 49void ieee80211_rx_bss_put(struct ieee80211_local *local,
207 struct ieee80211_bss *bss) 50 struct ieee80211_bss *bss)
208{ 51{
209 local_bh_disable(); 52 cfg80211_put_bss((struct cfg80211_bss *)bss);
210 if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) {
211 local_bh_enable();
212 return;
213 }
214
215 __ieee80211_rx_bss_hash_del(local, bss);
216 list_del(&bss->list);
217 spin_unlock_bh(&local->bss_lock);
218 ieee80211_rx_bss_free(bss);
219} 53}
220 54
221struct ieee80211_bss * 55struct ieee80211_bss *
@@ -228,7 +62,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
228 bool beacon) 62 bool beacon)
229{ 63{
230 struct ieee80211_bss *bss; 64 struct ieee80211_bss *bss;
231 int clen, freq = channel->center_freq; 65 int clen;
232 enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE; 66 enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE;
233 s32 signal = 0; 67 s32 signal = 0;
234 68
@@ -240,39 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
240 signal = (rx_status->signal * 100) / local->hw.max_signal; 74 signal = (rx_status->signal * 100) / local->hw.max_signal;
241 } 75 }
242 76
243 cfg80211_put_bss( 77 bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
244 cfg80211_inform_bss_frame(local->hw.wiphy, channel, 78 mgmt, len, signal, sigtype,
245 mgmt, len, signal, sigtype, 79 GFP_ATOMIC);
246 GFP_ATOMIC));
247 80
248#ifdef CONFIG_MAC80211_MESH 81 if (!bss)
249 if (elems->mesh_config) 82 return NULL;
250 bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, 83
251 elems->mesh_id_len, elems->mesh_config, freq); 84 bss->cbss.free_priv = ieee80211_rx_bss_free;
252 else
253#endif
254 bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq,
255 elems->ssid, elems->ssid_len);
256 if (!bss) {
257#ifdef CONFIG_MAC80211_MESH
258 if (elems->mesh_config)
259 bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id,
260 elems->mesh_id_len, elems->mesh_config,
261 elems->mesh_config_len, freq);
262 else
263#endif
264 bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq,
265 elems->ssid, elems->ssid_len);
266 if (!bss)
267 return NULL;
268 } else {
269#if 0
270 /* TODO: order by RSSI? */
271 spin_lock_bh(&local->bss_lock);
272 list_move_tail(&bss->list, &local->bss_list);
273 spin_unlock_bh(&local->bss_lock);
274#endif
275 }
276 85
277 /* save the ERP value so that it is available at association time */ 86 /* save the ERP value so that it is available at association time */
278 if (elems->erp_info && elems->erp_info_len >= 1) { 87 if (elems->erp_info && elems->erp_info_len >= 1) {
@@ -280,9 +89,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
280 bss->has_erp_value = 1; 89 bss->has_erp_value = 1;
281 } 90 }
282 91
283 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
284 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
285
286 if (elems->tim) { 92 if (elems->tim) {
287 struct ieee80211_tim_ie *tim_ie = 93 struct ieee80211_tim_ie *tim_ie =
288 (struct ieee80211_tim_ie *)elems->tim; 94 (struct ieee80211_tim_ie *)elems->tim;
@@ -311,34 +117,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
311 bss->supp_rates_len += clen; 117 bss->supp_rates_len += clen;
312 } 118 }
313 119
314 bss->band = rx_status->band;
315
316 bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
317 bss->last_update = jiffies;
318 bss->signal = rx_status->signal;
319 bss->noise = rx_status->noise;
320 bss->qual = rx_status->qual;
321 bss->wmm_used = elems->wmm_param || elems->wmm_info; 120 bss->wmm_used = elems->wmm_param || elems->wmm_info;
322 121
323 if (!beacon) 122 if (!beacon)
324 bss->last_probe_resp = jiffies; 123 bss->last_probe_resp = jiffies;
325 124
326 /*
327 * For probe responses, or if we don't have any information yet,
328 * use the IEs from the beacon.
329 */
330 if (!bss->ies || !beacon) {
331 if (bss->ies == NULL || bss->ies_len < elems->total_len) {
332 kfree(bss->ies);
333 bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
334 }
335 if (bss->ies) {
336 memcpy(bss->ies, elems->ie_start, elems->total_len);
337 bss->ies_len = elems->total_len;
338 } else
339 bss->ies_len = 0;
340 }
341
342 return bss; 125 return bss;
343} 126}
344 127
@@ -350,7 +133,7 @@ void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
350 133
351 bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len); 134 bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
352 if (bss) { 135 if (bss) {
353 atomic_dec(&bss->users); 136 cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
354 ieee80211_rx_bss_put(local, bss); 137 ieee80211_rx_bss_put(local, bss);
355 } 138 }
356} 139}
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 8d4ec2968f8f..47bb2aed2813 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -102,8 +102,9 @@ void ieee80211_chswitch_work(struct work_struct *work)
102 goto exit; 102 goto exit;
103 103
104 sdata->local->oper_channel = sdata->local->csa_channel; 104 sdata->local->oper_channel = sdata->local->csa_channel;
105 /* XXX: shouldn't really modify cfg80211-owned data! */
105 if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) 106 if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
106 bss->freq = sdata->local->oper_channel->center_freq; 107 bss->cbss.channel = sdata->local->oper_channel;
107 108
108 ieee80211_rx_bss_put(sdata->local, bss); 109 ieee80211_rx_bss_put(sdata->local, bss);
109exit: 110exit:
@@ -158,7 +159,9 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
158 IEEE80211_QUEUE_STOP_REASON_CSA); 159 IEEE80211_QUEUE_STOP_REASON_CSA);
159 ifsta->flags |= IEEE80211_STA_CSA_RECEIVED; 160 ifsta->flags |= IEEE80211_STA_CSA_RECEIVED;
160 mod_timer(&ifsta->chswitch_timer, 161 mod_timer(&ifsta->chswitch_timer,
161 jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); 162 jiffies +
163 msecs_to_jiffies(sw_elem->count *
164 bss->cbss.beacon_interval));
162 } 165 }
163} 166}
164 167