2 * cfg80211 scan result handling
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
6 #include <linux/kernel.h>
7 #include <linux/slab.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/wireless.h>
11 #include <linux/nl80211.h>
12 #include <linux/etherdevice.h>
14 #include <net/cfg80211.h>
15 #include <net/cfg80211-wext.h>
16 #include <net/iw_handler.h>
19 #include "wext-compat.h"
22 #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
24 static void bss_release(struct kref
*ref
)
26 struct cfg80211_bss_ies
*ies
;
27 struct cfg80211_internal_bss
*bss
;
29 bss
= container_of(ref
, struct cfg80211_internal_bss
, ref
);
31 if (WARN_ON(atomic_read(&bss
->hold
)))
34 ies
= (void *)rcu_access_pointer(bss
->pub
.beacon_ies
);
36 kfree_rcu(ies
, rcu_head
);
37 ies
= (void *)rcu_access_pointer(bss
->pub
.proberesp_ies
);
39 kfree_rcu(ies
, rcu_head
);
44 static void __cfg80211_unlink_bss(struct cfg80211_registered_device
*dev
,
45 struct cfg80211_internal_bss
*bss
)
47 lockdep_assert_held(&dev
->bss_lock
);
49 list_del_init(&bss
->list
);
50 rb_erase(&bss
->rbn
, &dev
->bss_tree
);
51 kref_put(&bss
->ref
, bss_release
);
54 static void __cfg80211_bss_expire(struct cfg80211_registered_device
*dev
,
55 unsigned long expire_time
)
57 struct cfg80211_internal_bss
*bss
, *tmp
;
60 lockdep_assert_held(&dev
->bss_lock
);
62 list_for_each_entry_safe(bss
, tmp
, &dev
->bss_list
, list
) {
63 if (atomic_read(&bss
->hold
))
65 if (!time_after(expire_time
, bss
->ts
))
68 __cfg80211_unlink_bss(dev
, bss
);
73 dev
->bss_generation
++;
76 void ___cfg80211_scan_done(struct cfg80211_registered_device
*rdev
, bool leak
)
78 struct cfg80211_scan_request
*request
;
79 struct wireless_dev
*wdev
;
80 #ifdef CONFIG_CFG80211_WEXT
81 union iwreq_data wrqu
;
84 ASSERT_RDEV_LOCK(rdev
);
86 request
= rdev
->scan_req
;
94 * This must be before sending the other events!
95 * Otherwise, wpa_supplicant gets completely confused with
99 cfg80211_sme_scan_done(wdev
->netdev
);
101 if (request
->aborted
) {
102 nl80211_send_scan_aborted(rdev
, wdev
);
104 if (request
->flags
& NL80211_SCAN_FLAG_FLUSH
) {
105 /* flush entries from previous scans */
106 spin_lock_bh(&rdev
->bss_lock
);
107 __cfg80211_bss_expire(rdev
, request
->scan_start
);
108 spin_unlock_bh(&rdev
->bss_lock
);
110 nl80211_send_scan_done(rdev
, wdev
);
113 #ifdef CONFIG_CFG80211_WEXT
114 if (wdev
->netdev
&& !request
->aborted
) {
115 memset(&wrqu
, 0, sizeof(wrqu
));
117 wireless_send_event(wdev
->netdev
, SIOCGIWSCAN
, &wrqu
, NULL
);
122 dev_put(wdev
->netdev
);
124 rdev
->scan_req
= NULL
;
127 * OK. If this is invoked with "leak" then we can't
128 * free this ... but we've cleaned it up anyway. The
129 * driver failed to call the scan_done callback, so
130 * all bets are off, it might still be trying to use
131 * the scan request or not ... if it accesses the dev
132 * in there (it shouldn't anyway) then it may crash.
138 void __cfg80211_scan_done(struct work_struct
*wk
)
140 struct cfg80211_registered_device
*rdev
;
142 rdev
= container_of(wk
, struct cfg80211_registered_device
,
145 cfg80211_lock_rdev(rdev
);
146 ___cfg80211_scan_done(rdev
, false);
147 cfg80211_unlock_rdev(rdev
);
150 void cfg80211_scan_done(struct cfg80211_scan_request
*request
, bool aborted
)
152 trace_cfg80211_scan_done(request
, aborted
);
153 WARN_ON(request
!= wiphy_to_dev(request
->wiphy
)->scan_req
);
155 request
->aborted
= aborted
;
156 queue_work(cfg80211_wq
, &wiphy_to_dev(request
->wiphy
)->scan_done_wk
);
158 EXPORT_SYMBOL(cfg80211_scan_done
);
160 void __cfg80211_sched_scan_results(struct work_struct
*wk
)
162 struct cfg80211_registered_device
*rdev
;
163 struct cfg80211_sched_scan_request
*request
;
165 rdev
= container_of(wk
, struct cfg80211_registered_device
,
166 sched_scan_results_wk
);
168 request
= rdev
->sched_scan_req
;
170 mutex_lock(&rdev
->sched_scan_mtx
);
172 /* we don't have sched_scan_req anymore if the scan is stopping */
174 if (request
->flags
& NL80211_SCAN_FLAG_FLUSH
) {
175 /* flush entries from previous scans */
176 spin_lock_bh(&rdev
->bss_lock
);
177 __cfg80211_bss_expire(rdev
, request
->scan_start
);
178 spin_unlock_bh(&rdev
->bss_lock
);
179 request
->scan_start
=
180 jiffies
+ msecs_to_jiffies(request
->interval
);
182 nl80211_send_sched_scan_results(rdev
, request
->dev
);
185 mutex_unlock(&rdev
->sched_scan_mtx
);
188 void cfg80211_sched_scan_results(struct wiphy
*wiphy
)
190 trace_cfg80211_sched_scan_results(wiphy
);
191 /* ignore if we're not scanning */
192 if (wiphy_to_dev(wiphy
)->sched_scan_req
)
193 queue_work(cfg80211_wq
,
194 &wiphy_to_dev(wiphy
)->sched_scan_results_wk
);
196 EXPORT_SYMBOL(cfg80211_sched_scan_results
);
198 void cfg80211_sched_scan_stopped(struct wiphy
*wiphy
)
200 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
202 trace_cfg80211_sched_scan_stopped(wiphy
);
204 mutex_lock(&rdev
->sched_scan_mtx
);
205 __cfg80211_stop_sched_scan(rdev
, true);
206 mutex_unlock(&rdev
->sched_scan_mtx
);
208 EXPORT_SYMBOL(cfg80211_sched_scan_stopped
);
210 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device
*rdev
,
211 bool driver_initiated
)
213 struct net_device
*dev
;
215 lockdep_assert_held(&rdev
->sched_scan_mtx
);
217 if (!rdev
->sched_scan_req
)
220 dev
= rdev
->sched_scan_req
->dev
;
222 if (!driver_initiated
) {
223 int err
= rdev_sched_scan_stop(rdev
, dev
);
228 nl80211_send_sched_scan(rdev
, dev
, NL80211_CMD_SCHED_SCAN_STOPPED
);
230 kfree(rdev
->sched_scan_req
);
231 rdev
->sched_scan_req
= NULL
;
236 void cfg80211_bss_age(struct cfg80211_registered_device
*dev
,
237 unsigned long age_secs
)
239 struct cfg80211_internal_bss
*bss
;
240 unsigned long age_jiffies
= msecs_to_jiffies(age_secs
* MSEC_PER_SEC
);
242 spin_lock_bh(&dev
->bss_lock
);
243 list_for_each_entry(bss
, &dev
->bss_list
, list
)
244 bss
->ts
-= age_jiffies
;
245 spin_unlock_bh(&dev
->bss_lock
);
248 void cfg80211_bss_expire(struct cfg80211_registered_device
*dev
)
250 __cfg80211_bss_expire(dev
, jiffies
- IEEE80211_SCAN_RESULT_EXPIRE
);
253 const u8
*cfg80211_find_ie(u8 eid
, const u8
*ies
, int len
)
255 while (len
> 2 && ies
[0] != eid
) {
261 if (len
< 2 + ies
[1])
265 EXPORT_SYMBOL(cfg80211_find_ie
);
267 const u8
*cfg80211_find_vendor_ie(unsigned int oui
, u8 oui_type
,
268 const u8
*ies
, int len
)
270 struct ieee80211_vendor_ie
*ie
;
271 const u8
*pos
= ies
, *end
= ies
+ len
;
275 pos
= cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC
, pos
,
280 if (end
- pos
< sizeof(*ie
))
283 ie
= (struct ieee80211_vendor_ie
*)pos
;
284 ie_oui
= ie
->oui
[0] << 16 | ie
->oui
[1] << 8 | ie
->oui
[2];
285 if (ie_oui
== oui
&& ie
->oui_type
== oui_type
)
292 EXPORT_SYMBOL(cfg80211_find_vendor_ie
);
294 static bool is_bss(struct cfg80211_bss
*a
, const u8
*bssid
,
295 const u8
*ssid
, size_t ssid_len
)
297 const struct cfg80211_bss_ies
*ies
;
300 if (bssid
&& !ether_addr_equal(a
->bssid
, bssid
))
306 ies
= rcu_access_pointer(a
->ies
);
309 ssidie
= cfg80211_find_ie(WLAN_EID_SSID
, ies
->data
, ies
->len
);
312 if (ssidie
[1] != ssid_len
)
314 return memcmp(ssidie
+ 2, ssid
, ssid_len
) == 0;
318 * enum bss_compare_mode - BSS compare mode
319 * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find)
320 * @BSS_CMP_HIDE_ZLEN: find hidden SSID with zero-length mode
321 * @BSS_CMP_HIDE_NUL: find hidden SSID with NUL-ed out mode
323 enum bss_compare_mode
{
329 static int cmp_bss(struct cfg80211_bss
*a
,
330 struct cfg80211_bss
*b
,
331 enum bss_compare_mode mode
)
333 const struct cfg80211_bss_ies
*a_ies
, *b_ies
;
334 const u8
*ie1
= NULL
;
335 const u8
*ie2
= NULL
;
338 if (a
->channel
!= b
->channel
)
339 return b
->channel
->center_freq
- a
->channel
->center_freq
;
341 a_ies
= rcu_access_pointer(a
->ies
);
344 b_ies
= rcu_access_pointer(b
->ies
);
348 if (WLAN_CAPABILITY_IS_STA_BSS(a
->capability
))
349 ie1
= cfg80211_find_ie(WLAN_EID_MESH_ID
,
350 a_ies
->data
, a_ies
->len
);
351 if (WLAN_CAPABILITY_IS_STA_BSS(b
->capability
))
352 ie2
= cfg80211_find_ie(WLAN_EID_MESH_ID
,
353 b_ies
->data
, b_ies
->len
);
357 if (ie1
[1] == ie2
[1])
358 mesh_id_cmp
= memcmp(ie1
+ 2, ie2
+ 2, ie1
[1]);
360 mesh_id_cmp
= ie2
[1] - ie1
[1];
362 ie1
= cfg80211_find_ie(WLAN_EID_MESH_CONFIG
,
363 a_ies
->data
, a_ies
->len
);
364 ie2
= cfg80211_find_ie(WLAN_EID_MESH_CONFIG
,
365 b_ies
->data
, b_ies
->len
);
369 if (ie1
[1] != ie2
[1])
370 return ie2
[1] - ie1
[1];
371 return memcmp(ie1
+ 2, ie2
+ 2, ie1
[1]);
376 * we can't use compare_ether_addr here since we need a < > operator.
377 * The binary return value of compare_ether_addr isn't enough
379 r
= memcmp(a
->bssid
, b
->bssid
, sizeof(a
->bssid
));
383 ie1
= cfg80211_find_ie(WLAN_EID_SSID
, a_ies
->data
, a_ies
->len
);
384 ie2
= cfg80211_find_ie(WLAN_EID_SSID
, b_ies
->data
, b_ies
->len
);
390 * Note that with "hide_ssid", the function returns a match if
391 * the already-present BSS ("b") is a hidden SSID beacon for
395 /* sort missing IE before (left of) present IE */
402 case BSS_CMP_HIDE_ZLEN
:
404 * In ZLEN mode we assume the BSS entry we're
405 * looking for has a zero-length SSID. So if
406 * the one we're looking at right now has that,
407 * return 0. Otherwise, return the difference
408 * in length, but since we're looking for the
409 * 0-length it's really equivalent to returning
410 * the length of the one we're looking at.
412 * No content comparison is needed as we assume
413 * the content length is zero.
416 case BSS_CMP_REGULAR
:
418 /* sort by length first, then by contents */
419 if (ie1
[1] != ie2
[1])
420 return ie2
[1] - ie1
[1];
421 return memcmp(ie1
+ 2, ie2
+ 2, ie1
[1]);
422 case BSS_CMP_HIDE_NUL
:
423 if (ie1
[1] != ie2
[1])
424 return ie2
[1] - ie1
[1];
425 /* this is equivalent to memcmp(zeroes, ie2 + 2, len) */
426 for (i
= 0; i
< ie2
[1]; i
++)
433 struct cfg80211_bss
*cfg80211_get_bss(struct wiphy
*wiphy
,
434 struct ieee80211_channel
*channel
,
436 const u8
*ssid
, size_t ssid_len
,
437 u16 capa_mask
, u16 capa_val
)
439 struct cfg80211_registered_device
*dev
= wiphy_to_dev(wiphy
);
440 struct cfg80211_internal_bss
*bss
, *res
= NULL
;
441 unsigned long now
= jiffies
;
443 trace_cfg80211_get_bss(wiphy
, channel
, bssid
, ssid
, ssid_len
, capa_mask
,
446 spin_lock_bh(&dev
->bss_lock
);
448 list_for_each_entry(bss
, &dev
->bss_list
, list
) {
449 if ((bss
->pub
.capability
& capa_mask
) != capa_val
)
451 if (channel
&& bss
->pub
.channel
!= channel
)
453 /* Don't get expired BSS structs */
454 if (time_after(now
, bss
->ts
+ IEEE80211_SCAN_RESULT_EXPIRE
) &&
455 !atomic_read(&bss
->hold
))
457 if (is_bss(&bss
->pub
, bssid
, ssid
, ssid_len
)) {
464 spin_unlock_bh(&dev
->bss_lock
);
467 trace_cfg80211_return_bss(&res
->pub
);
470 EXPORT_SYMBOL(cfg80211_get_bss
);
472 static void rb_insert_bss(struct cfg80211_registered_device
*dev
,
473 struct cfg80211_internal_bss
*bss
)
475 struct rb_node
**p
= &dev
->bss_tree
.rb_node
;
476 struct rb_node
*parent
= NULL
;
477 struct cfg80211_internal_bss
*tbss
;
482 tbss
= rb_entry(parent
, struct cfg80211_internal_bss
, rbn
);
484 cmp
= cmp_bss(&bss
->pub
, &tbss
->pub
, BSS_CMP_REGULAR
);
487 /* will sort of leak this BSS */
497 rb_link_node(&bss
->rbn
, parent
, p
);
498 rb_insert_color(&bss
->rbn
, &dev
->bss_tree
);
501 static struct cfg80211_internal_bss
*
502 rb_find_bss(struct cfg80211_registered_device
*dev
,
503 struct cfg80211_internal_bss
*res
,
504 enum bss_compare_mode mode
)
506 struct rb_node
*n
= dev
->bss_tree
.rb_node
;
507 struct cfg80211_internal_bss
*bss
;
511 bss
= rb_entry(n
, struct cfg80211_internal_bss
, rbn
);
512 r
= cmp_bss(&res
->pub
, &bss
->pub
, mode
);
526 copy_hidden_ies(struct cfg80211_internal_bss
*res
,
527 struct cfg80211_internal_bss
*hidden
)
529 const struct cfg80211_bss_ies
*ies
;
531 if (rcu_access_pointer(res
->pub
.beacon_ies
))
534 ies
= rcu_access_pointer(hidden
->pub
.beacon_ies
);
538 ies
= kmemdup(ies
, sizeof(*ies
) + ies
->len
, GFP_ATOMIC
);
541 rcu_assign_pointer(res
->pub
.beacon_ies
, ies
);
544 static struct cfg80211_internal_bss
*
545 cfg80211_bss_update(struct cfg80211_registered_device
*dev
,
546 struct cfg80211_internal_bss
*tmp
)
548 struct cfg80211_internal_bss
*found
= NULL
;
550 if (WARN_ON(!tmp
->pub
.channel
))
555 spin_lock_bh(&dev
->bss_lock
);
557 if (WARN_ON(!rcu_access_pointer(tmp
->pub
.ies
))) {
558 spin_unlock_bh(&dev
->bss_lock
);
562 found
= rb_find_bss(dev
, tmp
, BSS_CMP_REGULAR
);
565 found
->pub
.beacon_interval
= tmp
->pub
.beacon_interval
;
566 found
->pub
.tsf
= tmp
->pub
.tsf
;
567 found
->pub
.signal
= tmp
->pub
.signal
;
568 found
->pub
.capability
= tmp
->pub
.capability
;
572 if (rcu_access_pointer(tmp
->pub
.proberesp_ies
)) {
573 const struct cfg80211_bss_ies
*old
;
575 old
= rcu_access_pointer(found
->pub
.proberesp_ies
);
577 rcu_assign_pointer(found
->pub
.proberesp_ies
,
578 tmp
->pub
.proberesp_ies
);
579 /* Override possible earlier Beacon frame IEs */
580 rcu_assign_pointer(found
->pub
.ies
,
581 tmp
->pub
.proberesp_ies
);
583 kfree_rcu((struct cfg80211_bss_ies
*)old
,
585 } else if (rcu_access_pointer(tmp
->pub
.beacon_ies
)) {
586 const struct cfg80211_bss_ies
*old
, *ies
;
588 old
= rcu_access_pointer(found
->pub
.beacon_ies
);
589 ies
= rcu_access_pointer(found
->pub
.ies
);
591 rcu_assign_pointer(found
->pub
.beacon_ies
,
592 tmp
->pub
.beacon_ies
);
594 /* Override IEs if they were from a beacon before */
596 rcu_assign_pointer(found
->pub
.ies
,
597 tmp
->pub
.beacon_ies
);
600 kfree_rcu((struct cfg80211_bss_ies
*)old
,
604 struct cfg80211_internal_bss
*new;
605 struct cfg80211_internal_bss
*hidden
;
606 struct cfg80211_bss_ies
*ies
;
608 /* First check if the beacon is a probe response from
609 * a hidden bss. If so, copy beacon ies (with nullified
610 * ssid) into the probe response bss entry (with real ssid).
611 * It is required basically for PSM implementation
612 * (probe responses do not contain tim ie) */
614 /* TODO: The code is not trying to update existing probe
615 * response bss entries when beacon ies are
616 * getting changed. */
617 hidden
= rb_find_bss(dev
, tmp
, BSS_CMP_HIDE_ZLEN
);
619 copy_hidden_ies(tmp
, hidden
);
621 hidden
= rb_find_bss(dev
, tmp
, BSS_CMP_HIDE_NUL
);
623 copy_hidden_ies(tmp
, hidden
);
627 * create a copy -- the "res" variable that is passed in
628 * is allocated on the stack since it's not needed in the
629 * more common case of an update
631 new = kzalloc(sizeof(*new) + dev
->wiphy
.bss_priv_size
,
634 ies
= (void *)rcu_dereference(tmp
->pub
.beacon_ies
);
636 kfree_rcu(ies
, rcu_head
);
637 ies
= (void *)rcu_dereference(tmp
->pub
.proberesp_ies
);
639 kfree_rcu(ies
, rcu_head
);
640 spin_unlock_bh(&dev
->bss_lock
);
643 memcpy(new, tmp
, sizeof(*new));
644 kref_init(&new->ref
);
645 list_add_tail(&new->list
, &dev
->bss_list
);
646 rb_insert_bss(dev
, new);
650 dev
->bss_generation
++;
651 spin_unlock_bh(&dev
->bss_lock
);
653 kref_get(&found
->ref
);
657 static struct ieee80211_channel
*
658 cfg80211_get_bss_channel(struct wiphy
*wiphy
, const u8
*ie
, size_t ielen
,
659 struct ieee80211_channel
*channel
)
663 int channel_number
= -1;
665 tmp
= cfg80211_find_ie(WLAN_EID_DS_PARAMS
, ie
, ielen
);
666 if (tmp
&& tmp
[1] == 1) {
667 channel_number
= tmp
[2];
669 tmp
= cfg80211_find_ie(WLAN_EID_HT_OPERATION
, ie
, ielen
);
670 if (tmp
&& tmp
[1] >= sizeof(struct ieee80211_ht_operation
)) {
671 struct ieee80211_ht_operation
*htop
= (void *)(tmp
+ 2);
673 channel_number
= htop
->primary_chan
;
677 if (channel_number
< 0)
680 freq
= ieee80211_channel_to_frequency(channel_number
, channel
->band
);
681 channel
= ieee80211_get_channel(wiphy
, freq
);
684 if (channel
->flags
& IEEE80211_CHAN_DISABLED
)
690 cfg80211_inform_bss(struct wiphy
*wiphy
,
691 struct ieee80211_channel
*channel
,
692 const u8
*bssid
, u64 tsf
, u16 capability
,
693 u16 beacon_interval
, const u8
*ie
, size_t ielen
,
694 s32 signal
, gfp_t gfp
)
696 struct cfg80211_bss_ies
*ies
;
697 struct cfg80211_internal_bss tmp
= {}, *res
;
702 if (WARN_ON(wiphy
->signal_type
== CFG80211_SIGNAL_TYPE_UNSPEC
&&
703 (signal
< 0 || signal
> 100)))
706 channel
= cfg80211_get_bss_channel(wiphy
, ie
, ielen
, channel
);
710 memcpy(tmp
.pub
.bssid
, bssid
, ETH_ALEN
);
711 tmp
.pub
.channel
= channel
;
712 tmp
.pub
.signal
= signal
;
714 tmp
.pub
.beacon_interval
= beacon_interval
;
715 tmp
.pub
.capability
= capability
;
717 * Since we do not know here whether the IEs are from a Beacon or Probe
718 * Response frame, we need to pick one of the options and only use it
719 * with the driver that does not provide the full Beacon/Probe Response
720 * frame. Use Beacon frame pointer to avoid indicating that this should
721 * override the IEs pointer should we have received an earlier
722 * indication of Probe Response data.
724 ies
= kmalloc(sizeof(*ies
) + ielen
, gfp
);
728 memcpy(ies
->data
, ie
, ielen
);
730 rcu_assign_pointer(tmp
.pub
.beacon_ies
, ies
);
731 rcu_assign_pointer(tmp
.pub
.ies
, ies
);
733 res
= cfg80211_bss_update(wiphy_to_dev(wiphy
), &tmp
);
737 if (res
->pub
.capability
& WLAN_CAPABILITY_ESS
)
738 regulatory_hint_found_beacon(wiphy
, channel
, gfp
);
740 trace_cfg80211_return_bss(&res
->pub
);
741 /* cfg80211_bss_update gives us a referenced result */
744 EXPORT_SYMBOL(cfg80211_inform_bss
);
746 struct cfg80211_bss
*
747 cfg80211_inform_bss_frame(struct wiphy
*wiphy
,
748 struct ieee80211_channel
*channel
,
749 struct ieee80211_mgmt
*mgmt
, size_t len
,
750 s32 signal
, gfp_t gfp
)
752 struct cfg80211_internal_bss tmp
= {}, *res
;
753 struct cfg80211_bss_ies
*ies
;
754 size_t ielen
= len
- offsetof(struct ieee80211_mgmt
,
755 u
.probe_resp
.variable
);
757 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
) !=
758 offsetof(struct ieee80211_mgmt
, u
.beacon
.variable
));
760 trace_cfg80211_inform_bss_frame(wiphy
, channel
, mgmt
, len
, signal
);
768 if (WARN_ON(wiphy
->signal_type
== CFG80211_SIGNAL_TYPE_UNSPEC
&&
769 (signal
< 0 || signal
> 100)))
772 if (WARN_ON(len
< offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
)))
775 channel
= cfg80211_get_bss_channel(wiphy
, mgmt
->u
.beacon
.variable
,
780 ies
= kmalloc(sizeof(*ies
) + ielen
, gfp
);
784 memcpy(ies
->data
, mgmt
->u
.probe_resp
.variable
, ielen
);
786 if (ieee80211_is_probe_resp(mgmt
->frame_control
))
787 rcu_assign_pointer(tmp
.pub
.proberesp_ies
, ies
);
789 rcu_assign_pointer(tmp
.pub
.beacon_ies
, ies
);
790 rcu_assign_pointer(tmp
.pub
.ies
, ies
);
792 memcpy(tmp
.pub
.bssid
, mgmt
->bssid
, ETH_ALEN
);
793 tmp
.pub
.channel
= channel
;
794 tmp
.pub
.signal
= signal
;
795 tmp
.pub
.tsf
= le64_to_cpu(mgmt
->u
.probe_resp
.timestamp
);
796 tmp
.pub
.beacon_interval
= le16_to_cpu(mgmt
->u
.probe_resp
.beacon_int
);
797 tmp
.pub
.capability
= le16_to_cpu(mgmt
->u
.probe_resp
.capab_info
);
799 res
= cfg80211_bss_update(wiphy_to_dev(wiphy
), &tmp
);
803 if (res
->pub
.capability
& WLAN_CAPABILITY_ESS
)
804 regulatory_hint_found_beacon(wiphy
, channel
, gfp
);
806 trace_cfg80211_return_bss(&res
->pub
);
807 /* cfg80211_bss_update gives us a referenced result */
810 EXPORT_SYMBOL(cfg80211_inform_bss_frame
);
812 void cfg80211_ref_bss(struct cfg80211_bss
*pub
)
814 struct cfg80211_internal_bss
*bss
;
819 bss
= container_of(pub
, struct cfg80211_internal_bss
, pub
);
822 EXPORT_SYMBOL(cfg80211_ref_bss
);
824 void cfg80211_put_bss(struct cfg80211_bss
*pub
)
826 struct cfg80211_internal_bss
*bss
;
831 bss
= container_of(pub
, struct cfg80211_internal_bss
, pub
);
832 kref_put(&bss
->ref
, bss_release
);
834 EXPORT_SYMBOL(cfg80211_put_bss
);
836 void cfg80211_unlink_bss(struct wiphy
*wiphy
, struct cfg80211_bss
*pub
)
838 struct cfg80211_registered_device
*dev
= wiphy_to_dev(wiphy
);
839 struct cfg80211_internal_bss
*bss
;
844 bss
= container_of(pub
, struct cfg80211_internal_bss
, pub
);
846 spin_lock_bh(&dev
->bss_lock
);
847 if (!list_empty(&bss
->list
)) {
848 __cfg80211_unlink_bss(dev
, bss
);
849 dev
->bss_generation
++;
851 spin_unlock_bh(&dev
->bss_lock
);
853 EXPORT_SYMBOL(cfg80211_unlink_bss
);
855 #ifdef CONFIG_CFG80211_WEXT
856 int cfg80211_wext_siwscan(struct net_device
*dev
,
857 struct iw_request_info
*info
,
858 union iwreq_data
*wrqu
, char *extra
)
860 struct cfg80211_registered_device
*rdev
;
862 struct iw_scan_req
*wreq
= NULL
;
863 struct cfg80211_scan_request
*creq
= NULL
;
864 int i
, err
, n_channels
= 0;
865 enum ieee80211_band band
;
867 if (!netif_running(dev
))
870 if (wrqu
->data
.length
== sizeof(struct iw_scan_req
))
871 wreq
= (struct iw_scan_req
*)extra
;
873 rdev
= cfg80211_get_dev_from_ifindex(dev_net(dev
), dev
->ifindex
);
876 return PTR_ERR(rdev
);
878 if (rdev
->scan_req
) {
883 wiphy
= &rdev
->wiphy
;
885 /* Determine number of channels, needed to allocate creq */
886 if (wreq
&& wreq
->num_channels
)
887 n_channels
= wreq
->num_channels
;
889 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++)
890 if (wiphy
->bands
[band
])
891 n_channels
+= wiphy
->bands
[band
]->n_channels
;
894 creq
= kzalloc(sizeof(*creq
) + sizeof(struct cfg80211_ssid
) +
895 n_channels
* sizeof(void *),
903 creq
->wdev
= dev
->ieee80211_ptr
;
904 /* SSIDs come after channels */
905 creq
->ssids
= (void *)&creq
->channels
[n_channels
];
906 creq
->n_channels
= n_channels
;
908 creq
->scan_start
= jiffies
;
910 /* translate "Scan on frequencies" request */
912 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
915 if (!wiphy
->bands
[band
])
918 for (j
= 0; j
< wiphy
->bands
[band
]->n_channels
; j
++) {
919 /* ignore disabled channels */
920 if (wiphy
->bands
[band
]->channels
[j
].flags
&
921 IEEE80211_CHAN_DISABLED
)
924 /* If we have a wireless request structure and the
925 * wireless request specifies frequencies, then search
926 * for the matching hardware channel.
928 if (wreq
&& wreq
->num_channels
) {
930 int wiphy_freq
= wiphy
->bands
[band
]->channels
[j
].center_freq
;
931 for (k
= 0; k
< wreq
->num_channels
; k
++) {
932 int wext_freq
= cfg80211_wext_freq(wiphy
, &wreq
->channel_list
[k
]);
933 if (wext_freq
== wiphy_freq
)
934 goto wext_freq_found
;
936 goto wext_freq_not_found
;
940 creq
->channels
[i
] = &wiphy
->bands
[band
]->channels
[j
];
942 wext_freq_not_found
: ;
945 /* No channels found? */
951 /* Set real number of channels specified in creq->channels[] */
952 creq
->n_channels
= i
;
954 /* translate "Scan for SSID" request */
956 if (wrqu
->data
.flags
& IW_SCAN_THIS_ESSID
) {
957 if (wreq
->essid_len
> IEEE80211_MAX_SSID_LEN
) {
961 memcpy(creq
->ssids
[0].ssid
, wreq
->essid
, wreq
->essid_len
);
962 creq
->ssids
[0].ssid_len
= wreq
->essid_len
;
964 if (wreq
->scan_type
== IW_SCAN_TYPE_PASSIVE
)
968 for (i
= 0; i
< IEEE80211_NUM_BANDS
; i
++)
970 creq
->rates
[i
] = (1 << wiphy
->bands
[i
]->n_bitrates
) - 1;
972 rdev
->scan_req
= creq
;
973 err
= rdev_scan(rdev
, creq
);
975 rdev
->scan_req
= NULL
;
976 /* creq will be freed below */
978 nl80211_send_scan_start(rdev
, dev
->ieee80211_ptr
);
979 /* creq now owned by driver */
985 cfg80211_unlock_rdev(rdev
);
988 EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan
);
990 static void ieee80211_scan_add_ies(struct iw_request_info
*info
,
991 const struct cfg80211_bss_ies
*ies
,
992 char **current_ev
, char *end_buf
)
994 const u8
*pos
, *end
, *next
;
1001 * If needed, fragment the IEs buffer (at IE boundaries) into short
1002 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
1005 end
= pos
+ ies
->len
;
1007 while (end
- pos
> IW_GENERIC_IE_MAX
) {
1008 next
= pos
+ 2 + pos
[1];
1009 while (next
+ 2 + next
[1] - pos
< IW_GENERIC_IE_MAX
)
1010 next
= next
+ 2 + next
[1];
1012 memset(&iwe
, 0, sizeof(iwe
));
1013 iwe
.cmd
= IWEVGENIE
;
1014 iwe
.u
.data
.length
= next
- pos
;
1015 *current_ev
= iwe_stream_add_point(info
, *current_ev
,
1023 memset(&iwe
, 0, sizeof(iwe
));
1024 iwe
.cmd
= IWEVGENIE
;
1025 iwe
.u
.data
.length
= end
- pos
;
1026 *current_ev
= iwe_stream_add_point(info
, *current_ev
,
1032 static inline unsigned int elapsed_jiffies_msecs(unsigned long start
)
1034 unsigned long end
= jiffies
;
1037 return jiffies_to_msecs(end
- start
);
1039 return jiffies_to_msecs(end
+ (MAX_JIFFY_OFFSET
- start
) + 1);
1043 ieee80211_bss(struct wiphy
*wiphy
, struct iw_request_info
*info
,
1044 struct cfg80211_internal_bss
*bss
, char *current_ev
,
1047 const struct cfg80211_bss_ies
*ies
;
1048 struct iw_event iwe
;
1052 bool ismesh
= false;
1054 memset(&iwe
, 0, sizeof(iwe
));
1055 iwe
.cmd
= SIOCGIWAP
;
1056 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
1057 memcpy(iwe
.u
.ap_addr
.sa_data
, bss
->pub
.bssid
, ETH_ALEN
);
1058 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
,
1061 memset(&iwe
, 0, sizeof(iwe
));
1062 iwe
.cmd
= SIOCGIWFREQ
;
1063 iwe
.u
.freq
.m
= ieee80211_frequency_to_channel(bss
->pub
.channel
->center_freq
);
1065 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
,
1068 memset(&iwe
, 0, sizeof(iwe
));
1069 iwe
.cmd
= SIOCGIWFREQ
;
1070 iwe
.u
.freq
.m
= bss
->pub
.channel
->center_freq
;
1072 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
,
1075 if (wiphy
->signal_type
!= CFG80211_SIGNAL_TYPE_NONE
) {
1076 memset(&iwe
, 0, sizeof(iwe
));
1078 iwe
.u
.qual
.updated
= IW_QUAL_LEVEL_UPDATED
|
1079 IW_QUAL_NOISE_INVALID
|
1080 IW_QUAL_QUAL_UPDATED
;
1081 switch (wiphy
->signal_type
) {
1082 case CFG80211_SIGNAL_TYPE_MBM
:
1083 sig
= bss
->pub
.signal
/ 100;
1084 iwe
.u
.qual
.level
= sig
;
1085 iwe
.u
.qual
.updated
|= IW_QUAL_DBM
;
1086 if (sig
< -110) /* rather bad */
1088 else if (sig
> -40) /* perfect */
1090 /* will give a range of 0 .. 70 */
1091 iwe
.u
.qual
.qual
= sig
+ 110;
1093 case CFG80211_SIGNAL_TYPE_UNSPEC
:
1094 iwe
.u
.qual
.level
= bss
->pub
.signal
;
1095 /* will give range 0 .. 100 */
1096 iwe
.u
.qual
.qual
= bss
->pub
.signal
;
1102 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
,
1103 &iwe
, IW_EV_QUAL_LEN
);
1106 memset(&iwe
, 0, sizeof(iwe
));
1107 iwe
.cmd
= SIOCGIWENCODE
;
1108 if (bss
->pub
.capability
& WLAN_CAPABILITY_PRIVACY
)
1109 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
1111 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
1112 iwe
.u
.data
.length
= 0;
1113 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
,
1117 ies
= rcu_dereference(bss
->pub
.ies
);
1126 while (ies
&& rem
>= 2) {
1128 if (ie
[1] > rem
- 2)
1133 memset(&iwe
, 0, sizeof(iwe
));
1134 iwe
.cmd
= SIOCGIWESSID
;
1135 iwe
.u
.data
.length
= ie
[1];
1136 iwe
.u
.data
.flags
= 1;
1137 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
,
1138 &iwe
, (u8
*)ie
+ 2);
1140 case WLAN_EID_MESH_ID
:
1141 memset(&iwe
, 0, sizeof(iwe
));
1142 iwe
.cmd
= SIOCGIWESSID
;
1143 iwe
.u
.data
.length
= ie
[1];
1144 iwe
.u
.data
.flags
= 1;
1145 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
,
1146 &iwe
, (u8
*)ie
+ 2);
1148 case WLAN_EID_MESH_CONFIG
:
1150 if (ie
[1] != sizeof(struct ieee80211_meshconf_ie
))
1152 buf
= kmalloc(50, GFP_ATOMIC
);
1156 memset(&iwe
, 0, sizeof(iwe
));
1157 iwe
.cmd
= IWEVCUSTOM
;
1158 sprintf(buf
, "Mesh Network Path Selection Protocol ID: "
1160 iwe
.u
.data
.length
= strlen(buf
);
1161 current_ev
= iwe_stream_add_point(info
, current_ev
,
1164 sprintf(buf
, "Path Selection Metric ID: 0x%02X",
1166 iwe
.u
.data
.length
= strlen(buf
);
1167 current_ev
= iwe_stream_add_point(info
, current_ev
,
1170 sprintf(buf
, "Congestion Control Mode ID: 0x%02X",
1172 iwe
.u
.data
.length
= strlen(buf
);
1173 current_ev
= iwe_stream_add_point(info
, current_ev
,
1176 sprintf(buf
, "Synchronization ID: 0x%02X", cfg
[3]);
1177 iwe
.u
.data
.length
= strlen(buf
);
1178 current_ev
= iwe_stream_add_point(info
, current_ev
,
1181 sprintf(buf
, "Authentication ID: 0x%02X", cfg
[4]);
1182 iwe
.u
.data
.length
= strlen(buf
);
1183 current_ev
= iwe_stream_add_point(info
, current_ev
,
1186 sprintf(buf
, "Formation Info: 0x%02X", cfg
[5]);
1187 iwe
.u
.data
.length
= strlen(buf
);
1188 current_ev
= iwe_stream_add_point(info
, current_ev
,
1191 sprintf(buf
, "Capabilities: 0x%02X", cfg
[6]);
1192 iwe
.u
.data
.length
= strlen(buf
);
1193 current_ev
= iwe_stream_add_point(info
, current_ev
,
1198 case WLAN_EID_SUPP_RATES
:
1199 case WLAN_EID_EXT_SUPP_RATES
:
1200 /* display all supported rates in readable format */
1201 p
= current_ev
+ iwe_stream_lcp_len(info
);
1203 memset(&iwe
, 0, sizeof(iwe
));
1204 iwe
.cmd
= SIOCGIWRATE
;
1205 /* Those two flags are ignored... */
1206 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
1208 for (i
= 0; i
< ie
[1]; i
++) {
1209 iwe
.u
.bitrate
.value
=
1210 ((ie
[i
+ 2] & 0x7f) * 500000);
1211 p
= iwe_stream_add_value(info
, current_ev
, p
,
1212 end_buf
, &iwe
, IW_EV_PARAM_LEN
);
1221 if (bss
->pub
.capability
& (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
) ||
1223 memset(&iwe
, 0, sizeof(iwe
));
1224 iwe
.cmd
= SIOCGIWMODE
;
1226 iwe
.u
.mode
= IW_MODE_MESH
;
1227 else if (bss
->pub
.capability
& WLAN_CAPABILITY_ESS
)
1228 iwe
.u
.mode
= IW_MODE_MASTER
;
1230 iwe
.u
.mode
= IW_MODE_ADHOC
;
1231 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
,
1232 &iwe
, IW_EV_UINT_LEN
);
1235 buf
= kmalloc(30, GFP_ATOMIC
);
1237 memset(&iwe
, 0, sizeof(iwe
));
1238 iwe
.cmd
= IWEVCUSTOM
;
1239 sprintf(buf
, "tsf=%016llx", (unsigned long long)(bss
->pub
.tsf
));
1240 iwe
.u
.data
.length
= strlen(buf
);
1241 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
,
1243 memset(&iwe
, 0, sizeof(iwe
));
1244 iwe
.cmd
= IWEVCUSTOM
;
1245 sprintf(buf
, " Last beacon: %ums ago",
1246 elapsed_jiffies_msecs(bss
->ts
));
1247 iwe
.u
.data
.length
= strlen(buf
);
1248 current_ev
= iwe_stream_add_point(info
, current_ev
,
1249 end_buf
, &iwe
, buf
);
1253 ieee80211_scan_add_ies(info
, ies
, ¤t_ev
, end_buf
);
1260 static int ieee80211_scan_results(struct cfg80211_registered_device
*dev
,
1261 struct iw_request_info
*info
,
1262 char *buf
, size_t len
)
1264 char *current_ev
= buf
;
1265 char *end_buf
= buf
+ len
;
1266 struct cfg80211_internal_bss
*bss
;
1268 spin_lock_bh(&dev
->bss_lock
);
1269 cfg80211_bss_expire(dev
);
1271 list_for_each_entry(bss
, &dev
->bss_list
, list
) {
1272 if (buf
+ len
- current_ev
<= IW_EV_ADDR_LEN
) {
1273 spin_unlock_bh(&dev
->bss_lock
);
1276 current_ev
= ieee80211_bss(&dev
->wiphy
, info
, bss
,
1277 current_ev
, end_buf
);
1279 spin_unlock_bh(&dev
->bss_lock
);
1280 return current_ev
- buf
;
1284 int cfg80211_wext_giwscan(struct net_device
*dev
,
1285 struct iw_request_info
*info
,
1286 struct iw_point
*data
, char *extra
)
1288 struct cfg80211_registered_device
*rdev
;
1291 if (!netif_running(dev
))
1294 rdev
= cfg80211_get_dev_from_ifindex(dev_net(dev
), dev
->ifindex
);
1297 return PTR_ERR(rdev
);
1299 if (rdev
->scan_req
) {
1304 res
= ieee80211_scan_results(rdev
, info
, extra
, data
->length
);
1312 cfg80211_unlock_rdev(rdev
);
1315 EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan
);