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