aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/scan.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/wireless/scan.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r--net/wireless/scan.c230
1 files changed, 155 insertions, 75 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index e5f92ee758f4..a026c6d56bd3 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -4,6 +4,7 @@
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/slab.h>
7#include <linux/module.h> 8#include <linux/module.h>
8#include <linux/netdevice.h> 9#include <linux/netdevice.h>
9#include <linux/wireless.h> 10#include <linux/wireless.h>
@@ -22,7 +23,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
22{ 23{
23 struct cfg80211_scan_request *request; 24 struct cfg80211_scan_request *request;
24 struct net_device *dev; 25 struct net_device *dev;
25#ifdef CONFIG_WIRELESS_EXT 26#ifdef CONFIG_CFG80211_WEXT
26 union iwreq_data wrqu; 27 union iwreq_data wrqu;
27#endif 28#endif
28 29
@@ -47,7 +48,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
47 else 48 else
48 nl80211_send_scan_done(rdev, dev); 49 nl80211_send_scan_done(rdev, dev);
49 50
50#ifdef CONFIG_WIRELESS_EXT 51#ifdef CONFIG_CFG80211_WEXT
51 if (!request->aborted) { 52 if (!request->aborted) {
52 memset(&wrqu, 0, sizeof(wrqu)); 53 memset(&wrqu, 0, sizeof(wrqu));
53 54
@@ -88,7 +89,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
88 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 89 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
89 90
90 request->aborted = aborted; 91 request->aborted = aborted;
91 schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); 92 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
92} 93}
93EXPORT_SYMBOL(cfg80211_scan_done); 94EXPORT_SYMBOL(cfg80211_scan_done);
94 95
@@ -100,8 +101,10 @@ static void bss_release(struct kref *ref)
100 if (bss->pub.free_priv) 101 if (bss->pub.free_priv)
101 bss->pub.free_priv(&bss->pub); 102 bss->pub.free_priv(&bss->pub);
102 103
103 if (bss->ies_allocated) 104 if (bss->beacon_ies_allocated)
104 kfree(bss->pub.information_elements); 105 kfree(bss->pub.beacon_ies);
106 if (bss->proberesp_ies_allocated)
107 kfree(bss->pub.proberesp_ies);
105 108
106 BUG_ON(atomic_read(&bss->hold)); 109 BUG_ON(atomic_read(&bss->hold));
107 110
@@ -141,9 +144,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
141 dev->bss_generation++; 144 dev->bss_generation++;
142} 145}
143 146
144static u8 *find_ie(u8 num, u8 *ies, int len) 147const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
145{ 148{
146 while (len > 2 && ies[0] != num) { 149 while (len > 2 && ies[0] != eid) {
147 len -= ies[1] + 2; 150 len -= ies[1] + 2;
148 ies += ies[1] + 2; 151 ies += ies[1] + 2;
149 } 152 }
@@ -153,11 +156,12 @@ static u8 *find_ie(u8 num, u8 *ies, int len)
153 return NULL; 156 return NULL;
154 return ies; 157 return ies;
155} 158}
159EXPORT_SYMBOL(cfg80211_find_ie);
156 160
157static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) 161static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
158{ 162{
159 const u8 *ie1 = find_ie(num, ies1, len1); 163 const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
160 const u8 *ie2 = find_ie(num, ies2, len2); 164 const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
161 int r; 165 int r;
162 166
163 if (!ie1 && !ie2) 167 if (!ie1 && !ie2)
@@ -183,9 +187,9 @@ static bool is_bss(struct cfg80211_bss *a,
183 if (!ssid) 187 if (!ssid)
184 return true; 188 return true;
185 189
186 ssidie = find_ie(WLAN_EID_SSID, 190 ssidie = cfg80211_find_ie(WLAN_EID_SSID,
187 a->information_elements, 191 a->information_elements,
188 a->len_information_elements); 192 a->len_information_elements);
189 if (!ssidie) 193 if (!ssidie)
190 return false; 194 return false;
191 if (ssidie[1] != ssid_len) 195 if (ssidie[1] != ssid_len)
@@ -202,9 +206,9 @@ static bool is_mesh(struct cfg80211_bss *a,
202 if (!is_zero_ether_addr(a->bssid)) 206 if (!is_zero_ether_addr(a->bssid))
203 return false; 207 return false;
204 208
205 ie = find_ie(WLAN_EID_MESH_ID, 209 ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
206 a->information_elements, 210 a->information_elements,
207 a->len_information_elements); 211 a->len_information_elements);
208 if (!ie) 212 if (!ie)
209 return false; 213 return false;
210 if (ie[1] != meshidlen) 214 if (ie[1] != meshidlen)
@@ -212,12 +216,12 @@ static bool is_mesh(struct cfg80211_bss *a,
212 if (memcmp(ie + 2, meshid, meshidlen)) 216 if (memcmp(ie + 2, meshid, meshidlen))
213 return false; 217 return false;
214 218
215 ie = find_ie(WLAN_EID_MESH_CONFIG, 219 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
216 a->information_elements, 220 a->information_elements,
217 a->len_information_elements); 221 a->len_information_elements);
218 if (!ie) 222 if (!ie)
219 return false; 223 return false;
220 if (ie[1] != IEEE80211_MESH_CONFIG_LEN) 224 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
221 return false; 225 return false;
222 226
223 /* 227 /*
@@ -225,7 +229,8 @@ static bool is_mesh(struct cfg80211_bss *a,
225 * comparing since that may differ between stations taking 229 * comparing since that may differ between stations taking
226 * part in the same mesh. 230 * part in the same mesh.
227 */ 231 */
228 return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0; 232 return memcmp(ie + 2, meshcfg,
233 sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
229} 234}
230 235
231static int cmp_bss(struct cfg80211_bss *a, 236static int cmp_bss(struct cfg80211_bss *a,
@@ -374,8 +379,7 @@ rb_find_bss(struct cfg80211_registered_device *dev,
374 379
375static struct cfg80211_internal_bss * 380static struct cfg80211_internal_bss *
376cfg80211_bss_update(struct cfg80211_registered_device *dev, 381cfg80211_bss_update(struct cfg80211_registered_device *dev,
377 struct cfg80211_internal_bss *res, 382 struct cfg80211_internal_bss *res)
378 bool overwrite)
379{ 383{
380 struct cfg80211_internal_bss *found = NULL; 384 struct cfg80211_internal_bss *found = NULL;
381 const u8 *meshid, *meshcfg; 385 const u8 *meshid, *meshcfg;
@@ -393,13 +397,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
393 397
394 if (is_zero_ether_addr(res->pub.bssid)) { 398 if (is_zero_ether_addr(res->pub.bssid)) {
395 /* must be mesh, verify */ 399 /* must be mesh, verify */
396 meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements, 400 meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
397 res->pub.len_information_elements); 401 res->pub.information_elements,
398 meshcfg = find_ie(WLAN_EID_MESH_CONFIG, 402 res->pub.len_information_elements);
399 res->pub.information_elements, 403 meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
400 res->pub.len_information_elements); 404 res->pub.information_elements,
405 res->pub.len_information_elements);
401 if (!meshid || !meshcfg || 406 if (!meshid || !meshcfg ||
402 meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) { 407 meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
403 /* bogus mesh */ 408 /* bogus mesh */
404 kref_put(&res->ref, bss_release); 409 kref_put(&res->ref, bss_release);
405 return NULL; 410 return NULL;
@@ -417,28 +422,64 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
417 found->pub.capability = res->pub.capability; 422 found->pub.capability = res->pub.capability;
418 found->ts = res->ts; 423 found->ts = res->ts;
419 424
420 /* overwrite IEs */ 425 /* Update IEs */
421 if (overwrite) { 426 if (res->pub.proberesp_ies) {
422 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 427 size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
423 size_t ielen = res->pub.len_information_elements; 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);
424 443
425 if (!found->ies_allocated && ksize(found) >= used + ielen) { 444 if (ies) {
426 memcpy(found->pub.information_elements, 445 memcpy(ies, res->pub.proberesp_ies,
427 res->pub.information_elements, ielen); 446 ielen);
428 found->pub.len_information_elements = 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;
429 } else { 469 } else {
430 u8 *ies = found->pub.information_elements; 470 u8 *ies = found->pub.beacon_ies;
431 471
432 if (found->ies_allocated) 472 if (found->beacon_ies_allocated)
433 ies = krealloc(ies, ielen, GFP_ATOMIC); 473 ies = krealloc(ies, ielen, GFP_ATOMIC);
434 else 474 else
435 ies = kmalloc(ielen, GFP_ATOMIC); 475 ies = kmalloc(ielen, GFP_ATOMIC);
436 476
437 if (ies) { 477 if (ies) {
438 memcpy(ies, res->pub.information_elements, ielen); 478 memcpy(ies, res->pub.beacon_ies,
439 found->ies_allocated = true; 479 ielen);
440 found->pub.information_elements = ies; 480 found->beacon_ies_allocated = true;
441 found->pub.len_information_elements = ielen; 481 found->pub.beacon_ies = ies;
482 found->pub.len_beacon_ies = ielen;
442 } 483 }
443 } 484 }
444 } 485 }
@@ -488,14 +529,26 @@ cfg80211_inform_bss(struct wiphy *wiphy,
488 res->pub.tsf = timestamp; 529 res->pub.tsf = timestamp;
489 res->pub.beacon_interval = beacon_interval; 530 res->pub.beacon_interval = beacon_interval;
490 res->pub.capability = capability; 531 res->pub.capability = capability;
491 /* point to after the private area */ 532 /*
492 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; 533 * Since we do not know here whether the IEs are from a Beacon or Probe
493 memcpy(res->pub.information_elements, ie, ielen); 534 * Response frame, we need to pick one of the options and only use it
494 res->pub.len_information_elements = ielen; 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;
495 548
496 kref_init(&res->ref); 549 kref_init(&res->ref);
497 550
498 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0); 551 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
499 if (!res) 552 if (!res)
500 return NULL; 553 return NULL;
501 554
@@ -516,7 +569,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
516 struct cfg80211_internal_bss *res; 569 struct cfg80211_internal_bss *res;
517 size_t ielen = len - offsetof(struct ieee80211_mgmt, 570 size_t ielen = len - offsetof(struct ieee80211_mgmt,
518 u.probe_resp.variable); 571 u.probe_resp.variable);
519 bool overwrite;
520 size_t privsz = wiphy->bss_priv_size; 572 size_t privsz = wiphy->bss_priv_size;
521 573
522 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && 574 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
@@ -537,16 +589,28 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
537 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); 589 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
538 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 590 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
539 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 591 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
540 /* point to after the private area */ 592 /*
541 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; 593 * The initial buffer for the IEs is allocated with the BSS entry and
542 memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen); 594 * is located after the private area.
543 res->pub.len_information_elements = ielen; 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 }
544 610
545 kref_init(&res->ref); 611 kref_init(&res->ref);
546 612
547 overwrite = ieee80211_is_probe_resp(mgmt->frame_control); 613 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
548
549 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite);
550 if (!res) 614 if (!res)
551 return NULL; 615 return NULL;
552 616
@@ -592,7 +656,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
592} 656}
593EXPORT_SYMBOL(cfg80211_unlink_bss); 657EXPORT_SYMBOL(cfg80211_unlink_bss);
594 658
595#ifdef CONFIG_WIRELESS_EXT 659#ifdef CONFIG_CFG80211_WEXT
596int cfg80211_wext_siwscan(struct net_device *dev, 660int cfg80211_wext_siwscan(struct net_device *dev,
597 struct iw_request_info *info, 661 struct iw_request_info *info,
598 union iwreq_data *wrqu, char *extra) 662 union iwreq_data *wrqu, char *extra)
@@ -600,7 +664,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
600 struct cfg80211_registered_device *rdev; 664 struct cfg80211_registered_device *rdev;
601 struct wiphy *wiphy; 665 struct wiphy *wiphy;
602 struct iw_scan_req *wreq = NULL; 666 struct iw_scan_req *wreq = NULL;
603 struct cfg80211_scan_request *creq; 667 struct cfg80211_scan_request *creq = NULL;
604 int i, err, n_channels = 0; 668 int i, err, n_channels = 0;
605 enum ieee80211_band band; 669 enum ieee80211_band band;
606 670
@@ -650,9 +714,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
650 i = 0; 714 i = 0;
651 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 715 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
652 int j; 716 int j;
717
653 if (!wiphy->bands[band]) 718 if (!wiphy->bands[band])
654 continue; 719 continue;
720
655 for (j = 0; j < wiphy->bands[band]->n_channels; j++) { 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;
656 726
657 /* If we have a wireless request structure and the 727 /* If we have a wireless request structure and the
658 * wireless request specifies frequencies, then search 728 * wireless request specifies frequencies, then search
@@ -687,8 +757,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
687 /* translate "Scan for SSID" request */ 757 /* translate "Scan for SSID" request */
688 if (wreq) { 758 if (wreq) {
689 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 759 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
690 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) 760 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
691 return -EINVAL; 761 err = -EINVAL;
762 goto out;
763 }
692 memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); 764 memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
693 creq->ssids[0].ssid_len = wreq->essid_len; 765 creq->ssids[0].ssid_len = wreq->essid_len;
694 } 766 }
@@ -700,12 +772,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
700 err = rdev->ops->scan(wiphy, dev, creq); 772 err = rdev->ops->scan(wiphy, dev, creq);
701 if (err) { 773 if (err) {
702 rdev->scan_req = NULL; 774 rdev->scan_req = NULL;
703 kfree(creq); 775 /* creq will be freed below */
704 } else { 776 } else {
705 nl80211_send_scan_start(rdev, dev); 777 nl80211_send_scan_start(rdev, dev);
778 /* creq now owned by driver */
779 creq = NULL;
706 dev_hold(dev); 780 dev_hold(dev);
707 } 781 }
708 out: 782 out:
783 kfree(creq);
709 cfg80211_unlock_rdev(rdev); 784 cfg80211_unlock_rdev(rdev);
710 return err; 785 return err;
711} 786}
@@ -859,7 +934,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
859 break; 934 break;
860 case WLAN_EID_MESH_CONFIG: 935 case WLAN_EID_MESH_CONFIG:
861 ismesh = true; 936 ismesh = true;
862 if (ie[1] != IEEE80211_MESH_CONFIG_LEN) 937 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
863 break; 938 break;
864 buf = kmalloc(50, GFP_ATOMIC); 939 buf = kmalloc(50, GFP_ATOMIC);
865 if (!buf) 940 if (!buf)
@@ -867,35 +942,40 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
867 cfg = ie + 2; 942 cfg = ie + 2;
868 memset(&iwe, 0, sizeof(iwe)); 943 memset(&iwe, 0, sizeof(iwe));
869 iwe.cmd = IWEVCUSTOM; 944 iwe.cmd = IWEVCUSTOM;
870 sprintf(buf, "Mesh network (version %d)", cfg[0]); 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]);
871 iwe.u.data.length = strlen(buf); 959 iwe.u.data.length = strlen(buf);
872 current_ev = iwe_stream_add_point(info, current_ev, 960 current_ev = iwe_stream_add_point(info, current_ev,
873 end_buf, 961 end_buf,
874 &iwe, buf); 962 &iwe, buf);
875 sprintf(buf, "Path Selection Protocol ID: " 963 sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
876 "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
877 cfg[4]);
878 iwe.u.data.length = strlen(buf); 964 iwe.u.data.length = strlen(buf);
879 current_ev = iwe_stream_add_point(info, current_ev, 965 current_ev = iwe_stream_add_point(info, current_ev,
880 end_buf, 966 end_buf,
881 &iwe, buf); 967 &iwe, buf);
882 sprintf(buf, "Path Selection Metric ID: " 968 sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
883 "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
884 cfg[8]);
885 iwe.u.data.length = strlen(buf); 969 iwe.u.data.length = strlen(buf);
886 current_ev = iwe_stream_add_point(info, current_ev, 970 current_ev = iwe_stream_add_point(info, current_ev,
887 end_buf, 971 end_buf,
888 &iwe, buf); 972 &iwe, buf);
889 sprintf(buf, "Congestion Control Mode ID: " 973 sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
890 "0x%02X%02X%02X%02X", cfg[9], cfg[10],
891 cfg[11], cfg[12]);
892 iwe.u.data.length = strlen(buf); 974 iwe.u.data.length = strlen(buf);
893 current_ev = iwe_stream_add_point(info, current_ev, 975 current_ev = iwe_stream_add_point(info, current_ev,
894 end_buf, 976 end_buf,
895 &iwe, buf); 977 &iwe, buf);
896 sprintf(buf, "Channel Precedence: " 978 sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
897 "0x%02X%02X%02X%02X", cfg[13], cfg[14],
898 cfg[15], cfg[16]);
899 iwe.u.data.length = strlen(buf); 979 iwe.u.data.length = strlen(buf);
900 current_ev = iwe_stream_add_point(info, current_ev, 980 current_ev = iwe_stream_add_point(info, current_ev,
901 end_buf, 981 end_buf,
@@ -925,8 +1005,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
925 ie += ie[1] + 2; 1005 ie += ie[1] + 2;
926 } 1006 }
927 1007
928 if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) 1008 if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) ||
929 || ismesh) { 1009 ismesh) {
930 memset(&iwe, 0, sizeof(iwe)); 1010 memset(&iwe, 0, sizeof(iwe));
931 iwe.cmd = SIOCGIWMODE; 1011 iwe.cmd = SIOCGIWMODE;
932 if (ismesh) 1012 if (ismesh)