• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/wireless/
1/*
2 * cfg80211 scan result handling
3 *
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 */
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>
13#include <net/arp.h>
14#include <net/cfg80211.h>
15#include <net/iw_handler.h>
16#include "core.h"
17#include "nl80211.h"
18#include "wext-compat.h"
19
20#define IEEE80211_SCAN_RESULT_EXPIRE	(15 * HZ)
21
22void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
23{
24	struct cfg80211_scan_request *request;
25	struct net_device *dev;
26#ifdef CONFIG_CFG80211_WEXT
27	union iwreq_data wrqu;
28#endif
29
30	ASSERT_RDEV_LOCK(rdev);
31
32	request = rdev->scan_req;
33
34	if (!request)
35		return;
36
37	dev = request->dev;
38
39	/*
40	 * This must be before sending the other events!
41	 * Otherwise, wpa_supplicant gets completely confused with
42	 * wext events.
43	 */
44	cfg80211_sme_scan_done(dev);
45
46	if (request->aborted)
47		nl80211_send_scan_aborted(rdev, dev);
48	else
49		nl80211_send_scan_done(rdev, dev);
50
51#ifdef CONFIG_CFG80211_WEXT
52	if (!request->aborted) {
53		memset(&wrqu, 0, sizeof(wrqu));
54
55		wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
56	}
57#endif
58
59	dev_put(dev);
60
61	rdev->scan_req = NULL;
62
63	/*
64	 * OK. If this is invoked with "leak" then we can't
65	 * free this ... but we've cleaned it up anyway. The
66	 * driver failed to call the scan_done callback, so
67	 * all bets are off, it might still be trying to use
68	 * the scan request or not ... if it accesses the dev
69	 * in there (it shouldn't anyway) then it may crash.
70	 */
71	if (!leak)
72		kfree(request);
73}
74
75void __cfg80211_scan_done(struct work_struct *wk)
76{
77	struct cfg80211_registered_device *rdev;
78
79	rdev = container_of(wk, struct cfg80211_registered_device,
80			    scan_done_wk);
81
82	cfg80211_lock_rdev(rdev);
83	___cfg80211_scan_done(rdev, false);
84	cfg80211_unlock_rdev(rdev);
85}
86
87void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
88{
89	WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
90
91	request->aborted = aborted;
92	queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
93}
94EXPORT_SYMBOL(cfg80211_scan_done);
95
96static void bss_release(struct kref *ref)
97{
98	struct cfg80211_internal_bss *bss;
99
100	bss = container_of(ref, struct cfg80211_internal_bss, ref);
101	if (bss->pub.free_priv)
102		bss->pub.free_priv(&bss->pub);
103
104	if (bss->beacon_ies_allocated)
105		kfree(bss->pub.beacon_ies);
106	if (bss->proberesp_ies_allocated)
107		kfree(bss->pub.proberesp_ies);
108
109	BUG_ON(atomic_read(&bss->hold));
110
111	kfree(bss);
112}
113
114/* must hold dev->bss_lock! */
115void cfg80211_bss_age(struct cfg80211_registered_device *dev,
116                      unsigned long age_secs)
117{
118	struct cfg80211_internal_bss *bss;
119	unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
120
121	list_for_each_entry(bss, &dev->bss_list, list) {
122		bss->ts -= age_jiffies;
123	}
124}
125
126/* must hold dev->bss_lock! */
127void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
128{
129	struct cfg80211_internal_bss *bss, *tmp;
130	bool expired = false;
131
132	list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
133		if (atomic_read(&bss->hold))
134			continue;
135		if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
136			continue;
137		list_del(&bss->list);
138		rb_erase(&bss->rbn, &dev->bss_tree);
139		kref_put(&bss->ref, bss_release);
140		expired = true;
141	}
142
143	if (expired)
144		dev->bss_generation++;
145}
146
147const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
148{
149	while (len > 2 && ies[0] != eid) {
150		len -= ies[1] + 2;
151		ies += ies[1] + 2;
152	}
153	if (len < 2)
154		return NULL;
155	if (len < 2 + ies[1])
156		return NULL;
157	return ies;
158}
159EXPORT_SYMBOL(cfg80211_find_ie);
160
161static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
162{
163	const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
164	const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
165	int r;
166
167	if (!ie1 && !ie2)
168		return 0;
169	if (!ie1 || !ie2)
170		return -1;
171
172	r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
173	if (r == 0 && ie1[1] != ie2[1])
174		return ie2[1] - ie1[1];
175	return r;
176}
177
178static bool is_bss(struct cfg80211_bss *a,
179		   const u8 *bssid,
180		   const u8 *ssid, size_t ssid_len)
181{
182	const u8 *ssidie;
183
184	if (bssid && compare_ether_addr(a->bssid, bssid))
185		return false;
186
187	if (!ssid)
188		return true;
189
190	ssidie = cfg80211_find_ie(WLAN_EID_SSID,
191				  a->information_elements,
192				  a->len_information_elements);
193	if (!ssidie)
194		return false;
195	if (ssidie[1] != ssid_len)
196		return false;
197	return memcmp(ssidie + 2, ssid, ssid_len) == 0;
198}
199
200static bool is_mesh(struct cfg80211_bss *a,
201		    const u8 *meshid, size_t meshidlen,
202		    const u8 *meshcfg)
203{
204	const u8 *ie;
205
206	if (!is_zero_ether_addr(a->bssid))
207		return false;
208
209	ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
210			      a->information_elements,
211			      a->len_information_elements);
212	if (!ie)
213		return false;
214	if (ie[1] != meshidlen)
215		return false;
216	if (memcmp(ie + 2, meshid, meshidlen))
217		return false;
218
219	ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
220			      a->information_elements,
221			      a->len_information_elements);
222	if (!ie)
223		return false;
224	if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
225		return false;
226
227	/*
228	 * Ignore mesh capability (last two bytes of the IE) when
229	 * comparing since that may differ between stations taking
230	 * part in the same mesh.
231	 */
232	return memcmp(ie + 2, meshcfg,
233	    sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
234}
235
236static int cmp_bss(struct cfg80211_bss *a,
237		   struct cfg80211_bss *b)
238{
239	int r;
240
241	if (a->channel != b->channel)
242		return b->channel->center_freq - a->channel->center_freq;
243
244	r = memcmp(a->bssid, b->bssid, ETH_ALEN);
245	if (r)
246		return r;
247
248	if (is_zero_ether_addr(a->bssid)) {
249		r = cmp_ies(WLAN_EID_MESH_ID,
250			    a->information_elements,
251			    a->len_information_elements,
252			    b->information_elements,
253			    b->len_information_elements);
254		if (r)
255			return r;
256		return cmp_ies(WLAN_EID_MESH_CONFIG,
257			       a->information_elements,
258			       a->len_information_elements,
259			       b->information_elements,
260			       b->len_information_elements);
261	}
262
263	return cmp_ies(WLAN_EID_SSID,
264		       a->information_elements,
265		       a->len_information_elements,
266		       b->information_elements,
267		       b->len_information_elements);
268}
269
270struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
271				      struct ieee80211_channel *channel,
272				      const u8 *bssid,
273				      const u8 *ssid, size_t ssid_len,
274				      u16 capa_mask, u16 capa_val)
275{
276	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
277	struct cfg80211_internal_bss *bss, *res = NULL;
278	unsigned long now = jiffies;
279
280	spin_lock_bh(&dev->bss_lock);
281
282	list_for_each_entry(bss, &dev->bss_list, list) {
283		if ((bss->pub.capability & capa_mask) != capa_val)
284			continue;
285		if (channel && bss->pub.channel != channel)
286			continue;
287		/* Don't get expired BSS structs */
288		if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
289		    !atomic_read(&bss->hold))
290			continue;
291		if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
292			res = bss;
293			kref_get(&res->ref);
294			break;
295		}
296	}
297
298	spin_unlock_bh(&dev->bss_lock);
299	if (!res)
300		return NULL;
301	return &res->pub;
302}
303EXPORT_SYMBOL(cfg80211_get_bss);
304
305struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
306				       struct ieee80211_channel *channel,
307				       const u8 *meshid, size_t meshidlen,
308				       const u8 *meshcfg)
309{
310	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
311	struct cfg80211_internal_bss *bss, *res = NULL;
312
313	spin_lock_bh(&dev->bss_lock);
314
315	list_for_each_entry(bss, &dev->bss_list, list) {
316		if (channel && bss->pub.channel != channel)
317			continue;
318		if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) {
319			res = bss;
320			kref_get(&res->ref);
321			break;
322		}
323	}
324
325	spin_unlock_bh(&dev->bss_lock);
326	if (!res)
327		return NULL;
328	return &res->pub;
329}
330EXPORT_SYMBOL(cfg80211_get_mesh);
331
332
333static void rb_insert_bss(struct cfg80211_registered_device *dev,
334			  struct cfg80211_internal_bss *bss)
335{
336	struct rb_node **p = &dev->bss_tree.rb_node;
337	struct rb_node *parent = NULL;
338	struct cfg80211_internal_bss *tbss;
339	int cmp;
340
341	while (*p) {
342		parent = *p;
343		tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
344
345		cmp = cmp_bss(&bss->pub, &tbss->pub);
346
347		if (WARN_ON(!cmp)) {
348			/* will sort of leak this BSS */
349			return;
350		}
351
352		if (cmp < 0)
353			p = &(*p)->rb_left;
354		else
355			p = &(*p)->rb_right;
356	}
357
358	rb_link_node(&bss->rbn, parent, p);
359	rb_insert_color(&bss->rbn, &dev->bss_tree);
360}
361
362static struct cfg80211_internal_bss *
363rb_find_bss(struct cfg80211_registered_device *dev,
364	    struct cfg80211_internal_bss *res)
365{
366	struct rb_node *n = dev->bss_tree.rb_node;
367	struct cfg80211_internal_bss *bss;
368	int r;
369
370	while (n) {
371		bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
372		r = cmp_bss(&res->pub, &bss->pub);
373
374		if (r == 0)
375			return bss;
376		else if (r < 0)
377			n = n->rb_left;
378		else
379			n = n->rb_right;
380	}
381
382	return NULL;
383}
384
385static struct cfg80211_internal_bss *
386cfg80211_bss_update(struct cfg80211_registered_device *dev,
387		    struct cfg80211_internal_bss *res)
388{
389	struct cfg80211_internal_bss *found = NULL;
390	const u8 *meshid, *meshcfg;
391
392	/*
393	 * The reference to "res" is donated to this function.
394	 */
395
396	if (WARN_ON(!res->pub.channel)) {
397		kref_put(&res->ref, bss_release);
398		return NULL;
399	}
400
401	res->ts = jiffies;
402
403	if (is_zero_ether_addr(res->pub.bssid)) {
404		/* must be mesh, verify */
405		meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
406					  res->pub.information_elements,
407					  res->pub.len_information_elements);
408		meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
409					   res->pub.information_elements,
410					   res->pub.len_information_elements);
411		if (!meshid || !meshcfg ||
412		    meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
413			/* bogus mesh */
414			kref_put(&res->ref, bss_release);
415			return NULL;
416		}
417	}
418
419	spin_lock_bh(&dev->bss_lock);
420
421	found = rb_find_bss(dev, res);
422
423	if (found) {
424		found->pub.beacon_interval = res->pub.beacon_interval;
425		found->pub.tsf = res->pub.tsf;
426		found->pub.signal = res->pub.signal;
427		found->pub.capability = res->pub.capability;
428		found->ts = res->ts;
429
430		/* Update IEs */
431		if (res->pub.proberesp_ies) {
432			size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
433			size_t ielen = res->pub.len_proberesp_ies;
434
435			if (found->pub.proberesp_ies &&
436			    !found->proberesp_ies_allocated &&
437			    ksize(found) >= used + ielen) {
438				memcpy(found->pub.proberesp_ies,
439				       res->pub.proberesp_ies, ielen);
440				found->pub.len_proberesp_ies = ielen;
441			} else {
442				u8 *ies = found->pub.proberesp_ies;
443
444				if (found->proberesp_ies_allocated)
445					ies = krealloc(ies, ielen, GFP_ATOMIC);
446				else
447					ies = kmalloc(ielen, GFP_ATOMIC);
448
449				if (ies) {
450					memcpy(ies, res->pub.proberesp_ies,
451					       ielen);
452					found->proberesp_ies_allocated = true;
453					found->pub.proberesp_ies = ies;
454					found->pub.len_proberesp_ies = ielen;
455				}
456			}
457
458			/* Override possible earlier Beacon frame IEs */
459			found->pub.information_elements =
460				found->pub.proberesp_ies;
461			found->pub.len_information_elements =
462				found->pub.len_proberesp_ies;
463		}
464		if (res->pub.beacon_ies) {
465			size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
466			size_t ielen = res->pub.len_beacon_ies;
467
468			if (found->pub.beacon_ies &&
469			    !found->beacon_ies_allocated &&
470			    ksize(found) >= used + ielen) {
471				memcpy(found->pub.beacon_ies,
472				       res->pub.beacon_ies, ielen);
473				found->pub.len_beacon_ies = ielen;
474			} else {
475				u8 *ies = found->pub.beacon_ies;
476
477				if (found->beacon_ies_allocated)
478					ies = krealloc(ies, ielen, GFP_ATOMIC);
479				else
480					ies = kmalloc(ielen, GFP_ATOMIC);
481
482				if (ies) {
483					memcpy(ies, res->pub.beacon_ies,
484					       ielen);
485					found->beacon_ies_allocated = true;
486					found->pub.beacon_ies = ies;
487					found->pub.len_beacon_ies = ielen;
488				}
489			}
490		}
491
492		kref_put(&res->ref, bss_release);
493	} else {
494		/* this "consumes" the reference */
495		list_add_tail(&res->list, &dev->bss_list);
496		rb_insert_bss(dev, res);
497		found = res;
498	}
499
500	dev->bss_generation++;
501	spin_unlock_bh(&dev->bss_lock);
502
503	kref_get(&found->ref);
504	return found;
505}
506
507struct cfg80211_bss*
508cfg80211_inform_bss(struct wiphy *wiphy,
509		    struct ieee80211_channel *channel,
510		    const u8 *bssid,
511		    u64 timestamp, u16 capability, u16 beacon_interval,
512		    const u8 *ie, size_t ielen,
513		    s32 signal, gfp_t gfp)
514{
515	struct cfg80211_internal_bss *res;
516	size_t privsz;
517
518	if (WARN_ON(!wiphy))
519		return NULL;
520
521	privsz = wiphy->bss_priv_size;
522
523	if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
524			(signal < 0 || signal > 100)))
525		return NULL;
526
527	res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
528	if (!res)
529		return NULL;
530
531	memcpy(res->pub.bssid, bssid, ETH_ALEN);
532	res->pub.channel = channel;
533	res->pub.signal = signal;
534	res->pub.tsf = timestamp;
535	res->pub.beacon_interval = beacon_interval;
536	res->pub.capability = capability;
537	/*
538	 * Since we do not know here whether the IEs are from a Beacon or Probe
539	 * Response frame, we need to pick one of the options and only use it
540	 * with the driver that does not provide the full Beacon/Probe Response
541	 * frame. Use Beacon frame pointer to avoid indicating that this should
542	 * override the information_elements pointer should we have received an
543	 * earlier indication of Probe Response data.
544	 *
545	 * The initial buffer for the IEs is allocated with the BSS entry and
546	 * is located after the private area.
547	 */
548	res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz;
549	memcpy(res->pub.beacon_ies, ie, ielen);
550	res->pub.len_beacon_ies = ielen;
551	res->pub.information_elements = res->pub.beacon_ies;
552	res->pub.len_information_elements = res->pub.len_beacon_ies;
553
554	kref_init(&res->ref);
555
556	res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
557	if (!res)
558		return NULL;
559
560	if (res->pub.capability & WLAN_CAPABILITY_ESS)
561		regulatory_hint_found_beacon(wiphy, channel, gfp);
562
563	/* cfg80211_bss_update gives us a referenced result */
564	return &res->pub;
565}
566EXPORT_SYMBOL(cfg80211_inform_bss);
567
568struct cfg80211_bss *
569cfg80211_inform_bss_frame(struct wiphy *wiphy,
570			  struct ieee80211_channel *channel,
571			  struct ieee80211_mgmt *mgmt, size_t len,
572			  s32 signal, gfp_t gfp)
573{
574	struct cfg80211_internal_bss *res;
575	size_t ielen = len - offsetof(struct ieee80211_mgmt,
576				      u.probe_resp.variable);
577	size_t privsz = wiphy->bss_priv_size;
578
579	if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
580	            (signal < 0 || signal > 100)))
581		return NULL;
582
583	if (WARN_ON(!mgmt || !wiphy ||
584		    len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
585		return NULL;
586
587	res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
588	if (!res)
589		return NULL;
590
591	memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN);
592	res->pub.channel = channel;
593	res->pub.signal = signal;
594	res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
595	res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
596	res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
597	/*
598	 * The initial buffer for the IEs is allocated with the BSS entry and
599	 * is located after the private area.
600	 */
601	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
602		res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz;
603		memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable,
604		       ielen);
605		res->pub.len_proberesp_ies = ielen;
606		res->pub.information_elements = res->pub.proberesp_ies;
607		res->pub.len_information_elements = res->pub.len_proberesp_ies;
608	} else {
609		res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
610		memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
611		res->pub.len_beacon_ies = ielen;
612		res->pub.information_elements = res->pub.beacon_ies;
613		res->pub.len_information_elements = res->pub.len_beacon_ies;
614	}
615
616	kref_init(&res->ref);
617
618	res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
619	if (!res)
620		return NULL;
621
622	if (res->pub.capability & WLAN_CAPABILITY_ESS)
623		regulatory_hint_found_beacon(wiphy, channel, gfp);
624
625	/* cfg80211_bss_update gives us a referenced result */
626	return &res->pub;
627}
628EXPORT_SYMBOL(cfg80211_inform_bss_frame);
629
630void cfg80211_put_bss(struct cfg80211_bss *pub)
631{
632	struct cfg80211_internal_bss *bss;
633
634	if (!pub)
635		return;
636
637	bss = container_of(pub, struct cfg80211_internal_bss, pub);
638	kref_put(&bss->ref, bss_release);
639}
640EXPORT_SYMBOL(cfg80211_put_bss);
641
642void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
643{
644	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
645	struct cfg80211_internal_bss *bss;
646
647	if (WARN_ON(!pub))
648		return;
649
650	bss = container_of(pub, struct cfg80211_internal_bss, pub);
651
652	spin_lock_bh(&dev->bss_lock);
653	if (!list_empty(&bss->list)) {
654		list_del_init(&bss->list);
655		dev->bss_generation++;
656		rb_erase(&bss->rbn, &dev->bss_tree);
657
658		kref_put(&bss->ref, bss_release);
659	}
660	spin_unlock_bh(&dev->bss_lock);
661}
662EXPORT_SYMBOL(cfg80211_unlink_bss);
663
664#ifdef CONFIG_CFG80211_WEXT
665int cfg80211_wext_siwscan(struct net_device *dev,
666			  struct iw_request_info *info,
667			  union iwreq_data *wrqu, char *extra)
668{
669	struct cfg80211_registered_device *rdev;
670	struct wiphy *wiphy;
671	struct iw_scan_req *wreq = NULL;
672	struct cfg80211_scan_request *creq = NULL;
673	int i, err, n_channels = 0;
674	enum ieee80211_band band;
675
676	if (!netif_running(dev))
677		return -ENETDOWN;
678
679	if (wrqu->data.length == sizeof(struct iw_scan_req))
680		wreq = (struct iw_scan_req *)extra;
681
682	rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
683
684	if (IS_ERR(rdev))
685		return PTR_ERR(rdev);
686
687	if (rdev->scan_req) {
688		err = -EBUSY;
689		goto out;
690	}
691
692	wiphy = &rdev->wiphy;
693
694	/* Determine number of channels, needed to allocate creq */
695	if (wreq && wreq->num_channels)
696		n_channels = wreq->num_channels;
697	else {
698		for (band = 0; band < IEEE80211_NUM_BANDS; band++)
699			if (wiphy->bands[band])
700				n_channels += wiphy->bands[band]->n_channels;
701	}
702
703	creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
704		       n_channels * sizeof(void *),
705		       GFP_ATOMIC);
706	if (!creq) {
707		err = -ENOMEM;
708		goto out;
709	}
710
711	creq->wiphy = wiphy;
712	creq->dev = dev;
713	/* SSIDs come after channels */
714	creq->ssids = (void *)&creq->channels[n_channels];
715	creq->n_channels = n_channels;
716	creq->n_ssids = 1;
717
718	/* translate "Scan on frequencies" request */
719	i = 0;
720	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
721		int j;
722
723		if (!wiphy->bands[band])
724			continue;
725
726		for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
727			/* ignore disabled channels */
728			if (wiphy->bands[band]->channels[j].flags &
729						IEEE80211_CHAN_DISABLED)
730				continue;
731
732			/* If we have a wireless request structure and the
733			 * wireless request specifies frequencies, then search
734			 * for the matching hardware channel.
735			 */
736			if (wreq && wreq->num_channels) {
737				int k;
738				int wiphy_freq = wiphy->bands[band]->channels[j].center_freq;
739				for (k = 0; k < wreq->num_channels; k++) {
740					int wext_freq = cfg80211_wext_freq(wiphy, &wreq->channel_list[k]);
741					if (wext_freq == wiphy_freq)
742						goto wext_freq_found;
743				}
744				goto wext_freq_not_found;
745			}
746
747		wext_freq_found:
748			creq->channels[i] = &wiphy->bands[band]->channels[j];
749			i++;
750		wext_freq_not_found: ;
751		}
752	}
753	/* No channels found? */
754	if (!i) {
755		err = -EINVAL;
756		goto out;
757	}
758
759	/* Set real number of channels specified in creq->channels[] */
760	creq->n_channels = i;
761
762	/* translate "Scan for SSID" request */
763	if (wreq) {
764		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
765			if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
766				err = -EINVAL;
767				goto out;
768			}
769			memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
770			creq->ssids[0].ssid_len = wreq->essid_len;
771		}
772		if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
773			creq->n_ssids = 0;
774	}
775
776	rdev->scan_req = creq;
777	err = rdev->ops->scan(wiphy, dev, creq);
778	if (err) {
779		rdev->scan_req = NULL;
780		/* creq will be freed below */
781	} else {
782		nl80211_send_scan_start(rdev, dev);
783		/* creq now owned by driver */
784		creq = NULL;
785		dev_hold(dev);
786	}
787 out:
788	kfree(creq);
789	cfg80211_unlock_rdev(rdev);
790	return err;
791}
792EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
793
794static void ieee80211_scan_add_ies(struct iw_request_info *info,
795				   struct cfg80211_bss *bss,
796				   char **current_ev, char *end_buf)
797{
798	u8 *pos, *end, *next;
799	struct iw_event iwe;
800
801	if (!bss->information_elements ||
802	    !bss->len_information_elements)
803		return;
804
805	/*
806	 * If needed, fragment the IEs buffer (at IE boundaries) into short
807	 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
808	 */
809	pos = bss->information_elements;
810	end = pos + bss->len_information_elements;
811
812	while (end - pos > IW_GENERIC_IE_MAX) {
813		next = pos + 2 + pos[1];
814		while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
815			next = next + 2 + next[1];
816
817		memset(&iwe, 0, sizeof(iwe));
818		iwe.cmd = IWEVGENIE;
819		iwe.u.data.length = next - pos;
820		*current_ev = iwe_stream_add_point(info, *current_ev,
821						   end_buf, &iwe, pos);
822
823		pos = next;
824	}
825
826	if (end > pos) {
827		memset(&iwe, 0, sizeof(iwe));
828		iwe.cmd = IWEVGENIE;
829		iwe.u.data.length = end - pos;
830		*current_ev = iwe_stream_add_point(info, *current_ev,
831						   end_buf, &iwe, pos);
832	}
833}
834
835static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
836{
837	unsigned long end = jiffies;
838
839	if (end >= start)
840		return jiffies_to_msecs(end - start);
841
842	return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
843}
844
845static char *
846ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
847	      struct cfg80211_internal_bss *bss, char *current_ev,
848	      char *end_buf)
849{
850	struct iw_event iwe;
851	u8 *buf, *cfg, *p;
852	u8 *ie = bss->pub.information_elements;
853	int rem = bss->pub.len_information_elements, i, sig;
854	bool ismesh = false;
855
856	memset(&iwe, 0, sizeof(iwe));
857	iwe.cmd = SIOCGIWAP;
858	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
859	memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
860	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
861					  IW_EV_ADDR_LEN);
862
863	memset(&iwe, 0, sizeof(iwe));
864	iwe.cmd = SIOCGIWFREQ;
865	iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
866	iwe.u.freq.e = 0;
867	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
868					  IW_EV_FREQ_LEN);
869
870	memset(&iwe, 0, sizeof(iwe));
871	iwe.cmd = SIOCGIWFREQ;
872	iwe.u.freq.m = bss->pub.channel->center_freq;
873	iwe.u.freq.e = 6;
874	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
875					  IW_EV_FREQ_LEN);
876
877	if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
878		memset(&iwe, 0, sizeof(iwe));
879		iwe.cmd = IWEVQUAL;
880		iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED |
881				     IW_QUAL_NOISE_INVALID |
882				     IW_QUAL_QUAL_UPDATED;
883		switch (wiphy->signal_type) {
884		case CFG80211_SIGNAL_TYPE_MBM:
885			sig = bss->pub.signal / 100;
886			iwe.u.qual.level = sig;
887			iwe.u.qual.updated |= IW_QUAL_DBM;
888			if (sig < -110)		/* rather bad */
889				sig = -110;
890			else if (sig > -40)	/* perfect */
891				sig = -40;
892			/* will give a range of 0 .. 70 */
893			iwe.u.qual.qual = sig + 110;
894			break;
895		case CFG80211_SIGNAL_TYPE_UNSPEC:
896			iwe.u.qual.level = bss->pub.signal;
897			/* will give range 0 .. 100 */
898			iwe.u.qual.qual = bss->pub.signal;
899			break;
900		default:
901			/* not reached */
902			break;
903		}
904		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
905						  &iwe, IW_EV_QUAL_LEN);
906	}
907
908	memset(&iwe, 0, sizeof(iwe));
909	iwe.cmd = SIOCGIWENCODE;
910	if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY)
911		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
912	else
913		iwe.u.data.flags = IW_ENCODE_DISABLED;
914	iwe.u.data.length = 0;
915	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
916					  &iwe, "");
917
918	while (rem >= 2) {
919		/* invalid data */
920		if (ie[1] > rem - 2)
921			break;
922
923		switch (ie[0]) {
924		case WLAN_EID_SSID:
925			memset(&iwe, 0, sizeof(iwe));
926			iwe.cmd = SIOCGIWESSID;
927			iwe.u.data.length = ie[1];
928			iwe.u.data.flags = 1;
929			current_ev = iwe_stream_add_point(info, current_ev, end_buf,
930							  &iwe, ie + 2);
931			break;
932		case WLAN_EID_MESH_ID:
933			memset(&iwe, 0, sizeof(iwe));
934			iwe.cmd = SIOCGIWESSID;
935			iwe.u.data.length = ie[1];
936			iwe.u.data.flags = 1;
937			current_ev = iwe_stream_add_point(info, current_ev, end_buf,
938							  &iwe, ie + 2);
939			break;
940		case WLAN_EID_MESH_CONFIG:
941			ismesh = true;
942			if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
943				break;
944			buf = kmalloc(50, GFP_ATOMIC);
945			if (!buf)
946				break;
947			cfg = ie + 2;
948			memset(&iwe, 0, sizeof(iwe));
949			iwe.cmd = IWEVCUSTOM;
950			sprintf(buf, "Mesh Network Path Selection Protocol ID: "
951				"0x%02X", cfg[0]);
952			iwe.u.data.length = strlen(buf);
953			current_ev = iwe_stream_add_point(info, current_ev,
954							  end_buf,
955							  &iwe, buf);
956			sprintf(buf, "Path Selection Metric ID: 0x%02X",
957				cfg[1]);
958			iwe.u.data.length = strlen(buf);
959			current_ev = iwe_stream_add_point(info, current_ev,
960							  end_buf,
961							  &iwe, buf);
962			sprintf(buf, "Congestion Control Mode ID: 0x%02X",
963				cfg[2]);
964			iwe.u.data.length = strlen(buf);
965			current_ev = iwe_stream_add_point(info, current_ev,
966							  end_buf,
967							  &iwe, buf);
968			sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
969			iwe.u.data.length = strlen(buf);
970			current_ev = iwe_stream_add_point(info, current_ev,
971							  end_buf,
972							  &iwe, buf);
973			sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
974			iwe.u.data.length = strlen(buf);
975			current_ev = iwe_stream_add_point(info, current_ev,
976							  end_buf,
977							  &iwe, buf);
978			sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
979			iwe.u.data.length = strlen(buf);
980			current_ev = iwe_stream_add_point(info, current_ev,
981							  end_buf,
982							  &iwe, buf);
983			sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
984			iwe.u.data.length = strlen(buf);
985			current_ev = iwe_stream_add_point(info, current_ev,
986							  end_buf,
987							  &iwe, buf);
988			kfree(buf);
989			break;
990		case WLAN_EID_SUPP_RATES:
991		case WLAN_EID_EXT_SUPP_RATES:
992			/* display all supported rates in readable format */
993			p = current_ev + iwe_stream_lcp_len(info);
994
995			memset(&iwe, 0, sizeof(iwe));
996			iwe.cmd = SIOCGIWRATE;
997			/* Those two flags are ignored... */
998			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
999
1000			for (i = 0; i < ie[1]; i++) {
1001				iwe.u.bitrate.value =
1002					((ie[i + 2] & 0x7f) * 500000);
1003				p = iwe_stream_add_value(info, current_ev, p,
1004						end_buf, &iwe, IW_EV_PARAM_LEN);
1005			}
1006			current_ev = p;
1007			break;
1008		}
1009		rem -= ie[1] + 2;
1010		ie += ie[1] + 2;
1011	}
1012
1013	if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) ||
1014	    ismesh) {
1015		memset(&iwe, 0, sizeof(iwe));
1016		iwe.cmd = SIOCGIWMODE;
1017		if (ismesh)
1018			iwe.u.mode = IW_MODE_MESH;
1019		else if (bss->pub.capability & WLAN_CAPABILITY_ESS)
1020			iwe.u.mode = IW_MODE_MASTER;
1021		else
1022			iwe.u.mode = IW_MODE_ADHOC;
1023		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1024						  &iwe, IW_EV_UINT_LEN);
1025	}
1026
1027	buf = kmalloc(30, GFP_ATOMIC);
1028	if (buf) {
1029		memset(&iwe, 0, sizeof(iwe));
1030		iwe.cmd = IWEVCUSTOM;
1031		sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf));
1032		iwe.u.data.length = strlen(buf);
1033		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1034						  &iwe, buf);
1035		memset(&iwe, 0, sizeof(iwe));
1036		iwe.cmd = IWEVCUSTOM;
1037		sprintf(buf, " Last beacon: %ums ago",
1038			elapsed_jiffies_msecs(bss->ts));
1039		iwe.u.data.length = strlen(buf);
1040		current_ev = iwe_stream_add_point(info, current_ev,
1041						  end_buf, &iwe, buf);
1042		kfree(buf);
1043	}
1044
1045	ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf);
1046
1047	return current_ev;
1048}
1049
1050
1051static int ieee80211_scan_results(struct cfg80211_registered_device *dev,
1052				  struct iw_request_info *info,
1053				  char *buf, size_t len)
1054{
1055	char *current_ev = buf;
1056	char *end_buf = buf + len;
1057	struct cfg80211_internal_bss *bss;
1058
1059	spin_lock_bh(&dev->bss_lock);
1060	cfg80211_bss_expire(dev);
1061
1062	list_for_each_entry(bss, &dev->bss_list, list) {
1063		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
1064			spin_unlock_bh(&dev->bss_lock);
1065			return -E2BIG;
1066		}
1067		current_ev = ieee80211_bss(&dev->wiphy, info, bss,
1068					   current_ev, end_buf);
1069	}
1070	spin_unlock_bh(&dev->bss_lock);
1071	return current_ev - buf;
1072}
1073
1074
1075int cfg80211_wext_giwscan(struct net_device *dev,
1076			  struct iw_request_info *info,
1077			  struct iw_point *data, char *extra)
1078{
1079	struct cfg80211_registered_device *rdev;
1080	int res;
1081
1082	if (!netif_running(dev))
1083		return -ENETDOWN;
1084
1085	rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
1086
1087	if (IS_ERR(rdev))
1088		return PTR_ERR(rdev);
1089
1090	if (rdev->scan_req) {
1091		res = -EAGAIN;
1092		goto out;
1093	}
1094
1095	res = ieee80211_scan_results(rdev, info, extra, data->length);
1096	data->length = 0;
1097	if (res >= 0) {
1098		data->length = res;
1099		res = 0;
1100	}
1101
1102 out:
1103	cfg80211_unlock_rdev(rdev);
1104	return res;
1105}
1106EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
1107#endif
1108