]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/wireless/scan.c
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
[karo-tx-linux.git] / net / wireless / scan.c
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/cfg80211-wext.h>
16 #include <net/iw_handler.h>
17 #include "core.h"
18 #include "nl80211.h"
19 #include "wext-compat.h"
20 #include "rdev-ops.h"
21
22 #define IEEE80211_SCAN_RESULT_EXPIRE    (30 * HZ)
23
24 static void bss_release(struct kref *ref)
25 {
26         struct cfg80211_internal_bss *bss;
27
28         bss = container_of(ref, struct cfg80211_internal_bss, ref);
29         if (bss->pub.free_priv)
30                 bss->pub.free_priv(&bss->pub);
31
32         if (bss->beacon_ies_allocated)
33                 kfree(bss->pub.beacon_ies);
34         if (bss->proberesp_ies_allocated)
35                 kfree(bss->pub.proberesp_ies);
36
37         BUG_ON(atomic_read(&bss->hold));
38
39         kfree(bss);
40 }
41
42 /* must hold dev->bss_lock! */
43 static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
44                                   struct cfg80211_internal_bss *bss)
45 {
46         list_del_init(&bss->list);
47         rb_erase(&bss->rbn, &dev->bss_tree);
48         kref_put(&bss->ref, bss_release);
49 }
50
51 /* must hold dev->bss_lock! */
52 static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
53                                   unsigned long expire_time)
54 {
55         struct cfg80211_internal_bss *bss, *tmp;
56         bool expired = false;
57
58         list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
59                 if (atomic_read(&bss->hold))
60                         continue;
61                 if (!time_after(expire_time, bss->ts))
62                         continue;
63
64                 __cfg80211_unlink_bss(dev, bss);
65                 expired = true;
66         }
67
68         if (expired)
69                 dev->bss_generation++;
70 }
71
72 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
73 {
74         struct cfg80211_scan_request *request;
75         struct wireless_dev *wdev;
76 #ifdef CONFIG_CFG80211_WEXT
77         union iwreq_data wrqu;
78 #endif
79
80         ASSERT_RDEV_LOCK(rdev);
81
82         request = rdev->scan_req;
83
84         if (!request)
85                 return;
86
87         wdev = request->wdev;
88
89         /*
90          * This must be before sending the other events!
91          * Otherwise, wpa_supplicant gets completely confused with
92          * wext events.
93          */
94         if (wdev->netdev)
95                 cfg80211_sme_scan_done(wdev->netdev);
96
97         if (request->aborted) {
98                 nl80211_send_scan_aborted(rdev, wdev);
99         } else {
100                 if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
101                         /* flush entries from previous scans */
102                         spin_lock_bh(&rdev->bss_lock);
103                         __cfg80211_bss_expire(rdev, request->scan_start);
104                         spin_unlock_bh(&rdev->bss_lock);
105                 }
106                 nl80211_send_scan_done(rdev, wdev);
107         }
108
109 #ifdef CONFIG_CFG80211_WEXT
110         if (wdev->netdev && !request->aborted) {
111                 memset(&wrqu, 0, sizeof(wrqu));
112
113                 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
114         }
115 #endif
116
117         if (wdev->netdev)
118                 dev_put(wdev->netdev);
119
120         rdev->scan_req = NULL;
121
122         /*
123          * OK. If this is invoked with "leak" then we can't
124          * free this ... but we've cleaned it up anyway. The
125          * driver failed to call the scan_done callback, so
126          * all bets are off, it might still be trying to use
127          * the scan request or not ... if it accesses the dev
128          * in there (it shouldn't anyway) then it may crash.
129          */
130         if (!leak)
131                 kfree(request);
132 }
133
134 void __cfg80211_scan_done(struct work_struct *wk)
135 {
136         struct cfg80211_registered_device *rdev;
137
138         rdev = container_of(wk, struct cfg80211_registered_device,
139                             scan_done_wk);
140
141         cfg80211_lock_rdev(rdev);
142         ___cfg80211_scan_done(rdev, false);
143         cfg80211_unlock_rdev(rdev);
144 }
145
146 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
147 {
148         trace_cfg80211_scan_done(request, aborted);
149         WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
150
151         request->aborted = aborted;
152         queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
153 }
154 EXPORT_SYMBOL(cfg80211_scan_done);
155
156 void __cfg80211_sched_scan_results(struct work_struct *wk)
157 {
158         struct cfg80211_registered_device *rdev;
159         struct cfg80211_sched_scan_request *request;
160
161         rdev = container_of(wk, struct cfg80211_registered_device,
162                             sched_scan_results_wk);
163
164         request = rdev->sched_scan_req;
165
166         mutex_lock(&rdev->sched_scan_mtx);
167
168         /* we don't have sched_scan_req anymore if the scan is stopping */
169         if (request) {
170                 if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
171                         /* flush entries from previous scans */
172                         spin_lock_bh(&rdev->bss_lock);
173                         __cfg80211_bss_expire(rdev, request->scan_start);
174                         spin_unlock_bh(&rdev->bss_lock);
175                         request->scan_start =
176                                 jiffies + msecs_to_jiffies(request->interval);
177                 }
178                 nl80211_send_sched_scan_results(rdev, request->dev);
179         }
180
181         mutex_unlock(&rdev->sched_scan_mtx);
182 }
183
184 void cfg80211_sched_scan_results(struct wiphy *wiphy)
185 {
186         trace_cfg80211_sched_scan_results(wiphy);
187         /* ignore if we're not scanning */
188         if (wiphy_to_dev(wiphy)->sched_scan_req)
189                 queue_work(cfg80211_wq,
190                            &wiphy_to_dev(wiphy)->sched_scan_results_wk);
191 }
192 EXPORT_SYMBOL(cfg80211_sched_scan_results);
193
194 void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
195 {
196         struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
197
198         trace_cfg80211_sched_scan_stopped(wiphy);
199
200         mutex_lock(&rdev->sched_scan_mtx);
201         __cfg80211_stop_sched_scan(rdev, true);
202         mutex_unlock(&rdev->sched_scan_mtx);
203 }
204 EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
205
206 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
207                                bool driver_initiated)
208 {
209         struct net_device *dev;
210
211         lockdep_assert_held(&rdev->sched_scan_mtx);
212
213         if (!rdev->sched_scan_req)
214                 return -ENOENT;
215
216         dev = rdev->sched_scan_req->dev;
217
218         if (!driver_initiated) {
219                 int err = rdev_sched_scan_stop(rdev, dev);
220                 if (err)
221                         return err;
222         }
223
224         nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
225
226         kfree(rdev->sched_scan_req);
227         rdev->sched_scan_req = NULL;
228
229         return 0;
230 }
231
232 /* must hold dev->bss_lock! */
233 void cfg80211_bss_age(struct cfg80211_registered_device *dev,
234                       unsigned long age_secs)
235 {
236         struct cfg80211_internal_bss *bss;
237         unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
238
239         list_for_each_entry(bss, &dev->bss_list, list) {
240                 bss->ts -= age_jiffies;
241         }
242 }
243
244 void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
245 {
246         __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
247 }
248
249 const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
250 {
251         while (len > 2 && ies[0] != eid) {
252                 len -= ies[1] + 2;
253                 ies += ies[1] + 2;
254         }
255         if (len < 2)
256                 return NULL;
257         if (len < 2 + ies[1])
258                 return NULL;
259         return ies;
260 }
261 EXPORT_SYMBOL(cfg80211_find_ie);
262
263 const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
264                                   const u8 *ies, int len)
265 {
266         struct ieee80211_vendor_ie *ie;
267         const u8 *pos = ies, *end = ies + len;
268         int ie_oui;
269
270         while (pos < end) {
271                 pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
272                                        end - pos);
273                 if (!pos)
274                         return NULL;
275
276                 if (end - pos < sizeof(*ie))
277                         return NULL;
278
279                 ie = (struct ieee80211_vendor_ie *)pos;
280                 ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
281                 if (ie_oui == oui && ie->oui_type == oui_type)
282                         return pos;
283
284                 pos += 2 + ie->len;
285         }
286         return NULL;
287 }
288 EXPORT_SYMBOL(cfg80211_find_vendor_ie);
289
290 static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
291 {
292         const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
293         const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
294
295         /* equal if both missing */
296         if (!ie1 && !ie2)
297                 return 0;
298         /* sort missing IE before (left of) present IE */
299         if (!ie1)
300                 return -1;
301         if (!ie2)
302                 return 1;
303
304         /* sort by length first, then by contents */
305         if (ie1[1] != ie2[1])
306                 return ie2[1] - ie1[1];
307         return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
308 }
309
310 static bool is_bss(struct cfg80211_bss *a,
311                    const u8 *bssid,
312                    const u8 *ssid, size_t ssid_len)
313 {
314         const u8 *ssidie;
315
316         if (bssid && !ether_addr_equal(a->bssid, bssid))
317                 return false;
318
319         if (!ssid)
320                 return true;
321
322         ssidie = cfg80211_find_ie(WLAN_EID_SSID,
323                                   a->information_elements,
324                                   a->len_information_elements);
325         if (!ssidie)
326                 return false;
327         if (ssidie[1] != ssid_len)
328                 return false;
329         return memcmp(ssidie + 2, ssid, ssid_len) == 0;
330 }
331
332 static bool is_mesh_bss(struct cfg80211_bss *a)
333 {
334         const u8 *ie;
335
336         if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
337                 return false;
338
339         ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
340                               a->information_elements,
341                               a->len_information_elements);
342         if (!ie)
343                 return false;
344
345         ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
346                               a->information_elements,
347                               a->len_information_elements);
348         if (!ie)
349                 return false;
350
351         return true;
352 }
353
354 static bool is_mesh(struct cfg80211_bss *a,
355                     const u8 *meshid, size_t meshidlen,
356                     const u8 *meshcfg)
357 {
358         const u8 *ie;
359
360         if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
361                 return false;
362
363         ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
364                               a->information_elements,
365                               a->len_information_elements);
366         if (!ie)
367                 return false;
368         if (ie[1] != meshidlen)
369                 return false;
370         if (memcmp(ie + 2, meshid, meshidlen))
371                 return false;
372
373         ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
374                               a->information_elements,
375                               a->len_information_elements);
376         if (!ie)
377                 return false;
378         if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
379                 return false;
380
381         /*
382          * Ignore mesh capability (last two bytes of the IE) when
383          * comparing since that may differ between stations taking
384          * part in the same mesh.
385          */
386         return memcmp(ie + 2, meshcfg,
387             sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
388 }
389
390 static int cmp_bss_core(struct cfg80211_bss *a,
391                         struct cfg80211_bss *b)
392 {
393         int r;
394
395         if (a->channel != b->channel)
396                 return b->channel->center_freq - a->channel->center_freq;
397
398         if (is_mesh_bss(a) && is_mesh_bss(b)) {
399                 r = cmp_ies(WLAN_EID_MESH_ID,
400                             a->information_elements,
401                             a->len_information_elements,
402                             b->information_elements,
403                             b->len_information_elements);
404                 if (r)
405                         return r;
406                 return cmp_ies(WLAN_EID_MESH_CONFIG,
407                                a->information_elements,
408                                a->len_information_elements,
409                                b->information_elements,
410                                b->len_information_elements);
411         }
412
413         /*
414          * we can't use compare_ether_addr here since we need a < > operator.
415          * The binary return value of compare_ether_addr isn't enough
416          */
417         return memcmp(a->bssid, b->bssid, sizeof(a->bssid));
418 }
419
420 static int cmp_bss(struct cfg80211_bss *a,
421                    struct cfg80211_bss *b)
422 {
423         int r;
424
425         r = cmp_bss_core(a, b);
426         if (r)
427                 return r;
428
429         return cmp_ies(WLAN_EID_SSID,
430                        a->information_elements,
431                        a->len_information_elements,
432                        b->information_elements,
433                        b->len_information_elements);
434 }
435
436 static int cmp_hidden_bss(struct cfg80211_bss *a,
437                    struct cfg80211_bss *b)
438 {
439         const u8 *ie1;
440         const u8 *ie2;
441         int i;
442         int r;
443
444         r = cmp_bss_core(a, b);
445         if (r)
446                 return r;
447
448         ie1 = cfg80211_find_ie(WLAN_EID_SSID,
449                         a->information_elements,
450                         a->len_information_elements);
451         ie2 = cfg80211_find_ie(WLAN_EID_SSID,
452                         b->information_elements,
453                         b->len_information_elements);
454
455         /* Key comparator must use same algorithm in any rb-tree
456          * search function (order is important), otherwise ordering
457          * of items in the tree is broken and search gives incorrect
458          * results. This code uses same order as cmp_ies() does. */
459
460         /* sort missing IE before (left of) present IE */
461         if (!ie1)
462                 return -1;
463         if (!ie2)
464                 return 1;
465
466         /* zero-size SSID is used as an indication of the hidden bss */
467         if (!ie2[1])
468                 return 0;
469
470         /* sort by length first, then by contents */
471         if (ie1[1] != ie2[1])
472                 return ie2[1] - ie1[1];
473
474         /* zeroed SSID ie is another indication of a hidden bss */
475         for (i = 0; i < ie2[1]; i++)
476                 if (ie2[i + 2])
477                         return -1;
478
479         return 0;
480 }
481
482 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
483                                       struct ieee80211_channel *channel,
484                                       const u8 *bssid,
485                                       const u8 *ssid, size_t ssid_len,
486                                       u16 capa_mask, u16 capa_val)
487 {
488         struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
489         struct cfg80211_internal_bss *bss, *res = NULL;
490         unsigned long now = jiffies;
491
492         trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
493                                capa_val);
494
495         spin_lock_bh(&dev->bss_lock);
496
497         list_for_each_entry(bss, &dev->bss_list, list) {
498                 if ((bss->pub.capability & capa_mask) != capa_val)
499                         continue;
500                 if (channel && bss->pub.channel != channel)
501                         continue;
502                 /* Don't get expired BSS structs */
503                 if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
504                     !atomic_read(&bss->hold))
505                         continue;
506                 if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
507                         res = bss;
508                         kref_get(&res->ref);
509                         break;
510                 }
511         }
512
513         spin_unlock_bh(&dev->bss_lock);
514         if (!res)
515                 return NULL;
516         trace_cfg80211_return_bss(&res->pub);
517         return &res->pub;
518 }
519 EXPORT_SYMBOL(cfg80211_get_bss);
520
521 struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
522                                        struct ieee80211_channel *channel,
523                                        const u8 *meshid, size_t meshidlen,
524                                        const u8 *meshcfg)
525 {
526         struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
527         struct cfg80211_internal_bss *bss, *res = NULL;
528
529         spin_lock_bh(&dev->bss_lock);
530
531         list_for_each_entry(bss, &dev->bss_list, list) {
532                 if (channel && bss->pub.channel != channel)
533                         continue;
534                 if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) {
535                         res = bss;
536                         kref_get(&res->ref);
537                         break;
538                 }
539         }
540
541         spin_unlock_bh(&dev->bss_lock);
542         if (!res)
543                 return NULL;
544         return &res->pub;
545 }
546 EXPORT_SYMBOL(cfg80211_get_mesh);
547
548
549 static void rb_insert_bss(struct cfg80211_registered_device *dev,
550                           struct cfg80211_internal_bss *bss)
551 {
552         struct rb_node **p = &dev->bss_tree.rb_node;
553         struct rb_node *parent = NULL;
554         struct cfg80211_internal_bss *tbss;
555         int cmp;
556
557         while (*p) {
558                 parent = *p;
559                 tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn);
560
561                 cmp = cmp_bss(&bss->pub, &tbss->pub);
562
563                 if (WARN_ON(!cmp)) {
564                         /* will sort of leak this BSS */
565                         return;
566                 }
567
568                 if (cmp < 0)
569                         p = &(*p)->rb_left;
570                 else
571                         p = &(*p)->rb_right;
572         }
573
574         rb_link_node(&bss->rbn, parent, p);
575         rb_insert_color(&bss->rbn, &dev->bss_tree);
576 }
577
578 static struct cfg80211_internal_bss *
579 rb_find_bss(struct cfg80211_registered_device *dev,
580             struct cfg80211_internal_bss *res)
581 {
582         struct rb_node *n = dev->bss_tree.rb_node;
583         struct cfg80211_internal_bss *bss;
584         int r;
585
586         while (n) {
587                 bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
588                 r = cmp_bss(&res->pub, &bss->pub);
589
590                 if (r == 0)
591                         return bss;
592                 else if (r < 0)
593                         n = n->rb_left;
594                 else
595                         n = n->rb_right;
596         }
597
598         return NULL;
599 }
600
601 static struct cfg80211_internal_bss *
602 rb_find_hidden_bss(struct cfg80211_registered_device *dev,
603             struct cfg80211_internal_bss *res)
604 {
605         struct rb_node *n = dev->bss_tree.rb_node;
606         struct cfg80211_internal_bss *bss;
607         int r;
608
609         while (n) {
610                 bss = rb_entry(n, struct cfg80211_internal_bss, rbn);
611                 r = cmp_hidden_bss(&res->pub, &bss->pub);
612
613                 if (r == 0)
614                         return bss;
615                 else if (r < 0)
616                         n = n->rb_left;
617                 else
618                         n = n->rb_right;
619         }
620
621         return NULL;
622 }
623
624 static void
625 copy_hidden_ies(struct cfg80211_internal_bss *res,
626                  struct cfg80211_internal_bss *hidden)
627 {
628         if (unlikely(res->pub.beacon_ies))
629                 return;
630         if (WARN_ON(!hidden->pub.beacon_ies))
631                 return;
632
633         res->pub.beacon_ies = kmalloc(hidden->pub.len_beacon_ies, GFP_ATOMIC);
634         if (unlikely(!res->pub.beacon_ies))
635                 return;
636
637         res->beacon_ies_allocated = true;
638         res->pub.len_beacon_ies = hidden->pub.len_beacon_ies;
639         memcpy(res->pub.beacon_ies, hidden->pub.beacon_ies,
640                         res->pub.len_beacon_ies);
641 }
642
643 static struct cfg80211_internal_bss *
644 cfg80211_bss_update(struct cfg80211_registered_device *dev,
645                     struct cfg80211_internal_bss *res)
646 {
647         struct cfg80211_internal_bss *found = NULL;
648
649         /*
650          * The reference to "res" is donated to this function.
651          */
652
653         if (WARN_ON(!res->pub.channel)) {
654                 kref_put(&res->ref, bss_release);
655                 return NULL;
656         }
657
658         res->ts = jiffies;
659
660         spin_lock_bh(&dev->bss_lock);
661
662         found = rb_find_bss(dev, res);
663
664         if (found) {
665                 found->pub.beacon_interval = res->pub.beacon_interval;
666                 found->pub.tsf = res->pub.tsf;
667                 found->pub.signal = res->pub.signal;
668                 found->pub.capability = res->pub.capability;
669                 found->ts = res->ts;
670
671                 /* Update IEs */
672                 if (res->pub.proberesp_ies) {
673                         size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
674                         size_t ielen = res->pub.len_proberesp_ies;
675
676                         if (found->pub.proberesp_ies &&
677                             !found->proberesp_ies_allocated &&
678                             ksize(found) >= used + ielen) {
679                                 memcpy(found->pub.proberesp_ies,
680                                        res->pub.proberesp_ies, ielen);
681                                 found->pub.len_proberesp_ies = ielen;
682                         } else {
683                                 u8 *ies = found->pub.proberesp_ies;
684
685                                 if (found->proberesp_ies_allocated)
686                                         ies = krealloc(ies, ielen, GFP_ATOMIC);
687                                 else
688                                         ies = kmalloc(ielen, GFP_ATOMIC);
689
690                                 if (ies) {
691                                         memcpy(ies, res->pub.proberesp_ies,
692                                                ielen);
693                                         found->proberesp_ies_allocated = true;
694                                         found->pub.proberesp_ies = ies;
695                                         found->pub.len_proberesp_ies = ielen;
696                                 }
697                         }
698
699                         /* Override possible earlier Beacon frame IEs */
700                         found->pub.information_elements =
701                                 found->pub.proberesp_ies;
702                         found->pub.len_information_elements =
703                                 found->pub.len_proberesp_ies;
704                 }
705                 if (res->pub.beacon_ies) {
706                         size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
707                         size_t ielen = res->pub.len_beacon_ies;
708                         bool information_elements_is_beacon_ies =
709                                 (found->pub.information_elements ==
710                                  found->pub.beacon_ies);
711
712                         if (found->pub.beacon_ies &&
713                             !found->beacon_ies_allocated &&
714                             ksize(found) >= used + ielen) {
715                                 memcpy(found->pub.beacon_ies,
716                                        res->pub.beacon_ies, ielen);
717                                 found->pub.len_beacon_ies = ielen;
718                         } else {
719                                 u8 *ies = found->pub.beacon_ies;
720
721                                 if (found->beacon_ies_allocated)
722                                         ies = krealloc(ies, ielen, GFP_ATOMIC);
723                                 else
724                                         ies = kmalloc(ielen, GFP_ATOMIC);
725
726                                 if (ies) {
727                                         memcpy(ies, res->pub.beacon_ies,
728                                                ielen);
729                                         found->beacon_ies_allocated = true;
730                                         found->pub.beacon_ies = ies;
731                                         found->pub.len_beacon_ies = ielen;
732                                 }
733                         }
734
735                         /* Override IEs if they were from a beacon before */
736                         if (information_elements_is_beacon_ies) {
737                                 found->pub.information_elements =
738                                         found->pub.beacon_ies;
739                                 found->pub.len_information_elements =
740                                         found->pub.len_beacon_ies;
741                         }
742                 }
743
744                 kref_put(&res->ref, bss_release);
745         } else {
746                 struct cfg80211_internal_bss *hidden;
747
748                 /* First check if the beacon is a probe response from
749                  * a hidden bss. If so, copy beacon ies (with nullified
750                  * ssid) into the probe response bss entry (with real ssid).
751                  * It is required basically for PSM implementation
752                  * (probe responses do not contain tim ie) */
753
754                 /* TODO: The code is not trying to update existing probe
755                  * response bss entries when beacon ies are
756                  * getting changed. */
757                 hidden = rb_find_hidden_bss(dev, res);
758                 if (hidden)
759                         copy_hidden_ies(res, hidden);
760
761                 /* this "consumes" the reference */
762                 list_add_tail(&res->list, &dev->bss_list);
763                 rb_insert_bss(dev, res);
764                 found = res;
765         }
766
767         dev->bss_generation++;
768         spin_unlock_bh(&dev->bss_lock);
769
770         kref_get(&found->ref);
771         return found;
772 }
773
774 static struct ieee80211_channel *
775 cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
776                          struct ieee80211_channel *channel)
777 {
778         const u8 *tmp;
779         u32 freq;
780         int channel_number = -1;
781
782         tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
783         if (tmp && tmp[1] == 1) {
784                 channel_number = tmp[2];
785         } else {
786                 tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
787                 if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
788                         struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
789
790                         channel_number = htop->primary_chan;
791                 }
792         }
793
794         if (channel_number < 0)
795                 return channel;
796
797         freq = ieee80211_channel_to_frequency(channel_number, channel->band);
798         channel = ieee80211_get_channel(wiphy, freq);
799         if (!channel)
800                 return NULL;
801         if (channel->flags & IEEE80211_CHAN_DISABLED)
802                 return NULL;
803         return channel;
804 }
805
806 struct cfg80211_bss*
807 cfg80211_inform_bss(struct wiphy *wiphy,
808                     struct ieee80211_channel *channel,
809                     const u8 *bssid, u64 tsf, u16 capability,
810                     u16 beacon_interval, const u8 *ie, size_t ielen,
811                     s32 signal, gfp_t gfp)
812 {
813         struct cfg80211_internal_bss *res;
814         size_t privsz;
815
816         if (WARN_ON(!wiphy))
817                 return NULL;
818
819         privsz = wiphy->bss_priv_size;
820
821         if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
822                         (signal < 0 || signal > 100)))
823                 return NULL;
824
825         channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel);
826         if (!channel)
827                 return NULL;
828
829         res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
830         if (!res)
831                 return NULL;
832
833         memcpy(res->pub.bssid, bssid, ETH_ALEN);
834         res->pub.channel = channel;
835         res->pub.signal = signal;
836         res->pub.tsf = tsf;
837         res->pub.beacon_interval = beacon_interval;
838         res->pub.capability = capability;
839         /*
840          * Since we do not know here whether the IEs are from a Beacon or Probe
841          * Response frame, we need to pick one of the options and only use it
842          * with the driver that does not provide the full Beacon/Probe Response
843          * frame. Use Beacon frame pointer to avoid indicating that this should
844          * override the information_elements pointer should we have received an
845          * earlier indication of Probe Response data.
846          *
847          * The initial buffer for the IEs is allocated with the BSS entry and
848          * is located after the private area.
849          */
850         res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz;
851         memcpy(res->pub.beacon_ies, ie, ielen);
852         res->pub.len_beacon_ies = ielen;
853         res->pub.information_elements = res->pub.beacon_ies;
854         res->pub.len_information_elements = res->pub.len_beacon_ies;
855
856         kref_init(&res->ref);
857
858         res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
859         if (!res)
860                 return NULL;
861
862         if (res->pub.capability & WLAN_CAPABILITY_ESS)
863                 regulatory_hint_found_beacon(wiphy, channel, gfp);
864
865         trace_cfg80211_return_bss(&res->pub);
866         /* cfg80211_bss_update gives us a referenced result */
867         return &res->pub;
868 }
869 EXPORT_SYMBOL(cfg80211_inform_bss);
870
871 struct cfg80211_bss *
872 cfg80211_inform_bss_frame(struct wiphy *wiphy,
873                           struct ieee80211_channel *channel,
874                           struct ieee80211_mgmt *mgmt, size_t len,
875                           s32 signal, gfp_t gfp)
876 {
877         struct cfg80211_internal_bss *res;
878         size_t ielen = len - offsetof(struct ieee80211_mgmt,
879                                       u.probe_resp.variable);
880         size_t privsz;
881
882         BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
883                         offsetof(struct ieee80211_mgmt, u.beacon.variable));
884
885         trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
886
887         if (WARN_ON(!mgmt))
888                 return NULL;
889
890         if (WARN_ON(!wiphy))
891                 return NULL;
892
893         if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
894                     (signal < 0 || signal > 100)))
895                 return NULL;
896
897         if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
898                 return NULL;
899
900         privsz = wiphy->bss_priv_size;
901
902         channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
903                                            ielen, channel);
904         if (!channel)
905                 return NULL;
906
907         res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
908         if (!res)
909                 return NULL;
910
911         memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN);
912         res->pub.channel = channel;
913         res->pub.signal = signal;
914         res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
915         res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
916         res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
917         /*
918          * The initial buffer for the IEs is allocated with the BSS entry and
919          * is located after the private area.
920          */
921         if (ieee80211_is_probe_resp(mgmt->frame_control)) {
922                 res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz;
923                 memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable,
924                        ielen);
925                 res->pub.len_proberesp_ies = ielen;
926                 res->pub.information_elements = res->pub.proberesp_ies;
927                 res->pub.len_information_elements = res->pub.len_proberesp_ies;
928         } else {
929                 res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
930                 memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
931                 res->pub.len_beacon_ies = ielen;
932                 res->pub.information_elements = res->pub.beacon_ies;
933                 res->pub.len_information_elements = res->pub.len_beacon_ies;
934         }
935
936         kref_init(&res->ref);
937
938         res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
939         if (!res)
940                 return NULL;
941
942         if (res->pub.capability & WLAN_CAPABILITY_ESS)
943                 regulatory_hint_found_beacon(wiphy, channel, gfp);
944
945         trace_cfg80211_return_bss(&res->pub);
946         /* cfg80211_bss_update gives us a referenced result */
947         return &res->pub;
948 }
949 EXPORT_SYMBOL(cfg80211_inform_bss_frame);
950
951 void cfg80211_ref_bss(struct cfg80211_bss *pub)
952 {
953         struct cfg80211_internal_bss *bss;
954
955         if (!pub)
956                 return;
957
958         bss = container_of(pub, struct cfg80211_internal_bss, pub);
959         kref_get(&bss->ref);
960 }
961 EXPORT_SYMBOL(cfg80211_ref_bss);
962
963 void cfg80211_put_bss(struct cfg80211_bss *pub)
964 {
965         struct cfg80211_internal_bss *bss;
966
967         if (!pub)
968                 return;
969
970         bss = container_of(pub, struct cfg80211_internal_bss, pub);
971         kref_put(&bss->ref, bss_release);
972 }
973 EXPORT_SYMBOL(cfg80211_put_bss);
974
975 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
976 {
977         struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
978         struct cfg80211_internal_bss *bss;
979
980         if (WARN_ON(!pub))
981                 return;
982
983         bss = container_of(pub, struct cfg80211_internal_bss, pub);
984
985         spin_lock_bh(&dev->bss_lock);
986         if (!list_empty(&bss->list)) {
987                 __cfg80211_unlink_bss(dev, bss);
988                 dev->bss_generation++;
989         }
990         spin_unlock_bh(&dev->bss_lock);
991 }
992 EXPORT_SYMBOL(cfg80211_unlink_bss);
993
994 #ifdef CONFIG_CFG80211_WEXT
995 int cfg80211_wext_siwscan(struct net_device *dev,
996                           struct iw_request_info *info,
997                           union iwreq_data *wrqu, char *extra)
998 {
999         struct cfg80211_registered_device *rdev;
1000         struct wiphy *wiphy;
1001         struct iw_scan_req *wreq = NULL;
1002         struct cfg80211_scan_request *creq = NULL;
1003         int i, err, n_channels = 0;
1004         enum ieee80211_band band;
1005
1006         if (!netif_running(dev))
1007                 return -ENETDOWN;
1008
1009         if (wrqu->data.length == sizeof(struct iw_scan_req))
1010                 wreq = (struct iw_scan_req *)extra;
1011
1012         rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
1013
1014         if (IS_ERR(rdev))
1015                 return PTR_ERR(rdev);
1016
1017         if (rdev->scan_req) {
1018                 err = -EBUSY;
1019                 goto out;
1020         }
1021
1022         wiphy = &rdev->wiphy;
1023
1024         /* Determine number of channels, needed to allocate creq */
1025         if (wreq && wreq->num_channels)
1026                 n_channels = wreq->num_channels;
1027         else {
1028                 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
1029                         if (wiphy->bands[band])
1030                                 n_channels += wiphy->bands[band]->n_channels;
1031         }
1032
1033         creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
1034                        n_channels * sizeof(void *),
1035                        GFP_ATOMIC);
1036         if (!creq) {
1037                 err = -ENOMEM;
1038                 goto out;
1039         }
1040
1041         creq->wiphy = wiphy;
1042         creq->wdev = dev->ieee80211_ptr;
1043         /* SSIDs come after channels */
1044         creq->ssids = (void *)&creq->channels[n_channels];
1045         creq->n_channels = n_channels;
1046         creq->n_ssids = 1;
1047         creq->scan_start = jiffies;
1048
1049         /* translate "Scan on frequencies" request */
1050         i = 0;
1051         for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1052                 int j;
1053
1054                 if (!wiphy->bands[band])
1055                         continue;
1056
1057                 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
1058                         /* ignore disabled channels */
1059                         if (wiphy->bands[band]->channels[j].flags &
1060                                                 IEEE80211_CHAN_DISABLED)
1061                                 continue;
1062
1063                         /* If we have a wireless request structure and the
1064                          * wireless request specifies frequencies, then search
1065                          * for the matching hardware channel.
1066                          */
1067                         if (wreq && wreq->num_channels) {
1068                                 int k;
1069                                 int wiphy_freq = wiphy->bands[band]->channels[j].center_freq;
1070                                 for (k = 0; k < wreq->num_channels; k++) {
1071                                         int wext_freq = cfg80211_wext_freq(wiphy, &wreq->channel_list[k]);
1072                                         if (wext_freq == wiphy_freq)
1073                                                 goto wext_freq_found;
1074                                 }
1075                                 goto wext_freq_not_found;
1076                         }
1077
1078                 wext_freq_found:
1079                         creq->channels[i] = &wiphy->bands[band]->channels[j];
1080                         i++;
1081                 wext_freq_not_found: ;
1082                 }
1083         }
1084         /* No channels found? */
1085         if (!i) {
1086                 err = -EINVAL;
1087                 goto out;
1088         }
1089
1090         /* Set real number of channels specified in creq->channels[] */
1091         creq->n_channels = i;
1092
1093         /* translate "Scan for SSID" request */
1094         if (wreq) {
1095                 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1096                         if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
1097                                 err = -EINVAL;
1098                                 goto out;
1099                         }
1100                         memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
1101                         creq->ssids[0].ssid_len = wreq->essid_len;
1102                 }
1103                 if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
1104                         creq->n_ssids = 0;
1105         }
1106
1107         for (i = 0; i < IEEE80211_NUM_BANDS; i++)
1108                 if (wiphy->bands[i])
1109                         creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
1110
1111         rdev->scan_req = creq;
1112         err = rdev_scan(rdev, creq);
1113         if (err) {
1114                 rdev->scan_req = NULL;
1115                 /* creq will be freed below */
1116         } else {
1117                 nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
1118                 /* creq now owned by driver */
1119                 creq = NULL;
1120                 dev_hold(dev);
1121         }
1122  out:
1123         kfree(creq);
1124         cfg80211_unlock_rdev(rdev);
1125         return err;
1126 }
1127 EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
1128
1129 static void ieee80211_scan_add_ies(struct iw_request_info *info,
1130                                    struct cfg80211_bss *bss,
1131                                    char **current_ev, char *end_buf)
1132 {
1133         u8 *pos, *end, *next;
1134         struct iw_event iwe;
1135
1136         if (!bss->information_elements ||
1137             !bss->len_information_elements)
1138                 return;
1139
1140         /*
1141          * If needed, fragment the IEs buffer (at IE boundaries) into short
1142          * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
1143          */
1144         pos = bss->information_elements;
1145         end = pos + bss->len_information_elements;
1146
1147         while (end - pos > IW_GENERIC_IE_MAX) {
1148                 next = pos + 2 + pos[1];
1149                 while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
1150                         next = next + 2 + next[1];
1151
1152                 memset(&iwe, 0, sizeof(iwe));
1153                 iwe.cmd = IWEVGENIE;
1154                 iwe.u.data.length = next - pos;
1155                 *current_ev = iwe_stream_add_point(info, *current_ev,
1156                                                    end_buf, &iwe, pos);
1157
1158                 pos = next;
1159         }
1160
1161         if (end > pos) {
1162                 memset(&iwe, 0, sizeof(iwe));
1163                 iwe.cmd = IWEVGENIE;
1164                 iwe.u.data.length = end - pos;
1165                 *current_ev = iwe_stream_add_point(info, *current_ev,
1166                                                    end_buf, &iwe, pos);
1167         }
1168 }
1169
1170 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
1171 {
1172         unsigned long end = jiffies;
1173
1174         if (end >= start)
1175                 return jiffies_to_msecs(end - start);
1176
1177         return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
1178 }
1179
1180 static char *
1181 ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1182               struct cfg80211_internal_bss *bss, char *current_ev,
1183               char *end_buf)
1184 {
1185         struct iw_event iwe;
1186         u8 *buf, *cfg, *p;
1187         u8 *ie = bss->pub.information_elements;
1188         int rem = bss->pub.len_information_elements, i, sig;
1189         bool ismesh = false;
1190
1191         memset(&iwe, 0, sizeof(iwe));
1192         iwe.cmd = SIOCGIWAP;
1193         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1194         memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
1195         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1196                                           IW_EV_ADDR_LEN);
1197
1198         memset(&iwe, 0, sizeof(iwe));
1199         iwe.cmd = SIOCGIWFREQ;
1200         iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
1201         iwe.u.freq.e = 0;
1202         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1203                                           IW_EV_FREQ_LEN);
1204
1205         memset(&iwe, 0, sizeof(iwe));
1206         iwe.cmd = SIOCGIWFREQ;
1207         iwe.u.freq.m = bss->pub.channel->center_freq;
1208         iwe.u.freq.e = 6;
1209         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1210                                           IW_EV_FREQ_LEN);
1211
1212         if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
1213                 memset(&iwe, 0, sizeof(iwe));
1214                 iwe.cmd = IWEVQUAL;
1215                 iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED |
1216                                      IW_QUAL_NOISE_INVALID |
1217                                      IW_QUAL_QUAL_UPDATED;
1218                 switch (wiphy->signal_type) {
1219                 case CFG80211_SIGNAL_TYPE_MBM:
1220                         sig = bss->pub.signal / 100;
1221                         iwe.u.qual.level = sig;
1222                         iwe.u.qual.updated |= IW_QUAL_DBM;
1223                         if (sig < -110)         /* rather bad */
1224                                 sig = -110;
1225                         else if (sig > -40)     /* perfect */
1226                                 sig = -40;
1227                         /* will give a range of 0 .. 70 */
1228                         iwe.u.qual.qual = sig + 110;
1229                         break;
1230                 case CFG80211_SIGNAL_TYPE_UNSPEC:
1231                         iwe.u.qual.level = bss->pub.signal;
1232                         /* will give range 0 .. 100 */
1233                         iwe.u.qual.qual = bss->pub.signal;
1234                         break;
1235                 default:
1236                         /* not reached */
1237                         break;
1238                 }
1239                 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1240                                                   &iwe, IW_EV_QUAL_LEN);
1241         }
1242
1243         memset(&iwe, 0, sizeof(iwe));
1244         iwe.cmd = SIOCGIWENCODE;
1245         if (bss->pub.capability & WLAN_CAPABILITY_PRIVACY)
1246                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1247         else
1248                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1249         iwe.u.data.length = 0;
1250         current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1251                                           &iwe, "");
1252
1253         while (rem >= 2) {
1254                 /* invalid data */
1255                 if (ie[1] > rem - 2)
1256                         break;
1257
1258                 switch (ie[0]) {
1259                 case WLAN_EID_SSID:
1260                         memset(&iwe, 0, sizeof(iwe));
1261                         iwe.cmd = SIOCGIWESSID;
1262                         iwe.u.data.length = ie[1];
1263                         iwe.u.data.flags = 1;
1264                         current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1265                                                           &iwe, ie + 2);
1266                         break;
1267                 case WLAN_EID_MESH_ID:
1268                         memset(&iwe, 0, sizeof(iwe));
1269                         iwe.cmd = SIOCGIWESSID;
1270                         iwe.u.data.length = ie[1];
1271                         iwe.u.data.flags = 1;
1272                         current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1273                                                           &iwe, ie + 2);
1274                         break;
1275                 case WLAN_EID_MESH_CONFIG:
1276                         ismesh = true;
1277                         if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
1278                                 break;
1279                         buf = kmalloc(50, GFP_ATOMIC);
1280                         if (!buf)
1281                                 break;
1282                         cfg = ie + 2;
1283                         memset(&iwe, 0, sizeof(iwe));
1284                         iwe.cmd = IWEVCUSTOM;
1285                         sprintf(buf, "Mesh Network Path Selection Protocol ID: "
1286                                 "0x%02X", cfg[0]);
1287                         iwe.u.data.length = strlen(buf);
1288                         current_ev = iwe_stream_add_point(info, current_ev,
1289                                                           end_buf,
1290                                                           &iwe, buf);
1291                         sprintf(buf, "Path Selection Metric ID: 0x%02X",
1292                                 cfg[1]);
1293                         iwe.u.data.length = strlen(buf);
1294                         current_ev = iwe_stream_add_point(info, current_ev,
1295                                                           end_buf,
1296                                                           &iwe, buf);
1297                         sprintf(buf, "Congestion Control Mode ID: 0x%02X",
1298                                 cfg[2]);
1299                         iwe.u.data.length = strlen(buf);
1300                         current_ev = iwe_stream_add_point(info, current_ev,
1301                                                           end_buf,
1302                                                           &iwe, buf);
1303                         sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
1304                         iwe.u.data.length = strlen(buf);
1305                         current_ev = iwe_stream_add_point(info, current_ev,
1306                                                           end_buf,
1307                                                           &iwe, buf);
1308                         sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
1309                         iwe.u.data.length = strlen(buf);
1310                         current_ev = iwe_stream_add_point(info, current_ev,
1311                                                           end_buf,
1312                                                           &iwe, buf);
1313                         sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
1314                         iwe.u.data.length = strlen(buf);
1315                         current_ev = iwe_stream_add_point(info, current_ev,
1316                                                           end_buf,
1317                                                           &iwe, buf);
1318                         sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
1319                         iwe.u.data.length = strlen(buf);
1320                         current_ev = iwe_stream_add_point(info, current_ev,
1321                                                           end_buf,
1322                                                           &iwe, buf);
1323                         kfree(buf);
1324                         break;
1325                 case WLAN_EID_SUPP_RATES:
1326                 case WLAN_EID_EXT_SUPP_RATES:
1327                         /* display all supported rates in readable format */
1328                         p = current_ev + iwe_stream_lcp_len(info);
1329
1330                         memset(&iwe, 0, sizeof(iwe));
1331                         iwe.cmd = SIOCGIWRATE;
1332                         /* Those two flags are ignored... */
1333                         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1334
1335                         for (i = 0; i < ie[1]; i++) {
1336                                 iwe.u.bitrate.value =
1337                                         ((ie[i + 2] & 0x7f) * 500000);
1338                                 p = iwe_stream_add_value(info, current_ev, p,
1339                                                 end_buf, &iwe, IW_EV_PARAM_LEN);
1340                         }
1341                         current_ev = p;
1342                         break;
1343                 }
1344                 rem -= ie[1] + 2;
1345                 ie += ie[1] + 2;
1346         }
1347
1348         if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) ||
1349             ismesh) {
1350                 memset(&iwe, 0, sizeof(iwe));
1351                 iwe.cmd = SIOCGIWMODE;
1352                 if (ismesh)
1353                         iwe.u.mode = IW_MODE_MESH;
1354                 else if (bss->pub.capability & WLAN_CAPABILITY_ESS)
1355                         iwe.u.mode = IW_MODE_MASTER;
1356                 else
1357                         iwe.u.mode = IW_MODE_ADHOC;
1358                 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1359                                                   &iwe, IW_EV_UINT_LEN);
1360         }
1361
1362         buf = kmalloc(30, GFP_ATOMIC);
1363         if (buf) {
1364                 memset(&iwe, 0, sizeof(iwe));
1365                 iwe.cmd = IWEVCUSTOM;
1366                 sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf));
1367                 iwe.u.data.length = strlen(buf);
1368                 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1369                                                   &iwe, buf);
1370                 memset(&iwe, 0, sizeof(iwe));
1371                 iwe.cmd = IWEVCUSTOM;
1372                 sprintf(buf, " Last beacon: %ums ago",
1373                         elapsed_jiffies_msecs(bss->ts));
1374                 iwe.u.data.length = strlen(buf);
1375                 current_ev = iwe_stream_add_point(info, current_ev,
1376                                                   end_buf, &iwe, buf);
1377                 kfree(buf);
1378         }
1379
1380         ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf);
1381
1382         return current_ev;
1383 }
1384
1385
1386 static int ieee80211_scan_results(struct cfg80211_registered_device *dev,
1387                                   struct iw_request_info *info,
1388                                   char *buf, size_t len)
1389 {
1390         char *current_ev = buf;
1391         char *end_buf = buf + len;
1392         struct cfg80211_internal_bss *bss;
1393
1394         spin_lock_bh(&dev->bss_lock);
1395         cfg80211_bss_expire(dev);
1396
1397         list_for_each_entry(bss, &dev->bss_list, list) {
1398                 if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
1399                         spin_unlock_bh(&dev->bss_lock);
1400                         return -E2BIG;
1401                 }
1402                 current_ev = ieee80211_bss(&dev->wiphy, info, bss,
1403                                            current_ev, end_buf);
1404         }
1405         spin_unlock_bh(&dev->bss_lock);
1406         return current_ev - buf;
1407 }
1408
1409
1410 int cfg80211_wext_giwscan(struct net_device *dev,
1411                           struct iw_request_info *info,
1412                           struct iw_point *data, char *extra)
1413 {
1414         struct cfg80211_registered_device *rdev;
1415         int res;
1416
1417         if (!netif_running(dev))
1418                 return -ENETDOWN;
1419
1420         rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
1421
1422         if (IS_ERR(rdev))
1423                 return PTR_ERR(rdev);
1424
1425         if (rdev->scan_req) {
1426                 res = -EAGAIN;
1427                 goto out;
1428         }
1429
1430         res = ieee80211_scan_results(rdev, info, extra, data->length);
1431         data->length = 0;
1432         if (res >= 0) {
1433                 data->length = res;
1434                 res = 0;
1435         }
1436
1437  out:
1438         cfg80211_unlock_rdev(rdev);
1439         return res;
1440 }
1441 EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
1442 #endif