xref: /linux/net/wireless/scan.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
1 /*
2  * cfg80211 scan result handling
3  *
4  * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5  */
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/netdevice.h>
9 #include <linux/wireless.h>
10 #include <linux/nl80211.h>
11 #include <linux/etherdevice.h>
12 #include <net/arp.h>
13 #include <net/cfg80211.h>
14 #include <net/iw_handler.h>
15 #include "core.h"
16 #include "nl80211.h"
17 
18 #define IEEE80211_SCAN_RESULT_EXPIRE	(10 * HZ)
19 
20 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
21 {
22 	struct net_device *dev;
23 #ifdef CONFIG_WIRELESS_EXT
24 	union iwreq_data wrqu;
25 #endif
26 
27 	dev = dev_get_by_index(&init_net, request->ifidx);
28 	if (!dev)
29 		goto out;
30 
31 	WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
32 	wiphy_to_dev(request->wiphy)->scan_req = NULL;
33 
34 	if (aborted)
35 		nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
36 	else
37 		nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
38 
39 #ifdef CONFIG_WIRELESS_EXT
40 	if (!aborted) {
41 		memset(&wrqu, 0, sizeof(wrqu));
42 
43 		wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
44 	}
45 #endif
46 
47 	dev_put(dev);
48 
49  out:
50 	kfree(request);
51 }
52 EXPORT_SYMBOL(cfg80211_scan_done);
53 
54 static void bss_release(struct kref *ref)
55 {
56 	struct cfg80211_internal_bss *bss;
57 
58 	bss = container_of(ref, struct cfg80211_internal_bss, ref);
59 	if (bss->pub.free_priv)
60 		bss->pub.free_priv(&bss->pub);
61 	kfree(bss);
62 }
63 
64 /* must hold dev->bss_lock! */
65 void cfg80211_bss_age(struct cfg80211_registered_device *dev,
66                       unsigned long age_secs)
67 {
68 	struct cfg80211_internal_bss *bss;
69 	unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
70 
71 	list_for_each_entry(bss, &dev->bss_list, list) {
72 		bss->ts -= age_jiffies;
73 	}
74 }
75 
76 /* must hold dev->bss_lock! */
77 void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
78 {
79 	struct cfg80211_internal_bss *bss, *tmp;
80 	bool expired = false;
81 
82 	list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
83 		if (bss->hold ||
84 		    !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
85 			continue;
86 		list_del(&bss->list);
87 		rb_erase(&bss->rbn, &dev->bss_tree);
88 		kref_put(&bss->ref, bss_release);
89 		expired = true;
90 	}
91 
92 	if (expired)
93 		dev->bss_generation++;
94 }
95 
96 static u8 *find_ie(u8 num, u8 *ies, size_t len)
97 {
98 	while (len > 2 && ies[0] != num) {
99 		len -= ies[1] + 2;
100 		ies += ies[1] + 2;
101 	}
102 	if (len < 2)
103 		return NULL;
104 	if (len < 2 + ies[1])
105 		return NULL;
106 	return ies;
107 }
108 
109 static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
110 {
111 	const u8 *ie1 = find_ie(num, ies1, len1);
112 	const u8 *ie2 = find_ie(num, ies2, len2);
113 	int r;
114 
115 	if (!ie1 && !ie2)
116 		return 0;
117 	if (!ie1)
118 		return -1;
119 
120 	r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
121 	if (r == 0 && ie1[1] != ie2[1])
122 		return ie2[1] - ie1[1];
123 	return r;
124 }
125 
126 static bool is_bss(struct cfg80211_bss *a,
127 		   const u8 *bssid,
128 		   const u8 *ssid, size_t ssid_len)
129 {
130 	const u8 *ssidie;
131 
132 	if (bssid && compare_ether_addr(a->bssid, bssid))
133 		return false;
134 
135 	if (!ssid)
136 		return true;
137 
138 	ssidie = find_ie(WLAN_EID_SSID,
139 			 a->information_elements,
140 			 a->len_information_elements);
141 	if (!ssidie)
142 		return false;
143 	if (ssidie[1] != ssid_len)
144 		return false;
145 	return memcmp(ssidie + 2, ssid, ssid_len) == 0;
146 }
147 
148 static bool is_mesh(struct cfg80211_bss *a,
149 		    const u8 *meshid, size_t meshidlen,
150 		    const u8 *meshcfg)
151 {
152 	const u8 *ie;
153 
154 	if (!is_zero_ether_addr(a->bssid))
155 		return false;
156 
157 	ie = find_ie(WLAN_EID_MESH_ID,
158 		     a->information_elements,
159 		     a->len_information_elements);
160 	if (!ie)
161 		return false;
162 	if (ie[1] != meshidlen)
163 		return false;
164 	if (memcmp(ie + 2, meshid, meshidlen))
165 		return false;
166 
167 	ie = find_ie(WLAN_EID_MESH_CONFIG,
168 		     a->information_elements,
169 		     a->len_information_elements);
170 	if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
171 		return false;
172 
173 	/*
174 	 * Ignore mesh capability (last two bytes of the IE) when
175 	 * comparing since that may differ between stations taking
176 	 * part in the same mesh.
177 	 */
178 	return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0;
179 }
180 
181 static int cmp_bss(struct cfg80211_bss *a,
182 		   struct cfg80211_bss *b)
183 {
184 	int r;
185 
186 	if (a->channel != b->channel)
187 		return b->channel->center_freq - a->channel->center_freq;
188 
189 	r = memcmp(a->bssid, b->bssid, ETH_ALEN);
190 	if (r)
191 		return r;
192 
193 	if (is_zero_ether_addr(a->bssid)) {
194 		r = cmp_ies(WLAN_EID_MESH_ID,
195 			    a->information_elements,
196 			    a->len_information_elements,
197 			    b->information_elements,
198 			    b->len_information_elements);
199 		if (r)
200 			return r;
201 		return cmp_ies(WLAN_EID_MESH_CONFIG,
202 			       a->information_elements,
203 			       a->len_information_elements,
204 			       b->information_elements,
205 			       b->len_information_elements);
206 	}
207 
208 	return cmp_ies(WLAN_EID_SSID,
209 		       a->information_elements,
210 		       a->len_information_elements,
211 		       b->information_elements,
212 		       b->len_information_elements);
213 }
214 
215 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
216 				      struct ieee80211_channel *channel,
217 				      const u8 *bssid,
218 				      const u8 *ssid, size_t ssid_len,
219 				      u16 capa_mask, u16 capa_val)
220 {
221 	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
222 	struct cfg80211_internal_bss *bss, *res = NULL;
223 
224 	spin_lock_bh(&dev->bss_lock);
225 
226 	list_for_each_entry(bss, &dev->bss_list, list) {
227 		if ((bss->pub.capability & capa_mask) != capa_val)
228 			continue;
229 		if (channel && bss->pub.channel != channel)
230 			continue;
231 		if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
232 			res = bss;
233 			kref_get(&res->ref);
234 			break;
235 		}
236 	}
237 
238 	spin_unlock_bh(&dev->bss_lock);
239 	if (!res)
240 		return NULL;
241 	return &res->pub;
242 }
243 EXPORT_SYMBOL(cfg80211_get_bss);
244 
245 struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
246 				       struct ieee80211_channel *channel,
247 				       const u8 *meshid, size_t meshidlen,
248 				       const u8 *meshcfg)
249 {
250 	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
251 	struct cfg80211_internal_bss *bss, *res = NULL;
252 
253 	spin_lock_bh(&dev->bss_lock);
254 
255 	list_for_each_entry(bss, &dev->bss_list, list) {
256 		if (channel && bss->pub.channel != channel)
257 			continue;
258 		if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) {
259 			res = bss;
260 			kref_get(&res->ref);
261 			break;
262 		}
263 	}
264 
265 	spin_unlock_bh(&dev->bss_lock);
266 	if (!res)
267 		return NULL;
268 	return &res->pub;
269 }
270 EXPORT_SYMBOL(cfg80211_get_mesh);
271 
272 
273 static void rb_insert_bss(struct cfg80211_registered_device *dev,
274 			  struct cfg80211_internal_bss *bss)
275 {
276 	struct rb_node **p = &dev->bss_tree.rb_node;
277 	struct rb_node *parent = NULL;
278 	struct cfg80211_internal_bss *tbss;
279 	int cmp;
280 
281 	while (*p) {
282 		parent = *p;
283 		tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
284 
285 		cmp = cmp_bss(&bss->pub, &tbss->pub);
286 
287 		if (WARN_ON(!cmp)) {
288 			/* will sort of leak this BSS */
289 			return;
290 		}
291 
292 		if (cmp < 0)
293 			p = &(*p)->rb_left;
294 		else
295 			p = &(*p)->rb_right;
296 	}
297 
298 	rb_link_node(&bss->rbn, parent, p);
299 	rb_insert_color(&bss->rbn, &dev->bss_tree);
300 }
301 
302 static struct cfg80211_internal_bss *
303 rb_find_bss(struct cfg80211_registered_device *dev,
304 	    struct cfg80211_internal_bss *res)
305 {
306 	struct rb_node *n = dev->bss_tree.rb_node;
307 	struct cfg80211_internal_bss *bss;
308 	int r;
309 
310 	while (n) {
311 		bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
312 		r = cmp_bss(&res->pub, &bss->pub);
313 
314 		if (r == 0)
315 			return bss;
316 		else if (r < 0)
317 			n = n->rb_left;
318 		else
319 			n = n->rb_right;
320 	}
321 
322 	return NULL;
323 }
324 
325 static struct cfg80211_internal_bss *
326 cfg80211_bss_update(struct cfg80211_registered_device *dev,
327 		    struct cfg80211_internal_bss *res,
328 		    bool overwrite)
329 {
330 	struct cfg80211_internal_bss *found = NULL;
331 	const u8 *meshid, *meshcfg;
332 
333 	/*
334 	 * The reference to "res" is donated to this function.
335 	 */
336 
337 	if (WARN_ON(!res->pub.channel)) {
338 		kref_put(&res->ref, bss_release);
339 		return NULL;
340 	}
341 
342 	res->ts = jiffies;
343 
344 	if (is_zero_ether_addr(res->pub.bssid)) {
345 		/* must be mesh, verify */
346 		meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements,
347 				 res->pub.len_information_elements);
348 		meshcfg = find_ie(WLAN_EID_MESH_CONFIG,
349 				  res->pub.information_elements,
350 				  res->pub.len_information_elements);
351 		if (!meshid || !meshcfg ||
352 		    meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) {
353 			/* bogus mesh */
354 			kref_put(&res->ref, bss_release);
355 			return NULL;
356 		}
357 	}
358 
359 	spin_lock_bh(&dev->bss_lock);
360 
361 	found = rb_find_bss(dev, res);
362 
363 	if (found && overwrite) {
364 		list_replace(&found->list, &res->list);
365 		rb_replace_node(&found->rbn, &res->rbn,
366 				&dev->bss_tree);
367 		kref_put(&found->ref, bss_release);
368 		found = res;
369 	} else if (found) {
370 		kref_get(&found->ref);
371 		found->pub.beacon_interval = res->pub.beacon_interval;
372 		found->pub.tsf = res->pub.tsf;
373 		found->pub.signal = res->pub.signal;
374 		found->pub.capability = res->pub.capability;
375 		found->ts = res->ts;
376 		kref_put(&res->ref, bss_release);
377 	} else {
378 		/* this "consumes" the reference */
379 		list_add_tail(&res->list, &dev->bss_list);
380 		rb_insert_bss(dev, res);
381 		found = res;
382 	}
383 
384 	dev->bss_generation++;
385 	spin_unlock_bh(&dev->bss_lock);
386 
387 	kref_get(&found->ref);
388 	return found;
389 }
390 
391 struct cfg80211_bss *
392 cfg80211_inform_bss_frame(struct wiphy *wiphy,
393 			  struct ieee80211_channel *channel,
394 			  struct ieee80211_mgmt *mgmt, size_t len,
395 			  s32 signal, gfp_t gfp)
396 {
397 	struct cfg80211_internal_bss *res;
398 	size_t ielen = len - offsetof(struct ieee80211_mgmt,
399 				      u.probe_resp.variable);
400 	bool overwrite;
401 	size_t privsz = wiphy->bss_priv_size;
402 
403 	if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
404 	            (signal < 0 || signal > 100)))
405 		return NULL;
406 
407 	if (WARN_ON(!mgmt || !wiphy ||
408 		    len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
409 		return NULL;
410 
411 	res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
412 	if (!res)
413 		return NULL;
414 
415 	memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN);
416 	res->pub.channel = channel;
417 	res->pub.signal = signal;
418 	res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
419 	res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
420 	res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
421 	/* point to after the private area */
422 	res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
423 	memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen);
424 	res->pub.len_information_elements = ielen;
425 
426 	kref_init(&res->ref);
427 
428 	overwrite = ieee80211_is_probe_resp(mgmt->frame_control);
429 
430 	res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite);
431 	if (!res)
432 		return NULL;
433 
434 	if (res->pub.capability & WLAN_CAPABILITY_ESS)
435 		regulatory_hint_found_beacon(wiphy, channel, gfp);
436 
437 	/* cfg80211_bss_update gives us a referenced result */
438 	return &res->pub;
439 }
440 EXPORT_SYMBOL(cfg80211_inform_bss_frame);
441 
442 void cfg80211_put_bss(struct cfg80211_bss *pub)
443 {
444 	struct cfg80211_internal_bss *bss;
445 
446 	if (!pub)
447 		return;
448 
449 	bss = container_of(pub, struct cfg80211_internal_bss, pub);
450 	kref_put(&bss->ref, bss_release);
451 }
452 EXPORT_SYMBOL(cfg80211_put_bss);
453 
454 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
455 {
456 	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
457 	struct cfg80211_internal_bss *bss;
458 
459 	if (WARN_ON(!pub))
460 		return;
461 
462 	bss = container_of(pub, struct cfg80211_internal_bss, pub);
463 
464 	spin_lock_bh(&dev->bss_lock);
465 
466 	list_del(&bss->list);
467 	rb_erase(&bss->rbn, &dev->bss_tree);
468 
469 	spin_unlock_bh(&dev->bss_lock);
470 
471 	kref_put(&bss->ref, bss_release);
472 }
473 EXPORT_SYMBOL(cfg80211_unlink_bss);
474 
475 void cfg80211_hold_bss(struct cfg80211_bss *pub)
476 {
477 	struct cfg80211_internal_bss *bss;
478 
479 	if (!pub)
480 		return;
481 
482 	bss = container_of(pub, struct cfg80211_internal_bss, pub);
483 	bss->hold = true;
484 }
485 EXPORT_SYMBOL(cfg80211_hold_bss);
486 
487 void cfg80211_unhold_bss(struct cfg80211_bss *pub)
488 {
489 	struct cfg80211_internal_bss *bss;
490 
491 	if (!pub)
492 		return;
493 
494 	bss = container_of(pub, struct cfg80211_internal_bss, pub);
495 	bss->hold = false;
496 }
497 EXPORT_SYMBOL(cfg80211_unhold_bss);
498 
499 #ifdef CONFIG_WIRELESS_EXT
500 int cfg80211_wext_siwscan(struct net_device *dev,
501 			  struct iw_request_info *info,
502 			  union iwreq_data *wrqu, char *extra)
503 {
504 	struct cfg80211_registered_device *rdev;
505 	struct wiphy *wiphy;
506 	struct iw_scan_req *wreq = NULL;
507 	struct cfg80211_scan_request *creq;
508 	int i, err, n_channels = 0;
509 	enum ieee80211_band band;
510 
511 	if (!netif_running(dev))
512 		return -ENETDOWN;
513 
514 	rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
515 
516 	if (IS_ERR(rdev))
517 		return PTR_ERR(rdev);
518 
519 	if (rdev->scan_req) {
520 		err = -EBUSY;
521 		goto out;
522 	}
523 
524 	wiphy = &rdev->wiphy;
525 
526 	for (band = 0; band < IEEE80211_NUM_BANDS; band++)
527 		if (wiphy->bands[band])
528 			n_channels += wiphy->bands[band]->n_channels;
529 
530 	creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
531 		       n_channels * sizeof(void *),
532 		       GFP_ATOMIC);
533 	if (!creq) {
534 		err = -ENOMEM;
535 		goto out;
536 	}
537 
538 	creq->wiphy = wiphy;
539 	creq->ifidx = dev->ifindex;
540 	creq->ssids = (void *)(creq + 1);
541 	creq->channels = (void *)(creq->ssids + 1);
542 	creq->n_channels = n_channels;
543 	creq->n_ssids = 1;
544 
545 	/* all channels */
546 	i = 0;
547 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
548 		int j;
549 		if (!wiphy->bands[band])
550 			continue;
551 		for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
552 			creq->channels[i] = &wiphy->bands[band]->channels[j];
553 			i++;
554 		}
555 	}
556 
557 	/* translate scan request */
558 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
559 		wreq = (struct iw_scan_req *)extra;
560 
561 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
562 			if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
563 				return -EINVAL;
564 			memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
565 			creq->ssids[0].ssid_len = wreq->essid_len;
566 		}
567 		if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
568 			creq->n_ssids = 0;
569 	}
570 
571 	rdev->scan_req = creq;
572 	err = rdev->ops->scan(wiphy, dev, creq);
573 	if (err) {
574 		rdev->scan_req = NULL;
575 		kfree(creq);
576 	}
577  out:
578 	cfg80211_put_dev(rdev);
579 	return err;
580 }
581 EXPORT_SYMBOL(cfg80211_wext_siwscan);
582 
583 static void ieee80211_scan_add_ies(struct iw_request_info *info,
584 				   struct cfg80211_bss *bss,
585 				   char **current_ev, char *end_buf)
586 {
587 	u8 *pos, *end, *next;
588 	struct iw_event iwe;
589 
590 	if (!bss->information_elements ||
591 	    !bss->len_information_elements)
592 		return;
593 
594 	/*
595 	 * If needed, fragment the IEs buffer (at IE boundaries) into short
596 	 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
597 	 */
598 	pos = bss->information_elements;
599 	end = pos + bss->len_information_elements;
600 
601 	while (end - pos > IW_GENERIC_IE_MAX) {
602 		next = pos + 2 + pos[1];
603 		while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
604 			next = next + 2 + next[1];
605 
606 		memset(&iwe, 0, sizeof(iwe));
607 		iwe.cmd = IWEVGENIE;
608 		iwe.u.data.length = next - pos;
609 		*current_ev = iwe_stream_add_point(info, *current_ev,
610 						   end_buf, &iwe, pos);
611 
612 		pos = next;
613 	}
614 
615 	if (end > pos) {
616 		memset(&iwe, 0, sizeof(iwe));
617 		iwe.cmd = IWEVGENIE;
618 		iwe.u.data.length = end - pos;
619 		*current_ev = iwe_stream_add_point(info, *current_ev,
620 						   end_buf, &iwe, pos);
621 	}
622 }
623 
624 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
625 {
626 	unsigned long end = jiffies;
627 
628 	if (end >= start)
629 		return jiffies_to_msecs(end - start);
630 
631 	return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
632 }
633 
634 static char *
635 ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
636 	      struct cfg80211_internal_bss *bss, char *current_ev,
637 	      char *end_buf)
638 {
639 	struct iw_event iwe;
640 	u8 *buf, *cfg, *p;
641 	u8 *ie = bss->pub.information_elements;
642 	int rem = bss->pub.len_information_elements, i, sig;
643 	bool ismesh = false;
644 
645 	memset(&iwe, 0, sizeof(iwe));
646 	iwe.cmd = SIOCGIWAP;
647 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
648 	memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
649 	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
650 					  IW_EV_ADDR_LEN);
651 
652 	memset(&iwe, 0, sizeof(iwe));
653 	iwe.cmd = SIOCGIWFREQ;
654 	iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
655 	iwe.u.freq.e = 0;
656 	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
657 					  IW_EV_FREQ_LEN);
658 
659 	memset(&iwe, 0, sizeof(iwe));
660 	iwe.cmd = SIOCGIWFREQ;
661 	iwe.u.freq.m = bss->pub.channel->center_freq;
662 	iwe.u.freq.e = 6;
663 	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
664 					  IW_EV_FREQ_LEN);
665 
666 	if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
667 		memset(&iwe, 0, sizeof(iwe));
668 		iwe.cmd = IWEVQUAL;
669 		iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED |
670 				     IW_QUAL_NOISE_INVALID |
671 				     IW_QUAL_QUAL_UPDATED;
672 		switch (wiphy->signal_type) {
673 		case CFG80211_SIGNAL_TYPE_MBM:
674 			sig = bss->pub.signal / 100;
675 			iwe.u.qual.level = sig;
676 			iwe.u.qual.updated |= IW_QUAL_DBM;
677 			if (sig < -110)		/* rather bad */
678 				sig = -110;
679 			else if (sig > -40)	/* perfect */
680 				sig = -40;
681 			/* will give a range of 0 .. 70 */
682 			iwe.u.qual.qual = sig + 110;
683 			break;
684 		case CFG80211_SIGNAL_TYPE_UNSPEC:
685 			iwe.u.qual.level = bss->pub.signal;
686 			/* will give range 0 .. 100 */
687 			iwe.u.qual.qual = bss->pub.signal;
688 			break;
689 		default:
690 			/* not reached */
691 			break;
692 		}
693 		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
694 						  &iwe, IW_EV_QUAL_LEN);
695 	}
696 
697 	memset(&iwe, 0, sizeof(iwe));
698 	iwe.cmd = SIOCGIWENCODE;
699 	if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY)
700 		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
701 	else
702 		iwe.u.data.flags = IW_ENCODE_DISABLED;
703 	iwe.u.data.length = 0;
704 	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
705 					  &iwe, "");
706 
707 	while (rem >= 2) {
708 		/* invalid data */
709 		if (ie[1] > rem - 2)
710 			break;
711 
712 		switch (ie[0]) {
713 		case WLAN_EID_SSID:
714 			memset(&iwe, 0, sizeof(iwe));
715 			iwe.cmd = SIOCGIWESSID;
716 			iwe.u.data.length = ie[1];
717 			iwe.u.data.flags = 1;
718 			current_ev = iwe_stream_add_point(info, current_ev, end_buf,
719 							  &iwe, ie + 2);
720 			break;
721 		case WLAN_EID_MESH_ID:
722 			memset(&iwe, 0, sizeof(iwe));
723 			iwe.cmd = SIOCGIWESSID;
724 			iwe.u.data.length = ie[1];
725 			iwe.u.data.flags = 1;
726 			current_ev = iwe_stream_add_point(info, current_ev, end_buf,
727 							  &iwe, ie + 2);
728 			break;
729 		case WLAN_EID_MESH_CONFIG:
730 			ismesh = true;
731 			if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
732 				break;
733 			buf = kmalloc(50, GFP_ATOMIC);
734 			if (!buf)
735 				break;
736 			cfg = ie + 2;
737 			memset(&iwe, 0, sizeof(iwe));
738 			iwe.cmd = IWEVCUSTOM;
739 			sprintf(buf, "Mesh network (version %d)", cfg[0]);
740 			iwe.u.data.length = strlen(buf);
741 			current_ev = iwe_stream_add_point(info, current_ev,
742 							  end_buf,
743 							  &iwe, buf);
744 			sprintf(buf, "Path Selection Protocol ID: "
745 				"0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
746 							cfg[4]);
747 			iwe.u.data.length = strlen(buf);
748 			current_ev = iwe_stream_add_point(info, current_ev,
749 							  end_buf,
750 							  &iwe, buf);
751 			sprintf(buf, "Path Selection Metric ID: "
752 				"0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
753 							cfg[8]);
754 			iwe.u.data.length = strlen(buf);
755 			current_ev = iwe_stream_add_point(info, current_ev,
756 							  end_buf,
757 							  &iwe, buf);
758 			sprintf(buf, "Congestion Control Mode ID: "
759 				"0x%02X%02X%02X%02X", cfg[9], cfg[10],
760 							cfg[11], cfg[12]);
761 			iwe.u.data.length = strlen(buf);
762 			current_ev = iwe_stream_add_point(info, current_ev,
763 							  end_buf,
764 							  &iwe, buf);
765 			sprintf(buf, "Channel Precedence: "
766 				"0x%02X%02X%02X%02X", cfg[13], cfg[14],
767 							cfg[15], cfg[16]);
768 			iwe.u.data.length = strlen(buf);
769 			current_ev = iwe_stream_add_point(info, current_ev,
770 							  end_buf,
771 							  &iwe, buf);
772 			kfree(buf);
773 			break;
774 		case WLAN_EID_SUPP_RATES:
775 		case WLAN_EID_EXT_SUPP_RATES:
776 			/* display all supported rates in readable format */
777 			p = current_ev + iwe_stream_lcp_len(info);
778 
779 			memset(&iwe, 0, sizeof(iwe));
780 			iwe.cmd = SIOCGIWRATE;
781 			/* Those two flags are ignored... */
782 			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
783 
784 			for (i = 0; i < ie[1]; i++) {
785 				iwe.u.bitrate.value =
786 					((ie[i + 2] & 0x7f) * 500000);
787 				p = iwe_stream_add_value(info, current_ev, p,
788 						end_buf, &iwe, IW_EV_PARAM_LEN);
789 			}
790 			current_ev = p;
791 			break;
792 		}
793 		rem -= ie[1] + 2;
794 		ie += ie[1] + 2;
795 	}
796 
797 	if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)
798 	    || ismesh) {
799 		memset(&iwe, 0, sizeof(iwe));
800 		iwe.cmd = SIOCGIWMODE;
801 		if (ismesh)
802 			iwe.u.mode = IW_MODE_MESH;
803 		else if (bss->pub.capability & WLAN_CAPABILITY_ESS)
804 			iwe.u.mode = IW_MODE_MASTER;
805 		else
806 			iwe.u.mode = IW_MODE_ADHOC;
807 		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
808 						  &iwe, IW_EV_UINT_LEN);
809 	}
810 
811 	buf = kmalloc(30, GFP_ATOMIC);
812 	if (buf) {
813 		memset(&iwe, 0, sizeof(iwe));
814 		iwe.cmd = IWEVCUSTOM;
815 		sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf));
816 		iwe.u.data.length = strlen(buf);
817 		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
818 						  &iwe, buf);
819 		memset(&iwe, 0, sizeof(iwe));
820 		iwe.cmd = IWEVCUSTOM;
821 		sprintf(buf, " Last beacon: %ums ago",
822 			elapsed_jiffies_msecs(bss->ts));
823 		iwe.u.data.length = strlen(buf);
824 		current_ev = iwe_stream_add_point(info, current_ev,
825 						  end_buf, &iwe, buf);
826 		kfree(buf);
827 	}
828 
829 	ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf);
830 
831 	return current_ev;
832 }
833 
834 
835 static int ieee80211_scan_results(struct cfg80211_registered_device *dev,
836 				  struct iw_request_info *info,
837 				  char *buf, size_t len)
838 {
839 	char *current_ev = buf;
840 	char *end_buf = buf + len;
841 	struct cfg80211_internal_bss *bss;
842 
843 	spin_lock_bh(&dev->bss_lock);
844 	cfg80211_bss_expire(dev);
845 
846 	list_for_each_entry(bss, &dev->bss_list, list) {
847 		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
848 			spin_unlock_bh(&dev->bss_lock);
849 			return -E2BIG;
850 		}
851 		current_ev = ieee80211_bss(&dev->wiphy, info, bss,
852 					   current_ev, end_buf);
853 	}
854 	spin_unlock_bh(&dev->bss_lock);
855 	return current_ev - buf;
856 }
857 
858 
859 int cfg80211_wext_giwscan(struct net_device *dev,
860 			  struct iw_request_info *info,
861 			  struct iw_point *data, char *extra)
862 {
863 	struct cfg80211_registered_device *rdev;
864 	int res;
865 
866 	if (!netif_running(dev))
867 		return -ENETDOWN;
868 
869 	rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
870 
871 	if (IS_ERR(rdev))
872 		return PTR_ERR(rdev);
873 
874 	if (rdev->scan_req) {
875 		res = -EAGAIN;
876 		goto out;
877 	}
878 
879 	res = ieee80211_scan_results(rdev, info, extra, data->length);
880 	data->length = 0;
881 	if (res >= 0) {
882 		data->length = res;
883 		res = 0;
884 	}
885 
886  out:
887 	cfg80211_put_dev(rdev);
888 	return res;
889 }
890 EXPORT_SYMBOL(cfg80211_wext_giwscan);
891 #endif
892