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