diff options
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r-- | net/wireless/scan.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e5f92ee758f4..0c2cbbebca95 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -22,7 +22,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
22 | { | 22 | { |
23 | struct cfg80211_scan_request *request; | 23 | struct cfg80211_scan_request *request; |
24 | struct net_device *dev; | 24 | struct net_device *dev; |
25 | #ifdef CONFIG_WIRELESS_EXT | 25 | #ifdef CONFIG_CFG80211_WEXT |
26 | union iwreq_data wrqu; | 26 | union iwreq_data wrqu; |
27 | #endif | 27 | #endif |
28 | 28 | ||
@@ -47,7 +47,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
47 | else | 47 | else |
48 | nl80211_send_scan_done(rdev, dev); | 48 | nl80211_send_scan_done(rdev, dev); |
49 | 49 | ||
50 | #ifdef CONFIG_WIRELESS_EXT | 50 | #ifdef CONFIG_CFG80211_WEXT |
51 | if (!request->aborted) { | 51 | if (!request->aborted) { |
52 | memset(&wrqu, 0, sizeof(wrqu)); | 52 | memset(&wrqu, 0, sizeof(wrqu)); |
53 | 53 | ||
@@ -88,7 +88,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | |||
88 | WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); | 88 | WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); |
89 | 89 | ||
90 | request->aborted = aborted; | 90 | request->aborted = aborted; |
91 | schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); | 91 | queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); |
92 | } | 92 | } |
93 | EXPORT_SYMBOL(cfg80211_scan_done); | 93 | EXPORT_SYMBOL(cfg80211_scan_done); |
94 | 94 | ||
@@ -217,7 +217,7 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
217 | a->len_information_elements); | 217 | a->len_information_elements); |
218 | if (!ie) | 218 | if (!ie) |
219 | return false; | 219 | return false; |
220 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | 220 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
221 | return false; | 221 | return false; |
222 | 222 | ||
223 | /* | 223 | /* |
@@ -225,7 +225,8 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
225 | * comparing since that may differ between stations taking | 225 | * comparing since that may differ between stations taking |
226 | * part in the same mesh. | 226 | * part in the same mesh. |
227 | */ | 227 | */ |
228 | return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0; | 228 | return memcmp(ie + 2, meshcfg, |
229 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; | ||
229 | } | 230 | } |
230 | 231 | ||
231 | static int cmp_bss(struct cfg80211_bss *a, | 232 | static int cmp_bss(struct cfg80211_bss *a, |
@@ -399,7 +400,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
399 | res->pub.information_elements, | 400 | res->pub.information_elements, |
400 | res->pub.len_information_elements); | 401 | res->pub.len_information_elements); |
401 | if (!meshid || !meshcfg || | 402 | if (!meshid || !meshcfg || |
402 | meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) { | 403 | meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { |
403 | /* bogus mesh */ | 404 | /* bogus mesh */ |
404 | kref_put(&res->ref, bss_release); | 405 | kref_put(&res->ref, bss_release); |
405 | return NULL; | 406 | return NULL; |
@@ -592,7 +593,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
592 | } | 593 | } |
593 | EXPORT_SYMBOL(cfg80211_unlink_bss); | 594 | EXPORT_SYMBOL(cfg80211_unlink_bss); |
594 | 595 | ||
595 | #ifdef CONFIG_WIRELESS_EXT | 596 | #ifdef CONFIG_CFG80211_WEXT |
596 | int cfg80211_wext_siwscan(struct net_device *dev, | 597 | int cfg80211_wext_siwscan(struct net_device *dev, |
597 | struct iw_request_info *info, | 598 | struct iw_request_info *info, |
598 | union iwreq_data *wrqu, char *extra) | 599 | union iwreq_data *wrqu, char *extra) |
@@ -600,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
600 | struct cfg80211_registered_device *rdev; | 601 | struct cfg80211_registered_device *rdev; |
601 | struct wiphy *wiphy; | 602 | struct wiphy *wiphy; |
602 | struct iw_scan_req *wreq = NULL; | 603 | struct iw_scan_req *wreq = NULL; |
603 | struct cfg80211_scan_request *creq; | 604 | struct cfg80211_scan_request *creq = NULL; |
604 | int i, err, n_channels = 0; | 605 | int i, err, n_channels = 0; |
605 | enum ieee80211_band band; | 606 | enum ieee80211_band band; |
606 | 607 | ||
@@ -650,9 +651,15 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
650 | i = 0; | 651 | i = 0; |
651 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 652 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
652 | int j; | 653 | int j; |
654 | |||
653 | if (!wiphy->bands[band]) | 655 | if (!wiphy->bands[band]) |
654 | continue; | 656 | continue; |
657 | |||
655 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { | 658 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { |
659 | /* ignore disabled channels */ | ||
660 | if (wiphy->bands[band]->channels[j].flags & | ||
661 | IEEE80211_CHAN_DISABLED) | ||
662 | continue; | ||
656 | 663 | ||
657 | /* If we have a wireless request structure and the | 664 | /* If we have a wireless request structure and the |
658 | * wireless request specifies frequencies, then search | 665 | * wireless request specifies frequencies, then search |
@@ -687,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
687 | /* translate "Scan for SSID" request */ | 694 | /* translate "Scan for SSID" request */ |
688 | if (wreq) { | 695 | if (wreq) { |
689 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 696 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
690 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) | 697 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { |
691 | return -EINVAL; | 698 | err = -EINVAL; |
699 | goto out; | ||
700 | } | ||
692 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); | 701 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); |
693 | creq->ssids[0].ssid_len = wreq->essid_len; | 702 | creq->ssids[0].ssid_len = wreq->essid_len; |
694 | } | 703 | } |
@@ -700,12 +709,15 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
700 | err = rdev->ops->scan(wiphy, dev, creq); | 709 | err = rdev->ops->scan(wiphy, dev, creq); |
701 | if (err) { | 710 | if (err) { |
702 | rdev->scan_req = NULL; | 711 | rdev->scan_req = NULL; |
703 | kfree(creq); | 712 | /* creq will be freed below */ |
704 | } else { | 713 | } else { |
705 | nl80211_send_scan_start(rdev, dev); | 714 | nl80211_send_scan_start(rdev, dev); |
715 | /* creq now owned by driver */ | ||
716 | creq = NULL; | ||
706 | dev_hold(dev); | 717 | dev_hold(dev); |
707 | } | 718 | } |
708 | out: | 719 | out: |
720 | kfree(creq); | ||
709 | cfg80211_unlock_rdev(rdev); | 721 | cfg80211_unlock_rdev(rdev); |
710 | return err; | 722 | return err; |
711 | } | 723 | } |
@@ -859,7 +871,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
859 | break; | 871 | break; |
860 | case WLAN_EID_MESH_CONFIG: | 872 | case WLAN_EID_MESH_CONFIG: |
861 | ismesh = true; | 873 | ismesh = true; |
862 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | 874 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
863 | break; | 875 | break; |
864 | buf = kmalloc(50, GFP_ATOMIC); | 876 | buf = kmalloc(50, GFP_ATOMIC); |
865 | if (!buf) | 877 | if (!buf) |
@@ -867,35 +879,40 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
867 | cfg = ie + 2; | 879 | cfg = ie + 2; |
868 | memset(&iwe, 0, sizeof(iwe)); | 880 | memset(&iwe, 0, sizeof(iwe)); |
869 | iwe.cmd = IWEVCUSTOM; | 881 | iwe.cmd = IWEVCUSTOM; |
870 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 882 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " |
883 | "0x%02X", cfg[0]); | ||
884 | iwe.u.data.length = strlen(buf); | ||
885 | current_ev = iwe_stream_add_point(info, current_ev, | ||
886 | end_buf, | ||
887 | &iwe, buf); | ||
888 | sprintf(buf, "Path Selection Metric ID: 0x%02X", | ||
889 | cfg[1]); | ||
890 | iwe.u.data.length = strlen(buf); | ||
891 | current_ev = iwe_stream_add_point(info, current_ev, | ||
892 | end_buf, | ||
893 | &iwe, buf); | ||
894 | sprintf(buf, "Congestion Control Mode ID: 0x%02X", | ||
895 | cfg[2]); | ||
871 | iwe.u.data.length = strlen(buf); | 896 | iwe.u.data.length = strlen(buf); |
872 | current_ev = iwe_stream_add_point(info, current_ev, | 897 | current_ev = iwe_stream_add_point(info, current_ev, |
873 | end_buf, | 898 | end_buf, |
874 | &iwe, buf); | 899 | &iwe, buf); |
875 | sprintf(buf, "Path Selection Protocol ID: " | 900 | 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); | 901 | iwe.u.data.length = strlen(buf); |
879 | current_ev = iwe_stream_add_point(info, current_ev, | 902 | current_ev = iwe_stream_add_point(info, current_ev, |
880 | end_buf, | 903 | end_buf, |
881 | &iwe, buf); | 904 | &iwe, buf); |
882 | sprintf(buf, "Path Selection Metric ID: " | 905 | 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); | 906 | iwe.u.data.length = strlen(buf); |
886 | current_ev = iwe_stream_add_point(info, current_ev, | 907 | current_ev = iwe_stream_add_point(info, current_ev, |
887 | end_buf, | 908 | end_buf, |
888 | &iwe, buf); | 909 | &iwe, buf); |
889 | sprintf(buf, "Congestion Control Mode ID: " | 910 | 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); | 911 | iwe.u.data.length = strlen(buf); |
893 | current_ev = iwe_stream_add_point(info, current_ev, | 912 | current_ev = iwe_stream_add_point(info, current_ev, |
894 | end_buf, | 913 | end_buf, |
895 | &iwe, buf); | 914 | &iwe, buf); |
896 | sprintf(buf, "Channel Precedence: " | 915 | 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); | 916 | iwe.u.data.length = strlen(buf); |
900 | current_ev = iwe_stream_add_point(info, current_ev, | 917 | current_ev = iwe_stream_add_point(info, current_ev, |
901 | end_buf, | 918 | end_buf, |
@@ -925,8 +942,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
925 | ie += ie[1] + 2; | 942 | ie += ie[1] + 2; |
926 | } | 943 | } |
927 | 944 | ||
928 | if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | 945 | if (bss->pub.capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) || |
929 | || ismesh) { | 946 | ismesh) { |
930 | memset(&iwe, 0, sizeof(iwe)); | 947 | memset(&iwe, 0, sizeof(iwe)); |
931 | iwe.cmd = SIOCGIWMODE; | 948 | iwe.cmd = SIOCGIWMODE; |
932 | if (ismesh) | 949 | if (ismesh) |