aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wext.c')
-rw-r--r--net/mac80211/wext.c243
1 files changed, 148 insertions, 95 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 7162d5816f3..2b023dce8b2 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -37,7 +37,14 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
37 struct ieee80211_key *key; 37 struct ieee80211_key *key;
38 int err; 38 int err;
39 39
40 if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { 40 if (alg == ALG_AES_CMAC) {
41 if (idx < NUM_DEFAULT_KEYS ||
42 idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
43 printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
44 "(BIP)\n", sdata->dev->name, idx);
45 return -EINVAL;
46 }
47 } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
41 printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", 48 printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
42 sdata->dev->name, idx); 49 sdata->dev->name, idx);
43 return -EINVAL; 50 return -EINVAL;
@@ -103,6 +110,9 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta
103 110
104 if (set_tx_key || (!sta && !sdata->default_key && key)) 111 if (set_tx_key || (!sta && !sdata->default_key && key))
105 ieee80211_set_default_key(sdata, idx); 112 ieee80211_set_default_key(sdata, idx);
113 if (alg == ALG_AES_CMAC &&
114 (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
115 ieee80211_set_default_mgmt_key(sdata, idx);
106 } 116 }
107 117
108 out_unlock: 118 out_unlock:
@@ -135,6 +145,21 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
135 return -EOPNOTSUPP; 145 return -EOPNOTSUPP;
136} 146}
137 147
148static u8 ieee80211_get_wstats_flags(struct ieee80211_local *local)
149{
150 u8 wstats_flags = 0;
151
152 wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
153 IEEE80211_HW_SIGNAL_DBM) ?
154 IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
155 wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
156 IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
157 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
158 wstats_flags |= IW_QUAL_DBM;
159
160 return wstats_flags;
161}
162
138static int ieee80211_ioctl_giwrange(struct net_device *dev, 163static int ieee80211_ioctl_giwrange(struct net_device *dev,
139 struct iw_request_info *info, 164 struct iw_request_info *info,
140 struct iw_point *data, char *extra) 165 struct iw_point *data, char *extra)
@@ -163,9 +188,9 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
163 range->num_encoding_sizes = 2; 188 range->num_encoding_sizes = 2;
164 range->max_encoding_tokens = NUM_DEFAULT_KEYS; 189 range->max_encoding_tokens = NUM_DEFAULT_KEYS;
165 190
166 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || 191 /* cfg80211 requires this, and enforces 0..100 */
167 local->hw.flags & IEEE80211_HW_SIGNAL_DB) 192 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
168 range->max_qual.level = local->hw.max_signal; 193 range->max_qual.level = 100;
169 else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 194 else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
170 range->max_qual.level = -110; 195 range->max_qual.level = -110;
171 else 196 else
@@ -177,13 +202,13 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
177 range->max_qual.noise = 0; 202 range->max_qual.noise = 0;
178 203
179 range->max_qual.qual = 100; 204 range->max_qual.qual = 100;
180 range->max_qual.updated = local->wstats_flags; 205 range->max_qual.updated = ieee80211_get_wstats_flags(local);
181 206
182 range->avg_qual.qual = 50; 207 range->avg_qual.qual = 50;
183 /* not always true but better than nothing */ 208 /* not always true but better than nothing */
184 range->avg_qual.level = range->max_qual.level / 2; 209 range->avg_qual.level = range->max_qual.level / 2;
185 range->avg_qual.noise = range->max_qual.noise / 2; 210 range->avg_qual.noise = range->max_qual.noise / 2;
186 range->avg_qual.updated = local->wstats_flags; 211 range->avg_qual.updated = ieee80211_get_wstats_flags(local);
187 212
188 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | 213 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
189 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; 214 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
@@ -230,13 +255,15 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
230{ 255{
231 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 256 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
232 257
233 if (sdata->vif.type == NL80211_IFTYPE_STATION) 258 if (sdata->vif.type == NL80211_IFTYPE_ADHOC ||
259 sdata->vif.type == NL80211_IFTYPE_STATION)
234 sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; 260 sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
235 261
236 /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ 262 /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
237 if (freq->e == 0) { 263 if (freq->e == 0) {
238 if (freq->m < 0) { 264 if (freq->m < 0) {
239 if (sdata->vif.type == NL80211_IFTYPE_STATION) 265 if (sdata->vif.type == NL80211_IFTYPE_ADHOC ||
266 sdata->vif.type == NL80211_IFTYPE_STATION)
240 sdata->u.sta.flags |= 267 sdata->u.sta.flags |=
241 IEEE80211_STA_AUTO_CHANNEL_SEL; 268 IEEE80211_STA_AUTO_CHANNEL_SEL;
242 return 0; 269 return 0;
@@ -404,58 +431,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
404} 431}
405 432
406 433
407static int ieee80211_ioctl_siwscan(struct net_device *dev,
408 struct iw_request_info *info,
409 union iwreq_data *wrqu, char *extra)
410{
411 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
412 struct iw_scan_req *req = NULL;
413 u8 *ssid = NULL;
414 size_t ssid_len = 0;
415
416 if (!netif_running(dev))
417 return -ENETDOWN;
418
419 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
420 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
421 sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
422 return -EOPNOTSUPP;
423
424 /* if SSID was specified explicitly then use that */
425 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
426 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
427 req = (struct iw_scan_req *)extra;
428 ssid = req->essid;
429 ssid_len = req->essid_len;
430 }
431
432 return ieee80211_request_scan(sdata, ssid, ssid_len);
433}
434
435
436static int ieee80211_ioctl_giwscan(struct net_device *dev,
437 struct iw_request_info *info,
438 struct iw_point *data, char *extra)
439{
440 int res;
441 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
442 struct ieee80211_sub_if_data *sdata;
443
444 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
445
446 if (local->sw_scanning || local->hw_scanning)
447 return -EAGAIN;
448
449 res = ieee80211_scan_results(local, info, extra, data->length);
450 if (res >= 0) {
451 data->length = res;
452 return 0;
453 }
454 data->length = 0;
455 return res;
456}
457
458
459static int ieee80211_ioctl_siwrate(struct net_device *dev, 434static int ieee80211_ioctl_siwrate(struct net_device *dev,
460 struct iw_request_info *info, 435 struct iw_request_info *info,
461 struct iw_param *rate, char *extra) 436 struct iw_param *rate, char *extra)
@@ -549,10 +524,9 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
549 else /* Automatic power level setting */ 524 else /* Automatic power level setting */
550 new_power_level = chan->max_power; 525 new_power_level = chan->max_power;
551 526
552 if (local->hw.conf.power_level != new_power_level) { 527 local->user_power_level = new_power_level;
553 local->hw.conf.power_level = new_power_level; 528 if (local->hw.conf.power_level != new_power_level)
554 reconf_flags |= IEEE80211_CONF_CHANGE_POWER; 529 reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
555 }
556 530
557 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { 531 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
558 local->hw.conf.radio_enabled = !(data->txpower.disabled); 532 local->hw.conf.radio_enabled = !(data->txpower.disabled);
@@ -836,6 +810,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
836 int ret = 0, timeout = 0; 810 int ret = 0, timeout = 0;
837 bool ps; 811 bool ps;
838 812
813 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
814 return -EOPNOTSUPP;
815
839 if (sdata->vif.type != NL80211_IFTYPE_STATION) 816 if (sdata->vif.type != NL80211_IFTYPE_STATION)
840 return -EINVAL; 817 return -EINVAL;
841 818
@@ -852,31 +829,49 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
852 ps = true; 829 ps = true;
853 break; 830 break;
854 default: /* Otherwise we ignore */ 831 default: /* Otherwise we ignore */
855 break; 832 return -EINVAL;
856 } 833 }
857 834
835 if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
836 return -EINVAL;
837
858 if (wrq->flags & IW_POWER_TIMEOUT) 838 if (wrq->flags & IW_POWER_TIMEOUT)
859 timeout = wrq->value / 1000; 839 timeout = wrq->value / 1000;
860 840
861set: 841 set:
862 if (ps == local->powersave && timeout == local->dynamic_ps_timeout) 842 if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
863 return ret; 843 return ret;
864 844
865 local->powersave = ps; 845 local->powersave = ps;
866 local->dynamic_ps_timeout = timeout; 846 conf->dynamic_ps_timeout = timeout;
867 847
868 if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { 848 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
869 if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && 849 ret = ieee80211_hw_config(local,
870 local->dynamic_ps_timeout > 0) 850 IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
871 mod_timer(&local->dynamic_ps_timer, jiffies + 851
872 msecs_to_jiffies(local->dynamic_ps_timeout)); 852 if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
873 else { 853 return ret;
874 if (local->powersave) 854
875 conf->flags |= IEEE80211_CONF_PS; 855 if (conf->dynamic_ps_timeout > 0 &&
876 else 856 !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
877 conf->flags &= ~IEEE80211_CONF_PS; 857 mod_timer(&local->dynamic_ps_timer, jiffies +
858 msecs_to_jiffies(conf->dynamic_ps_timeout));
859 } else {
860 if (local->powersave) {
861 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
862 ieee80211_send_nullfunc(local, sdata, 1);
863 conf->flags |= IEEE80211_CONF_PS;
864 ret = ieee80211_hw_config(local,
865 IEEE80211_CONF_CHANGE_PS);
866 } else {
867 conf->flags &= ~IEEE80211_CONF_PS;
868 ret = ieee80211_hw_config(local,
869 IEEE80211_CONF_CHANGE_PS);
870 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
871 ieee80211_send_nullfunc(local, sdata, 0);
872 del_timer_sync(&local->dynamic_ps_timer);
873 cancel_work_sync(&local->dynamic_ps_enable_work);
878 } 874 }
879 ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
880 } 875 }
881 876
882 return ret; 877 return ret;
@@ -903,11 +898,22 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
903 898
904 switch (data->flags & IW_AUTH_INDEX) { 899 switch (data->flags & IW_AUTH_INDEX) {
905 case IW_AUTH_WPA_VERSION: 900 case IW_AUTH_WPA_VERSION:
906 case IW_AUTH_CIPHER_PAIRWISE:
907 case IW_AUTH_CIPHER_GROUP: 901 case IW_AUTH_CIPHER_GROUP:
908 case IW_AUTH_WPA_ENABLED: 902 case IW_AUTH_WPA_ENABLED:
909 case IW_AUTH_RX_UNENCRYPTED_EAPOL: 903 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
910 case IW_AUTH_KEY_MGMT: 904 case IW_AUTH_KEY_MGMT:
905 case IW_AUTH_CIPHER_GROUP_MGMT:
906 break;
907 case IW_AUTH_CIPHER_PAIRWISE:
908 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
909 if (data->value & (IW_AUTH_CIPHER_WEP40 |
910 IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
911 sdata->u.sta.flags |=
912 IEEE80211_STA_TKIP_WEP_USED;
913 else
914 sdata->u.sta.flags &=
915 ~IEEE80211_STA_TKIP_WEP_USED;
916 }
911 break; 917 break;
912 case IW_AUTH_DROP_UNENCRYPTED: 918 case IW_AUTH_DROP_UNENCRYPTED:
913 sdata->drop_unencrypted = !!data->value; 919 sdata->drop_unencrypted = !!data->value;
@@ -934,6 +940,29 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
934 else 940 else
935 ret = -EOPNOTSUPP; 941 ret = -EOPNOTSUPP;
936 break; 942 break;
943 case IW_AUTH_MFP:
944 if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
945 ret = -EOPNOTSUPP;
946 break;
947 }
948 if (sdata->vif.type == NL80211_IFTYPE_STATION ||
949 sdata->vif.type == NL80211_IFTYPE_ADHOC) {
950 switch (data->value) {
951 case IW_AUTH_MFP_DISABLED:
952 sdata->u.sta.mfp = IEEE80211_MFP_DISABLED;
953 break;
954 case IW_AUTH_MFP_OPTIONAL:
955 sdata->u.sta.mfp = IEEE80211_MFP_OPTIONAL;
956 break;
957 case IW_AUTH_MFP_REQUIRED:
958 sdata->u.sta.mfp = IEEE80211_MFP_REQUIRED;
959 break;
960 default:
961 ret = -EINVAL;
962 }
963 } else
964 ret = -EOPNOTSUPP;
965 break;
937 default: 966 default:
938 ret = -EOPNOTSUPP; 967 ret = -EOPNOTSUPP;
939 break; 968 break;
@@ -965,7 +994,7 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
965 wstats->qual.level = sta->last_signal; 994 wstats->qual.level = sta->last_signal;
966 wstats->qual.qual = sta->last_qual; 995 wstats->qual.qual = sta->last_qual;
967 wstats->qual.noise = sta->last_noise; 996 wstats->qual.noise = sta->last_noise;
968 wstats->qual.updated = local->wstats_flags; 997 wstats->qual.updated = ieee80211_get_wstats_flags(local);
969 } 998 }
970 999
971 rcu_read_unlock(); 1000 rcu_read_unlock();
@@ -1017,6 +1046,9 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1017 case IW_ENCODE_ALG_CCMP: 1046 case IW_ENCODE_ALG_CCMP:
1018 alg = ALG_CCMP; 1047 alg = ALG_CCMP;
1019 break; 1048 break;
1049 case IW_ENCODE_ALG_AES_CMAC:
1050 alg = ALG_AES_CMAC;
1051 break;
1020 default: 1052 default:
1021 return -EOPNOTSUPP; 1053 return -EOPNOTSUPP;
1022 } 1054 }
@@ -1025,20 +1057,41 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1025 remove = 1; 1057 remove = 1;
1026 1058
1027 idx = erq->flags & IW_ENCODE_INDEX; 1059 idx = erq->flags & IW_ENCODE_INDEX;
1028 if (idx < 1 || idx > 4) { 1060 if (alg == ALG_AES_CMAC) {
1029 idx = -1; 1061 if (idx < NUM_DEFAULT_KEYS + 1 ||
1030 if (!sdata->default_key) 1062 idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
1031 idx = 0; 1063 idx = -1;
1032 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { 1064 if (!sdata->default_mgmt_key)
1033 if (sdata->default_key == sdata->keys[i]) { 1065 idx = 0;
1034 idx = i; 1066 else for (i = NUM_DEFAULT_KEYS;
1035 break; 1067 i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
1068 i++) {
1069 if (sdata->default_mgmt_key == sdata->keys[i])
1070 {
1071 idx = i;
1072 break;
1073 }
1036 } 1074 }
1037 } 1075 if (idx < 0)
1038 if (idx < 0) 1076 return -EINVAL;
1039 return -EINVAL; 1077 } else
1040 } else 1078 idx--;
1041 idx--; 1079 } else {
1080 if (idx < 1 || idx > 4) {
1081 idx = -1;
1082 if (!sdata->default_key)
1083 idx = 0;
1084 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
1085 if (sdata->default_key == sdata->keys[i]) {
1086 idx = i;
1087 break;
1088 }
1089 }
1090 if (idx < 0)
1091 return -EINVAL;
1092 } else
1093 idx--;
1094 }
1042 1095
1043 return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, 1096 return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
1044 remove, 1097 remove,
@@ -1076,8 +1129,8 @@ static const iw_handler ieee80211_handler[] =
1076 (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ 1129 (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
1077 (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ 1130 (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
1078 (iw_handler) NULL, /* SIOCGIWAPLIST */ 1131 (iw_handler) NULL, /* SIOCGIWAPLIST */
1079 (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */ 1132 (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
1080 (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */ 1133 (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
1081 (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ 1134 (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
1082 (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ 1135 (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
1083 (iw_handler) NULL, /* SIOCSIWNICKN */ 1136 (iw_handler) NULL, /* SIOCSIWNICKN */