diff options
-rw-r--r-- | include/net/cfg80211.h | 36 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 69 | ||||
-rw-r--r-- | net/mac80211/wext.c | 215 | ||||
-rw-r--r-- | net/wireless/Makefile | 2 | ||||
-rw-r--r-- | net/wireless/core.c | 23 | ||||
-rw-r--r-- | net/wireless/core.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 2 | ||||
-rw-r--r-- | net/wireless/sme.c | 55 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 229 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 329 |
10 files changed, 625 insertions, 338 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 24fab439d415..07085216532d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1253,8 +1253,14 @@ struct wireless_dev { | |||
1253 | #ifdef CONFIG_WIRELESS_EXT | 1253 | #ifdef CONFIG_WIRELESS_EXT |
1254 | /* wext data */ | 1254 | /* wext data */ |
1255 | struct { | 1255 | struct { |
1256 | struct cfg80211_ibss_params ibss; | 1256 | union { |
1257 | struct cfg80211_ibss_params ibss; | ||
1258 | struct cfg80211_connect_params connect; | ||
1259 | }; | ||
1260 | u8 *ie; | ||
1261 | size_t ie_len; | ||
1257 | u8 bssid[ETH_ALEN]; | 1262 | u8 bssid[ETH_ALEN]; |
1263 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
1258 | s8 default_key, default_mgmt_key; | 1264 | s8 default_key, default_mgmt_key; |
1259 | } wext; | 1265 | } wext; |
1260 | #endif | 1266 | #endif |
@@ -1535,6 +1541,34 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, | |||
1535 | struct iw_request_info *info, | 1541 | struct iw_request_info *info, |
1536 | struct sockaddr *ap_addr, char *extra); | 1542 | struct sockaddr *ap_addr, char *extra); |
1537 | 1543 | ||
1544 | int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | ||
1545 | struct iw_request_info *info, | ||
1546 | struct iw_freq *freq, char *extra); | ||
1547 | int cfg80211_mgd_wext_giwfreq(struct net_device *dev, | ||
1548 | struct iw_request_info *info, | ||
1549 | struct iw_freq *freq, char *extra); | ||
1550 | int cfg80211_mgd_wext_siwessid(struct net_device *dev, | ||
1551 | struct iw_request_info *info, | ||
1552 | struct iw_point *data, char *ssid); | ||
1553 | int cfg80211_mgd_wext_giwessid(struct net_device *dev, | ||
1554 | struct iw_request_info *info, | ||
1555 | struct iw_point *data, char *ssid); | ||
1556 | int cfg80211_mgd_wext_siwap(struct net_device *dev, | ||
1557 | struct iw_request_info *info, | ||
1558 | struct sockaddr *ap_addr, char *extra); | ||
1559 | int cfg80211_mgd_wext_giwap(struct net_device *dev, | ||
1560 | struct iw_request_info *info, | ||
1561 | struct sockaddr *ap_addr, char *extra); | ||
1562 | int cfg80211_wext_siwgenie(struct net_device *dev, | ||
1563 | struct iw_request_info *info, | ||
1564 | struct iw_point *data, char *extra); | ||
1565 | int cfg80211_wext_siwauth(struct net_device *dev, | ||
1566 | struct iw_request_info *info, | ||
1567 | struct iw_param *data, char *extra); | ||
1568 | int cfg80211_wext_giwauth(struct net_device *dev, | ||
1569 | struct iw_request_info *info, | ||
1570 | struct iw_param *data, char *extra); | ||
1571 | |||
1538 | struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, | 1572 | struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, |
1539 | struct iw_freq *freq); | 1573 | struct iw_freq *freq); |
1540 | 1574 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 58135a5096af..fbb93a70ddc7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -870,70 +870,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
870 | return changed; | 870 | return changed; |
871 | } | 871 | } |
872 | 872 | ||
873 | static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata) | ||
874 | { | ||
875 | union iwreq_data wrqu; | ||
876 | |||
877 | memset(&wrqu, 0, sizeof(wrqu)); | ||
878 | if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) | ||
879 | memcpy(wrqu.ap_addr.sa_data, sdata->u.mgd.bssid, ETH_ALEN); | ||
880 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
881 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | ||
882 | } | ||
883 | |||
884 | static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata) | ||
885 | { | ||
886 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
887 | char *buf; | ||
888 | size_t len; | ||
889 | int i; | ||
890 | union iwreq_data wrqu; | ||
891 | |||
892 | if (!ifmgd->assocreq_ies && !ifmgd->assocresp_ies) | ||
893 | return; | ||
894 | |||
895 | buf = kmalloc(50 + 2 * (ifmgd->assocreq_ies_len + | ||
896 | ifmgd->assocresp_ies_len), GFP_KERNEL); | ||
897 | if (!buf) | ||
898 | return; | ||
899 | |||
900 | len = sprintf(buf, "ASSOCINFO("); | ||
901 | if (ifmgd->assocreq_ies) { | ||
902 | len += sprintf(buf + len, "ReqIEs="); | ||
903 | for (i = 0; i < ifmgd->assocreq_ies_len; i++) { | ||
904 | len += sprintf(buf + len, "%02x", | ||
905 | ifmgd->assocreq_ies[i]); | ||
906 | } | ||
907 | } | ||
908 | if (ifmgd->assocresp_ies) { | ||
909 | if (ifmgd->assocreq_ies) | ||
910 | len += sprintf(buf + len, " "); | ||
911 | len += sprintf(buf + len, "RespIEs="); | ||
912 | for (i = 0; i < ifmgd->assocresp_ies_len; i++) { | ||
913 | len += sprintf(buf + len, "%02x", | ||
914 | ifmgd->assocresp_ies[i]); | ||
915 | } | ||
916 | } | ||
917 | len += sprintf(buf + len, ")"); | ||
918 | |||
919 | if (len > IW_CUSTOM_MAX) { | ||
920 | len = sprintf(buf, "ASSOCRESPIE="); | ||
921 | for (i = 0; i < ifmgd->assocresp_ies_len; i++) { | ||
922 | len += sprintf(buf + len, "%02x", | ||
923 | ifmgd->assocresp_ies[i]); | ||
924 | } | ||
925 | } | ||
926 | |||
927 | if (len <= IW_CUSTOM_MAX) { | ||
928 | memset(&wrqu, 0, sizeof(wrqu)); | ||
929 | wrqu.data.length = len; | ||
930 | wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); | ||
931 | } | ||
932 | |||
933 | kfree(buf); | ||
934 | } | ||
935 | |||
936 | |||
937 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 873 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
938 | u32 bss_info_changed) | 874 | u32 bss_info_changed) |
939 | { | 875 | { |
@@ -966,7 +902,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
966 | 902 | ||
967 | ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET; | 903 | ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET; |
968 | memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN); | 904 | memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN); |
969 | ieee80211_sta_send_associnfo(sdata); | ||
970 | 905 | ||
971 | ifmgd->last_probe = jiffies; | 906 | ifmgd->last_probe = jiffies; |
972 | ieee80211_led_assoc(local, 1); | 907 | ieee80211_led_assoc(local, 1); |
@@ -993,8 +928,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
993 | 928 | ||
994 | netif_tx_start_all_queues(sdata->dev); | 929 | netif_tx_start_all_queues(sdata->dev); |
995 | netif_carrier_on(sdata->dev); | 930 | netif_carrier_on(sdata->dev); |
996 | |||
997 | ieee80211_sta_send_apinfo(sdata); | ||
998 | } | 931 | } |
999 | 932 | ||
1000 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) | 933 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) |
@@ -1147,8 +1080,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1147 | changed |= BSS_CHANGED_ASSOC; | 1080 | changed |= BSS_CHANGED_ASSOC; |
1148 | sdata->vif.bss_conf.assoc = false; | 1081 | sdata->vif.bss_conf.assoc = false; |
1149 | 1082 | ||
1150 | ieee80211_sta_send_apinfo(sdata); | ||
1151 | |||
1152 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) { | 1083 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) { |
1153 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 1084 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
1154 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, | 1085 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1da81f456744..d4e61dc903e8 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -27,29 +27,6 @@ | |||
27 | #include "aes_ccm.h" | 27 | #include "aes_ccm.h" |
28 | 28 | ||
29 | 29 | ||
30 | static int ieee80211_ioctl_siwgenie(struct net_device *dev, | ||
31 | struct iw_request_info *info, | ||
32 | struct iw_point *data, char *extra) | ||
33 | { | ||
34 | struct ieee80211_sub_if_data *sdata; | ||
35 | |||
36 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
37 | |||
38 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
39 | int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); | ||
40 | if (ret && ret != -EALREADY) | ||
41 | return ret; | ||
42 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | ||
43 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | ||
44 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
45 | if (ret != -EALREADY) | ||
46 | ieee80211_sta_req_auth(sdata); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | return -EOPNOTSUPP; | ||
51 | } | ||
52 | |||
53 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, | 30 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, |
54 | struct iw_request_info *info, | 31 | struct iw_request_info *info, |
55 | struct iw_freq *freq, char *extra) | 32 | struct iw_freq *freq, char *extra) |
@@ -61,16 +38,13 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
61 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 38 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
62 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | 39 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); |
63 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 40 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
64 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 41 | return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); |
65 | 42 | ||
66 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 43 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
67 | if (freq->e == 0) { | 44 | if (freq->e == 0) { |
68 | if (freq->m < 0) { | 45 | if (freq->m < 0) |
69 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 46 | return -EINVAL; |
70 | sdata->u.mgd.flags |= | 47 | else |
71 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
72 | return 0; | ||
73 | } else | ||
74 | chan = ieee80211_get_channel(local->hw.wiphy, | 48 | chan = ieee80211_get_channel(local->hw.wiphy, |
75 | ieee80211_channel_to_frequency(freq->m)); | 49 | ieee80211_channel_to_frequency(freq->m)); |
76 | } else { | 50 | } else { |
@@ -95,9 +69,6 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
95 | if (local->oper_channel == chan) | 69 | if (local->oper_channel == chan) |
96 | return 0; | 70 | return 0; |
97 | 71 | ||
98 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
99 | ieee80211_sta_req_auth(sdata); | ||
100 | |||
101 | local->oper_channel = chan; | 72 | local->oper_channel = chan; |
102 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 73 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
103 | ieee80211_hw_config(local, 0); | 74 | ieee80211_hw_config(local, 0); |
@@ -115,6 +86,8 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, | |||
115 | 86 | ||
116 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 87 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
117 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 88 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
89 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
90 | return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); | ||
118 | 91 | ||
119 | freq->m = local->oper_channel->center_freq; | 92 | freq->m = local->oper_channel->center_freq; |
120 | freq->e = 6; | 93 | freq->e = 6; |
@@ -128,31 +101,11 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
128 | struct iw_point *data, char *ssid) | 101 | struct iw_point *data, char *ssid) |
129 | { | 102 | { |
130 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 103 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
131 | size_t len = data->length; | ||
132 | int ret; | ||
133 | 104 | ||
134 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 105 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
135 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | 106 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); |
136 | 107 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | |
137 | /* iwconfig uses nul termination in SSID.. */ | 108 | return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); |
138 | if (len > 0 && ssid[len - 1] == '\0') | ||
139 | len--; | ||
140 | |||
141 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
142 | if (data->flags) | ||
143 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | ||
144 | else | ||
145 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL; | ||
146 | |||
147 | ret = ieee80211_sta_set_ssid(sdata, ssid, len); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | |||
151 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | ||
152 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
153 | ieee80211_sta_req_auth(sdata); | ||
154 | return 0; | ||
155 | } | ||
156 | 109 | ||
157 | return -EOPNOTSUPP; | 110 | return -EOPNOTSUPP; |
158 | } | 111 | } |
@@ -162,23 +115,14 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
162 | struct iw_request_info *info, | 115 | struct iw_request_info *info, |
163 | struct iw_point *data, char *ssid) | 116 | struct iw_point *data, char *ssid) |
164 | { | 117 | { |
165 | size_t len; | ||
166 | struct ieee80211_sub_if_data *sdata; | 118 | struct ieee80211_sub_if_data *sdata; |
167 | 119 | ||
168 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 120 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
169 | 121 | ||
170 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 122 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
171 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | 123 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); |
172 | 124 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | |
173 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 125 | return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); |
174 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); | ||
175 | if (res == 0) { | ||
176 | data->length = len; | ||
177 | data->flags = 1; | ||
178 | } else | ||
179 | data->flags = 0; | ||
180 | return res; | ||
181 | } | ||
182 | 126 | ||
183 | return -EOPNOTSUPP; | 127 | return -EOPNOTSUPP; |
184 | } | 128 | } |
@@ -193,24 +137,10 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
193 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 137 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
194 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | 138 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); |
195 | 139 | ||
196 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 140 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
197 | int ret; | 141 | return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); |
198 | 142 | ||
199 | if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) | 143 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
200 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL | | ||
201 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
202 | else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data)) | ||
203 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL; | ||
204 | else | ||
205 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | ||
206 | ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); | ||
207 | if (ret) | ||
208 | return ret; | ||
209 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | ||
210 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; | ||
211 | ieee80211_sta_req_auth(sdata); | ||
212 | return 0; | ||
213 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | ||
214 | /* | 144 | /* |
215 | * If it is necessary to update the WDS peer address | 145 | * If it is necessary to update the WDS peer address |
216 | * while the interface is running, then we need to do | 146 | * while the interface is running, then we need to do |
@@ -240,14 +170,10 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
240 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 170 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
241 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | 171 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); |
242 | 172 | ||
243 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 173 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
244 | if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { | 174 | return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); |
245 | ap_addr->sa_family = ARPHRD_ETHER; | 175 | |
246 | memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN); | 176 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
247 | } else | ||
248 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | ||
249 | return 0; | ||
250 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | ||
251 | ap_addr->sa_family = ARPHRD_ETHER; | 177 | ap_addr->sa_family = ARPHRD_ETHER; |
252 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); | 178 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); |
253 | return 0; | 179 | return 0; |
@@ -395,85 +321,6 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev, | |||
395 | return 0; | 321 | return 0; |
396 | } | 322 | } |
397 | 323 | ||
398 | static int ieee80211_ioctl_siwauth(struct net_device *dev, | ||
399 | struct iw_request_info *info, | ||
400 | struct iw_param *data, char *extra) | ||
401 | { | ||
402 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
403 | int ret = 0; | ||
404 | |||
405 | switch (data->flags & IW_AUTH_INDEX) { | ||
406 | case IW_AUTH_WPA_VERSION: | ||
407 | case IW_AUTH_CIPHER_GROUP: | ||
408 | case IW_AUTH_WPA_ENABLED: | ||
409 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
410 | case IW_AUTH_KEY_MGMT: | ||
411 | case IW_AUTH_CIPHER_GROUP_MGMT: | ||
412 | break; | ||
413 | case IW_AUTH_CIPHER_PAIRWISE: | ||
414 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
415 | if (data->value & (IW_AUTH_CIPHER_WEP40 | | ||
416 | IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP)) | ||
417 | sdata->u.mgd.flags |= | ||
418 | IEEE80211_STA_TKIP_WEP_USED; | ||
419 | else | ||
420 | sdata->u.mgd.flags &= | ||
421 | ~IEEE80211_STA_TKIP_WEP_USED; | ||
422 | } | ||
423 | break; | ||
424 | case IW_AUTH_DROP_UNENCRYPTED: | ||
425 | sdata->drop_unencrypted = !!data->value; | ||
426 | break; | ||
427 | case IW_AUTH_PRIVACY_INVOKED: | ||
428 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
429 | ret = -EINVAL; | ||
430 | else { | ||
431 | sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | ||
432 | /* | ||
433 | * Privacy invoked by wpa_supplicant, store the | ||
434 | * value and allow associating to a protected | ||
435 | * network without having a key up front. | ||
436 | */ | ||
437 | if (data->value) | ||
438 | sdata->u.mgd.flags |= | ||
439 | IEEE80211_STA_PRIVACY_INVOKED; | ||
440 | } | ||
441 | break; | ||
442 | case IW_AUTH_80211_AUTH_ALG: | ||
443 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
444 | sdata->u.mgd.auth_algs = data->value; | ||
445 | else | ||
446 | ret = -EOPNOTSUPP; | ||
447 | break; | ||
448 | case IW_AUTH_MFP: | ||
449 | if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) { | ||
450 | ret = -EOPNOTSUPP; | ||
451 | break; | ||
452 | } | ||
453 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
454 | switch (data->value) { | ||
455 | case IW_AUTH_MFP_DISABLED: | ||
456 | sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED; | ||
457 | break; | ||
458 | case IW_AUTH_MFP_OPTIONAL: | ||
459 | sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL; | ||
460 | break; | ||
461 | case IW_AUTH_MFP_REQUIRED: | ||
462 | sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED; | ||
463 | break; | ||
464 | default: | ||
465 | ret = -EINVAL; | ||
466 | } | ||
467 | } else | ||
468 | ret = -EOPNOTSUPP; | ||
469 | break; | ||
470 | default: | ||
471 | ret = -EOPNOTSUPP; | ||
472 | break; | ||
473 | } | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ | 324 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ |
478 | static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) | 325 | static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) |
479 | { | 326 | { |
@@ -541,28 +388,6 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
541 | return wstats; | 388 | return wstats; |
542 | } | 389 | } |
543 | 390 | ||
544 | static int ieee80211_ioctl_giwauth(struct net_device *dev, | ||
545 | struct iw_request_info *info, | ||
546 | struct iw_param *data, char *extra) | ||
547 | { | ||
548 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
549 | int ret = 0; | ||
550 | |||
551 | switch (data->flags & IW_AUTH_INDEX) { | ||
552 | case IW_AUTH_80211_AUTH_ALG: | ||
553 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
554 | data->value = sdata->u.mgd.auth_algs; | ||
555 | else | ||
556 | ret = -EOPNOTSUPP; | ||
557 | break; | ||
558 | default: | ||
559 | ret = -EOPNOTSUPP; | ||
560 | break; | ||
561 | } | ||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | |||
566 | /* Structures to export the Wireless Handlers */ | 391 | /* Structures to export the Wireless Handlers */ |
567 | 392 | ||
568 | static const iw_handler ieee80211_handler[] = | 393 | static const iw_handler ieee80211_handler[] = |
@@ -615,10 +440,10 @@ static const iw_handler ieee80211_handler[] = | |||
615 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ | 440 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
616 | (iw_handler) NULL, /* -- hole -- */ | 441 | (iw_handler) NULL, /* -- hole -- */ |
617 | (iw_handler) NULL, /* -- hole -- */ | 442 | (iw_handler) NULL, /* -- hole -- */ |
618 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ | 443 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ |
619 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 444 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
620 | (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ | 445 | (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ |
621 | (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ | 446 | (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ |
622 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ | 447 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
623 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 448 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
624 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 449 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 750c08e31b10..d74cc77fa57a 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -7,6 +7,6 @@ obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o | |||
7 | 7 | ||
8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o | 8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o |
9 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o | 9 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o |
10 | cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o | 10 | cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o |
11 | 11 | ||
12 | ccflags-y += -D__CHECK_ENDIAN__ | 12 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a0a679704612..e2f80dd0e4a6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -553,6 +553,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
553 | #ifdef CONFIG_WIRELESS_EXT | 553 | #ifdef CONFIG_WIRELESS_EXT |
554 | wdev->wext.default_key = -1; | 554 | wdev->wext.default_key = -1; |
555 | wdev->wext.default_mgmt_key = -1; | 555 | wdev->wext.default_mgmt_key = -1; |
556 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
556 | #endif | 557 | #endif |
557 | mutex_unlock(&rdev->devlist_mtx); | 558 | mutex_unlock(&rdev->devlist_mtx); |
558 | break; | 559 | break; |
@@ -565,8 +566,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
565 | cfg80211_leave_ibss(rdev, dev, true); | 566 | cfg80211_leave_ibss(rdev, dev, true); |
566 | break; | 567 | break; |
567 | case NL80211_IFTYPE_STATION: | 568 | case NL80211_IFTYPE_STATION: |
569 | #ifdef CONFIG_WIRELESS_EXT | ||
570 | kfree(wdev->wext.ie); | ||
571 | wdev->wext.ie = NULL; | ||
572 | wdev->wext.ie_len = 0; | ||
573 | #endif | ||
568 | cfg80211_disconnect(rdev, dev, | 574 | cfg80211_disconnect(rdev, dev, |
569 | WLAN_REASON_DEAUTH_LEAVING); | 575 | WLAN_REASON_DEAUTH_LEAVING, true); |
570 | break; | 576 | break; |
571 | default: | 577 | default: |
572 | break; | 578 | break; |
@@ -578,11 +584,20 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
578 | break; | 584 | break; |
579 | case NETDEV_UP: | 585 | case NETDEV_UP: |
580 | #ifdef CONFIG_WIRELESS_EXT | 586 | #ifdef CONFIG_WIRELESS_EXT |
581 | if (wdev->iftype != NL80211_IFTYPE_ADHOC) | 587 | switch (wdev->iftype) { |
588 | case NL80211_IFTYPE_ADHOC: | ||
589 | if (wdev->wext.ibss.ssid_len) | ||
590 | cfg80211_join_ibss(rdev, dev, | ||
591 | &wdev->wext.ibss); | ||
582 | break; | 592 | break; |
583 | if (!wdev->wext.ibss.ssid_len) | 593 | case NL80211_IFTYPE_STATION: |
594 | if (wdev->wext.connect.ssid_len) | ||
595 | cfg80211_connect(rdev, dev, | ||
596 | &wdev->wext.connect); | ||
597 | break; | ||
598 | default: | ||
584 | break; | 599 | break; |
585 | cfg80211_join_ibss(rdev, dev, &wdev->wext.ibss); | 600 | } |
586 | #endif | 601 | #endif |
587 | break; | 602 | break; |
588 | case NETDEV_UNREGISTER: | 603 | case NETDEV_UNREGISTER: |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 2c0f64252f3d..5209acb0ff7e 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -181,7 +181,8 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
181 | struct net_device *dev, | 181 | struct net_device *dev, |
182 | struct cfg80211_connect_params *connect); | 182 | struct cfg80211_connect_params *connect); |
183 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 183 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
184 | struct net_device *dev, u16 reason); | 184 | struct net_device *dev, u16 reason, |
185 | bool wextev); | ||
185 | 186 | ||
186 | void cfg80211_conn_work(struct work_struct *work); | 187 | void cfg80211_conn_work(struct work_struct *work); |
187 | 188 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 89aa9e781d10..0008144b354b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3747,7 +3747,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
3747 | goto out; | 3747 | goto out; |
3748 | } | 3748 | } |
3749 | 3749 | ||
3750 | err = cfg80211_disconnect(drv, dev, reason); | 3750 | err = cfg80211_disconnect(drv, dev, reason, true); |
3751 | 3751 | ||
3752 | out: | 3752 | out: |
3753 | cfg80211_put_dev(drv); | 3753 | cfg80211_put_dev(drv); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 3abb04729873..f272ebf94303 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -273,10 +273,10 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len) | |||
273 | } | 273 | } |
274 | } | 274 | } |
275 | 275 | ||
276 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 276 | static void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
277 | const u8 *req_ie, size_t req_ie_len, | 277 | const u8 *req_ie, size_t req_ie_len, |
278 | const u8 *resp_ie, size_t resp_ie_len, | 278 | const u8 *resp_ie, size_t resp_ie_len, |
279 | u16 status, gfp_t gfp) | 279 | u16 status, bool wextev, gfp_t gfp) |
280 | { | 280 | { |
281 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 281 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
282 | struct cfg80211_bss *bss; | 282 | struct cfg80211_bss *bss; |
@@ -321,25 +321,36 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
321 | status, gfp); | 321 | status, gfp); |
322 | 322 | ||
323 | #ifdef CONFIG_WIRELESS_EXT | 323 | #ifdef CONFIG_WIRELESS_EXT |
324 | if (req_ie && status == WLAN_STATUS_SUCCESS) { | 324 | if (wextev) { |
325 | memset(&wrqu, 0, sizeof(wrqu)); | 325 | if (req_ie && status == WLAN_STATUS_SUCCESS) { |
326 | wrqu.data.length = req_ie_len; | 326 | memset(&wrqu, 0, sizeof(wrqu)); |
327 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie); | 327 | wrqu.data.length = req_ie_len; |
328 | } | 328 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie); |
329 | } | ||
330 | |||
331 | if (resp_ie && status == WLAN_STATUS_SUCCESS) { | ||
332 | memset(&wrqu, 0, sizeof(wrqu)); | ||
333 | wrqu.data.length = resp_ie_len; | ||
334 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie); | ||
335 | } | ||
329 | 336 | ||
330 | if (resp_ie && status == WLAN_STATUS_SUCCESS) { | ||
331 | memset(&wrqu, 0, sizeof(wrqu)); | 337 | memset(&wrqu, 0, sizeof(wrqu)); |
332 | wrqu.data.length = resp_ie_len; | 338 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
333 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie); | 339 | if (bssid && status == WLAN_STATUS_SUCCESS) |
340 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | ||
341 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
334 | } | 342 | } |
335 | |||
336 | memset(&wrqu, 0, sizeof(wrqu)); | ||
337 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
338 | if (bssid && status == WLAN_STATUS_SUCCESS) | ||
339 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | ||
340 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
341 | #endif | 343 | #endif |
342 | } | 344 | } |
345 | |||
346 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | ||
347 | const u8 *req_ie, size_t req_ie_len, | ||
348 | const u8 *resp_ie, size_t resp_ie_len, | ||
349 | u16 status, gfp_t gfp) | ||
350 | { | ||
351 | bool wextev = status == WLAN_STATUS_SUCCESS; | ||
352 | __cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, status, wextev, gfp); | ||
353 | } | ||
343 | EXPORT_SYMBOL(cfg80211_connect_result); | 354 | EXPORT_SYMBOL(cfg80211_connect_result); |
344 | 355 | ||
345 | void cfg80211_roamed(struct net_device *dev, const u8 *bssid, | 356 | void cfg80211_roamed(struct net_device *dev, const u8 *bssid, |
@@ -540,7 +551,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
540 | } | 551 | } |
541 | 552 | ||
542 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 553 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
543 | struct net_device *dev, u16 reason) | 554 | struct net_device *dev, u16 reason, bool wextev) |
544 | { | 555 | { |
545 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 556 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
546 | int err; | 557 | int err; |
@@ -585,9 +596,9 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
585 | if (wdev->sme_state == CFG80211_SME_CONNECTED) | 596 | if (wdev->sme_state == CFG80211_SME_CONNECTED) |
586 | __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false); | 597 | __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false); |
587 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) | 598 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) |
588 | cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, | 599 | __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, |
589 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 600 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
590 | GFP_KERNEL); | 601 | wextev, GFP_KERNEL); |
591 | 602 | ||
592 | return 0; | 603 | return 0; |
593 | } | 604 | } |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index cae3b52fba7f..02f052fc1808 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -261,50 +261,6 @@ int cfg80211_wext_giwrange(struct net_device *dev, | |||
261 | } | 261 | } |
262 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); | 262 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); |
263 | 263 | ||
264 | int cfg80211_wext_siwmlme(struct net_device *dev, | ||
265 | struct iw_request_info *info, | ||
266 | struct iw_point *data, char *extra) | ||
267 | { | ||
268 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
269 | struct iw_mlme *mlme = (struct iw_mlme *)extra; | ||
270 | struct cfg80211_registered_device *rdev; | ||
271 | union { | ||
272 | struct cfg80211_disassoc_request disassoc; | ||
273 | struct cfg80211_deauth_request deauth; | ||
274 | } cmd; | ||
275 | |||
276 | if (!wdev) | ||
277 | return -EOPNOTSUPP; | ||
278 | |||
279 | rdev = wiphy_to_dev(wdev->wiphy); | ||
280 | |||
281 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
282 | return -EINVAL; | ||
283 | |||
284 | if (mlme->addr.sa_family != ARPHRD_ETHER) | ||
285 | return -EINVAL; | ||
286 | |||
287 | memset(&cmd, 0, sizeof(cmd)); | ||
288 | |||
289 | switch (mlme->cmd) { | ||
290 | case IW_MLME_DEAUTH: | ||
291 | if (!rdev->ops->deauth) | ||
292 | return -EOPNOTSUPP; | ||
293 | cmd.deauth.peer_addr = mlme->addr.sa_data; | ||
294 | cmd.deauth.reason_code = mlme->reason_code; | ||
295 | return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth); | ||
296 | case IW_MLME_DISASSOC: | ||
297 | if (!rdev->ops->disassoc) | ||
298 | return -EOPNOTSUPP; | ||
299 | cmd.disassoc.peer_addr = mlme->addr.sa_data; | ||
300 | cmd.disassoc.reason_code = mlme->reason_code; | ||
301 | return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc); | ||
302 | default: | ||
303 | return -EOPNOTSUPP; | ||
304 | } | ||
305 | } | ||
306 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); | ||
307 | |||
308 | 264 | ||
309 | /** | 265 | /** |
310 | * cfg80211_wext_freq - get wext frequency for non-"auto" | 266 | * cfg80211_wext_freq - get wext frequency for non-"auto" |
@@ -846,3 +802,188 @@ int cfg80211_wext_giwtxpower(struct net_device *dev, | |||
846 | return 0; | 802 | return 0; |
847 | } | 803 | } |
848 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower); | 804 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower); |
805 | |||
806 | static int cfg80211_set_auth_alg(struct wireless_dev *wdev, | ||
807 | s32 auth_alg) | ||
808 | { | ||
809 | int nr_alg = 0; | ||
810 | |||
811 | if (!auth_alg) | ||
812 | return -EINVAL; | ||
813 | |||
814 | if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM | | ||
815 | IW_AUTH_ALG_SHARED_KEY | | ||
816 | IW_AUTH_ALG_LEAP)) | ||
817 | return -EINVAL; | ||
818 | |||
819 | if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) { | ||
820 | nr_alg++; | ||
821 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
822 | } | ||
823 | |||
824 | if (auth_alg & IW_AUTH_ALG_SHARED_KEY) { | ||
825 | nr_alg++; | ||
826 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY; | ||
827 | } | ||
828 | |||
829 | if (auth_alg & IW_AUTH_ALG_LEAP) { | ||
830 | nr_alg++; | ||
831 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP; | ||
832 | } | ||
833 | |||
834 | if (nr_alg > 1) | ||
835 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
836 | |||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) | ||
841 | { | ||
842 | wdev->wext.connect.crypto.wpa_versions = 0; | ||
843 | |||
844 | if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | | ||
845 | IW_AUTH_WPA_VERSION_WPA2)) | ||
846 | return -EINVAL; | ||
847 | |||
848 | if (wpa_versions & IW_AUTH_WPA_VERSION_WPA) | ||
849 | wdev->wext.connect.crypto.wpa_versions |= | ||
850 | NL80211_WPA_VERSION_1; | ||
851 | |||
852 | if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2) | ||
853 | wdev->wext.connect.crypto.wpa_versions |= | ||
854 | NL80211_WPA_VERSION_2; | ||
855 | |||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) | ||
860 | { | ||
861 | wdev->wext.connect.crypto.cipher_group = 0; | ||
862 | |||
863 | if (cipher & IW_AUTH_CIPHER_WEP40) | ||
864 | wdev->wext.connect.crypto.cipher_group = | ||
865 | WLAN_CIPHER_SUITE_WEP40; | ||
866 | else if (cipher & IW_AUTH_CIPHER_WEP104) | ||
867 | wdev->wext.connect.crypto.cipher_group = | ||
868 | WLAN_CIPHER_SUITE_WEP104; | ||
869 | else if (cipher & IW_AUTH_CIPHER_TKIP) | ||
870 | wdev->wext.connect.crypto.cipher_group = | ||
871 | WLAN_CIPHER_SUITE_TKIP; | ||
872 | else if (cipher & IW_AUTH_CIPHER_CCMP) | ||
873 | wdev->wext.connect.crypto.cipher_group = | ||
874 | WLAN_CIPHER_SUITE_CCMP; | ||
875 | else if (cipher & IW_AUTH_CIPHER_AES_CMAC) | ||
876 | wdev->wext.connect.crypto.cipher_group = | ||
877 | WLAN_CIPHER_SUITE_AES_CMAC; | ||
878 | else | ||
879 | return -EINVAL; | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher) | ||
885 | { | ||
886 | int nr_ciphers = 0; | ||
887 | u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise; | ||
888 | |||
889 | if (cipher & IW_AUTH_CIPHER_WEP40) { | ||
890 | ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40; | ||
891 | nr_ciphers++; | ||
892 | } | ||
893 | |||
894 | if (cipher & IW_AUTH_CIPHER_WEP104) { | ||
895 | ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104; | ||
896 | nr_ciphers++; | ||
897 | } | ||
898 | |||
899 | if (cipher & IW_AUTH_CIPHER_TKIP) { | ||
900 | ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP; | ||
901 | nr_ciphers++; | ||
902 | } | ||
903 | |||
904 | if (cipher & IW_AUTH_CIPHER_CCMP) { | ||
905 | ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP; | ||
906 | nr_ciphers++; | ||
907 | } | ||
908 | |||
909 | if (cipher & IW_AUTH_CIPHER_AES_CMAC) { | ||
910 | ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC; | ||
911 | nr_ciphers++; | ||
912 | } | ||
913 | |||
914 | BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5); | ||
915 | |||
916 | wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers; | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | |||
922 | int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt) | ||
923 | { | ||
924 | int nr_akm_suites = 0; | ||
925 | |||
926 | if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X | | ||
927 | IW_AUTH_KEY_MGMT_PSK)) | ||
928 | return -EINVAL; | ||
929 | |||
930 | if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) { | ||
931 | wdev->wext.connect.crypto.akm_suites[nr_akm_suites] = | ||
932 | WLAN_AKM_SUITE_8021X; | ||
933 | nr_akm_suites++; | ||
934 | } | ||
935 | |||
936 | if (key_mgt & IW_AUTH_KEY_MGMT_PSK) { | ||
937 | wdev->wext.connect.crypto.akm_suites[nr_akm_suites] = | ||
938 | WLAN_AKM_SUITE_PSK; | ||
939 | nr_akm_suites++; | ||
940 | } | ||
941 | |||
942 | wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites; | ||
943 | |||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | int cfg80211_wext_siwauth(struct net_device *dev, | ||
948 | struct iw_request_info *info, | ||
949 | struct iw_param *data, char *extra) | ||
950 | { | ||
951 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
952 | |||
953 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
954 | return -EOPNOTSUPP; | ||
955 | |||
956 | switch (data->flags & IW_AUTH_INDEX) { | ||
957 | case IW_AUTH_PRIVACY_INVOKED: | ||
958 | wdev->wext.connect.privacy = data->value; | ||
959 | return 0; | ||
960 | case IW_AUTH_WPA_VERSION: | ||
961 | return cfg80211_set_wpa_version(wdev, data->value); | ||
962 | case IW_AUTH_CIPHER_GROUP: | ||
963 | return cfg80211_set_cipher_group(wdev, data->value); | ||
964 | case IW_AUTH_KEY_MGMT: | ||
965 | return cfg80211_set_key_mgt(wdev, data->value); | ||
966 | case IW_AUTH_CIPHER_PAIRWISE: | ||
967 | return cfg80211_set_cipher_pairwise(wdev, data->value); | ||
968 | case IW_AUTH_80211_AUTH_ALG: | ||
969 | return cfg80211_set_auth_alg(wdev, data->value); | ||
970 | case IW_AUTH_WPA_ENABLED: | ||
971 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
972 | case IW_AUTH_DROP_UNENCRYPTED: | ||
973 | case IW_AUTH_MFP: | ||
974 | return 0; | ||
975 | default: | ||
976 | return -EOPNOTSUPP; | ||
977 | } | ||
978 | } | ||
979 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth); | ||
980 | |||
981 | int cfg80211_wext_giwauth(struct net_device *dev, | ||
982 | struct iw_request_info *info, | ||
983 | struct iw_param *data, char *extra) | ||
984 | { | ||
985 | /* XXX: what do we need? */ | ||
986 | |||
987 | return -EOPNOTSUPP; | ||
988 | } | ||
989 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth); | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c new file mode 100644 index 000000000000..3b531d572b69 --- /dev/null +++ b/net/wireless/wext-sme.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /* | ||
2 | * cfg80211 wext compat for managed mode. | ||
3 | * | ||
4 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * Copyright (C) 2009 Intel Corporation. All rights reserved. | ||
6 | */ | ||
7 | |||
8 | #include <linux/etherdevice.h> | ||
9 | #include <linux/if_arp.h> | ||
10 | #include <net/cfg80211.h> | ||
11 | #include "nl80211.h" | ||
12 | |||
13 | static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | ||
14 | struct wireless_dev *wdev) | ||
15 | { | ||
16 | int err; | ||
17 | |||
18 | if (!netif_running(wdev->netdev)) | ||
19 | return 0; | ||
20 | |||
21 | wdev->wext.connect.ie = wdev->wext.ie; | ||
22 | wdev->wext.connect.ie_len = wdev->wext.ie_len; | ||
23 | wdev->wext.connect.privacy = wdev->wext.default_key != -1; | ||
24 | |||
25 | err = 0; | ||
26 | if (wdev->wext.connect.ssid_len != 0) | ||
27 | err = cfg80211_connect(rdev, wdev->netdev, | ||
28 | &wdev->wext.connect); | ||
29 | |||
30 | return err; | ||
31 | } | ||
32 | |||
33 | int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | ||
34 | struct iw_request_info *info, | ||
35 | struct iw_freq *freq, char *extra) | ||
36 | { | ||
37 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
38 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
39 | struct ieee80211_channel *chan; | ||
40 | int err; | ||
41 | |||
42 | /* call only for station! */ | ||
43 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
44 | return -EINVAL; | ||
45 | |||
46 | chan = cfg80211_wext_freq(wdev->wiphy, freq); | ||
47 | if (chan && IS_ERR(chan)) | ||
48 | return PTR_ERR(chan); | ||
49 | |||
50 | if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (wdev->wext.connect.channel == chan) | ||
54 | return 0; | ||
55 | |||
56 | if (wdev->sme_state != CFG80211_SME_IDLE) { | ||
57 | bool event = true; | ||
58 | /* if SSID set, we'll try right again, avoid event */ | ||
59 | if (wdev->wext.connect.ssid_len) | ||
60 | event = false; | ||
61 | err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), | ||
62 | dev, WLAN_REASON_DEAUTH_LEAVING, | ||
63 | event); | ||
64 | if (err) | ||
65 | return err; | ||
66 | } | ||
67 | |||
68 | wdev->wext.connect.channel = chan; | ||
69 | |||
70 | /* SSID is not set, we just want to switch channel */ | ||
71 | if (wdev->wext.connect.ssid_len && chan) { | ||
72 | if (!rdev->ops->set_channel) | ||
73 | return -EOPNOTSUPP; | ||
74 | |||
75 | return rdev->ops->set_channel(wdev->wiphy, chan, | ||
76 | NL80211_CHAN_NO_HT); | ||
77 | } | ||
78 | |||
79 | return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); | ||
80 | } | ||
81 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
82 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); | ||
83 | |||
84 | int cfg80211_mgd_wext_giwfreq(struct net_device *dev, | ||
85 | struct iw_request_info *info, | ||
86 | struct iw_freq *freq, char *extra) | ||
87 | { | ||
88 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
89 | struct ieee80211_channel *chan = NULL; | ||
90 | |||
91 | /* call only for station! */ | ||
92 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
93 | return -EINVAL; | ||
94 | |||
95 | if (wdev->current_bss) | ||
96 | chan = wdev->current_bss->channel; | ||
97 | else if (wdev->wext.connect.channel) | ||
98 | chan = wdev->wext.connect.channel; | ||
99 | |||
100 | if (chan) { | ||
101 | freq->m = chan->center_freq; | ||
102 | freq->e = 6; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | /* no channel if not joining */ | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
110 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwfreq); | ||
111 | |||
112 | int cfg80211_mgd_wext_siwessid(struct net_device *dev, | ||
113 | struct iw_request_info *info, | ||
114 | struct iw_point *data, char *ssid) | ||
115 | { | ||
116 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
117 | size_t len = data->length; | ||
118 | int err; | ||
119 | |||
120 | /* call only for station! */ | ||
121 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
122 | return -EINVAL; | ||
123 | |||
124 | if (!data->flags) | ||
125 | len = 0; | ||
126 | |||
127 | /* iwconfig uses nul termination in SSID.. */ | ||
128 | if (len > 0 && ssid[len - 1] == '\0') | ||
129 | len--; | ||
130 | |||
131 | if (wdev->wext.connect.ssid && len && | ||
132 | len == wdev->wext.connect.ssid_len && | ||
133 | memcmp(wdev->wext.connect.ssid, ssid, len)) | ||
134 | return 0; | ||
135 | |||
136 | if (wdev->sme_state != CFG80211_SME_IDLE) { | ||
137 | bool event = true; | ||
138 | /* if SSID set now, we'll try to connect, avoid event */ | ||
139 | if (len) | ||
140 | event = false; | ||
141 | err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), | ||
142 | dev, WLAN_REASON_DEAUTH_LEAVING, | ||
143 | event); | ||
144 | if (err) | ||
145 | return err; | ||
146 | } | ||
147 | |||
148 | wdev->wext.connect.ssid = wdev->wext.ssid; | ||
149 | memcpy(wdev->wext.ssid, ssid, len); | ||
150 | wdev->wext.connect.ssid_len = len; | ||
151 | |||
152 | wdev->wext.connect.crypto.control_port = false; | ||
153 | |||
154 | return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); | ||
155 | } | ||
156 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
157 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); | ||
158 | |||
159 | int cfg80211_mgd_wext_giwessid(struct net_device *dev, | ||
160 | struct iw_request_info *info, | ||
161 | struct iw_point *data, char *ssid) | ||
162 | { | ||
163 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
164 | |||
165 | /* call only for station! */ | ||
166 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
167 | return -EINVAL; | ||
168 | |||
169 | data->flags = 0; | ||
170 | |||
171 | if (wdev->ssid_len) { | ||
172 | data->flags = 1; | ||
173 | data->length = wdev->ssid_len; | ||
174 | memcpy(ssid, wdev->ssid, data->length); | ||
175 | } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { | ||
176 | data->flags = 1; | ||
177 | data->length = wdev->wext.connect.ssid_len; | ||
178 | memcpy(ssid, wdev->wext.connect.ssid, data->length); | ||
179 | } else | ||
180 | data->flags = 0; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
185 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwessid); | ||
186 | |||
187 | int cfg80211_mgd_wext_siwap(struct net_device *dev, | ||
188 | struct iw_request_info *info, | ||
189 | struct sockaddr *ap_addr, char *extra) | ||
190 | { | ||
191 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
192 | u8 *bssid = ap_addr->sa_data; | ||
193 | int err; | ||
194 | |||
195 | /* call only for station! */ | ||
196 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
197 | return -EINVAL; | ||
198 | |||
199 | if (ap_addr->sa_family != ARPHRD_ETHER) | ||
200 | return -EINVAL; | ||
201 | |||
202 | /* automatic mode */ | ||
203 | if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) | ||
204 | bssid = NULL; | ||
205 | |||
206 | /* both automatic */ | ||
207 | if (!bssid && !wdev->wext.connect.bssid) | ||
208 | return 0; | ||
209 | |||
210 | /* fixed already - and no change */ | ||
211 | if (wdev->wext.connect.bssid && bssid && | ||
212 | compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) | ||
213 | return 0; | ||
214 | |||
215 | if (wdev->sme_state != CFG80211_SME_IDLE) { | ||
216 | err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), | ||
217 | dev, WLAN_REASON_DEAUTH_LEAVING, | ||
218 | false); | ||
219 | if (err) | ||
220 | return err; | ||
221 | } | ||
222 | |||
223 | if (bssid) { | ||
224 | memcpy(wdev->wext.bssid, bssid, ETH_ALEN); | ||
225 | wdev->wext.connect.bssid = wdev->wext.bssid; | ||
226 | } else | ||
227 | wdev->wext.connect.bssid = NULL; | ||
228 | |||
229 | return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); | ||
230 | } | ||
231 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
232 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); | ||
233 | |||
234 | int cfg80211_mgd_wext_giwap(struct net_device *dev, | ||
235 | struct iw_request_info *info, | ||
236 | struct sockaddr *ap_addr, char *extra) | ||
237 | { | ||
238 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
239 | |||
240 | /* call only for station! */ | ||
241 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
242 | return -EINVAL; | ||
243 | |||
244 | ap_addr->sa_family = ARPHRD_ETHER; | ||
245 | |||
246 | if (wdev->current_bss) | ||
247 | memcpy(ap_addr->sa_data, wdev->current_bss->bssid, ETH_ALEN); | ||
248 | else if (wdev->wext.connect.bssid) | ||
249 | memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN); | ||
250 | else | ||
251 | memset(ap_addr->sa_data, 0, ETH_ALEN); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | /* temporary symbol - mark GPL - in the future the handler won't be */ | ||
256 | EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwap); | ||
257 | |||
258 | int cfg80211_wext_siwgenie(struct net_device *dev, | ||
259 | struct iw_request_info *info, | ||
260 | struct iw_point *data, char *extra) | ||
261 | { | ||
262 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
263 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
264 | u8 *ie = extra; | ||
265 | int ie_len = data->length, err; | ||
266 | |||
267 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
268 | return -EOPNOTSUPP; | ||
269 | |||
270 | if (!ie_len) | ||
271 | ie = NULL; | ||
272 | |||
273 | /* no change */ | ||
274 | if (wdev->wext.ie_len == ie_len && | ||
275 | memcmp(wdev->wext.ie, ie, ie_len) == 0) | ||
276 | return 0; | ||
277 | |||
278 | if (ie_len) { | ||
279 | ie = kmemdup(extra, ie_len, GFP_KERNEL); | ||
280 | if (!ie) | ||
281 | return -ENOMEM; | ||
282 | } else | ||
283 | ie = NULL; | ||
284 | |||
285 | kfree(wdev->wext.ie); | ||
286 | wdev->wext.ie = ie; | ||
287 | wdev->wext.ie_len = ie_len; | ||
288 | |||
289 | if (wdev->sme_state != CFG80211_SME_IDLE) { | ||
290 | err = cfg80211_disconnect(rdev, dev, | ||
291 | WLAN_REASON_DEAUTH_LEAVING, false); | ||
292 | if (err) | ||
293 | return err; | ||
294 | } | ||
295 | |||
296 | /* userspace better not think we'll reconnect */ | ||
297 | return 0; | ||
298 | } | ||
299 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie); | ||
300 | |||
301 | int cfg80211_wext_siwmlme(struct net_device *dev, | ||
302 | struct iw_request_info *info, | ||
303 | struct iw_point *data, char *extra) | ||
304 | { | ||
305 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
306 | struct iw_mlme *mlme = (struct iw_mlme *)extra; | ||
307 | struct cfg80211_registered_device *rdev; | ||
308 | |||
309 | if (!wdev) | ||
310 | return -EOPNOTSUPP; | ||
311 | |||
312 | rdev = wiphy_to_dev(wdev->wiphy); | ||
313 | |||
314 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
315 | return -EINVAL; | ||
316 | |||
317 | if (mlme->addr.sa_family != ARPHRD_ETHER) | ||
318 | return -EINVAL; | ||
319 | |||
320 | switch (mlme->cmd) { | ||
321 | case IW_MLME_DEAUTH: | ||
322 | case IW_MLME_DISASSOC: | ||
323 | return cfg80211_disconnect(rdev, dev, mlme->reason_code, | ||
324 | true); | ||
325 | default: | ||
326 | return -EOPNOTSUPP; | ||
327 | } | ||
328 | } | ||
329 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); | ||