diff options
Diffstat (limited to 'net/mac80211/ieee80211_ioctl.c')
-rw-r--r-- | net/mac80211/ieee80211_ioctl.c | 240 |
1 files changed, 69 insertions, 171 deletions
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 66e8a976b311..5918dd079e12 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
@@ -345,6 +345,8 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
345 | { | 345 | { |
346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
347 | struct iw_range *range = (struct iw_range *) extra; | 347 | struct iw_range *range = (struct iw_range *) extra; |
348 | struct ieee80211_hw_mode *mode = NULL; | ||
349 | int c = 0; | ||
348 | 350 | ||
349 | data->length = sizeof(struct iw_range); | 351 | data->length = sizeof(struct iw_range); |
350 | memset(range, 0, sizeof(struct iw_range)); | 352 | memset(range, 0, sizeof(struct iw_range)); |
@@ -378,6 +380,29 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
378 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 380 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
379 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; | 381 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; |
380 | 382 | ||
383 | list_for_each_entry(mode, &local->modes_list, list) { | ||
384 | int i = 0; | ||
385 | |||
386 | if (!(local->enabled_modes & (1 << mode->mode)) || | ||
387 | (local->hw_modes & local->enabled_modes & | ||
388 | (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) | ||
389 | continue; | ||
390 | |||
391 | while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) { | ||
392 | struct ieee80211_channel *chan = &mode->channels[i]; | ||
393 | |||
394 | if (chan->flag & IEEE80211_CHAN_W_SCAN) { | ||
395 | range->freq[c].i = chan->chan; | ||
396 | range->freq[c].m = chan->freq * 100000; | ||
397 | range->freq[c].e = 1; | ||
398 | c++; | ||
399 | } | ||
400 | i++; | ||
401 | } | ||
402 | } | ||
403 | range->num_channels = c; | ||
404 | range->num_frequency = c; | ||
405 | |||
381 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | 406 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); |
382 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); | 407 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); |
383 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | 408 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); |
@@ -838,6 +863,44 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
838 | } | 863 | } |
839 | 864 | ||
840 | 865 | ||
866 | static int ieee80211_ioctl_siwrate(struct net_device *dev, | ||
867 | struct iw_request_info *info, | ||
868 | struct iw_param *rate, char *extra) | ||
869 | { | ||
870 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
871 | struct ieee80211_hw_mode *mode; | ||
872 | int i; | ||
873 | u32 target_rate = rate->value / 100000; | ||
874 | struct ieee80211_sub_if_data *sdata; | ||
875 | |||
876 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
877 | if (!sdata->bss) | ||
878 | return -ENODEV; | ||
879 | mode = local->oper_hw_mode; | ||
880 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
881 | * target_rate = X, rate->fixed = 1 means only rate X | ||
882 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | ||
883 | sdata->bss->max_ratectrl_rateidx = -1; | ||
884 | sdata->bss->force_unicast_rateidx = -1; | ||
885 | if (rate->value < 0) | ||
886 | return 0; | ||
887 | for (i=0; i< mode->num_rates; i++) { | ||
888 | struct ieee80211_rate *rates = &mode->rates[i]; | ||
889 | int this_rate = rates->rate; | ||
890 | |||
891 | if (mode->mode == MODE_ATHEROS_TURBO || | ||
892 | mode->mode == MODE_ATHEROS_TURBOG) | ||
893 | this_rate *= 2; | ||
894 | if (target_rate == this_rate) { | ||
895 | sdata->bss->max_ratectrl_rateidx = i; | ||
896 | if (rate->fixed) | ||
897 | sdata->bss->force_unicast_rateidx = i; | ||
898 | break; | ||
899 | } | ||
900 | } | ||
901 | return 0; | ||
902 | } | ||
903 | |||
841 | static int ieee80211_ioctl_giwrate(struct net_device *dev, | 904 | static int ieee80211_ioctl_giwrate(struct net_device *dev, |
842 | struct iw_request_info *info, | 905 | struct iw_request_info *info, |
843 | struct iw_param *rate, char *extra) | 906 | struct iw_param *rate, char *extra) |
@@ -993,118 +1056,6 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, | |||
993 | return 0; | 1056 | return 0; |
994 | } | 1057 | } |
995 | 1058 | ||
996 | static int ieee80211_ioctl_clear_keys(struct net_device *dev) | ||
997 | { | ||
998 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
999 | struct ieee80211_key_conf key; | ||
1000 | int i; | ||
1001 | u8 addr[ETH_ALEN]; | ||
1002 | struct ieee80211_key_conf *keyconf; | ||
1003 | struct ieee80211_sub_if_data *sdata; | ||
1004 | struct sta_info *sta; | ||
1005 | |||
1006 | memset(addr, 0xff, ETH_ALEN); | ||
1007 | read_lock(&local->sub_if_lock); | ||
1008 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
1009 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1010 | keyconf = NULL; | ||
1011 | if (sdata->keys[i] && | ||
1012 | !sdata->keys[i]->force_sw_encrypt && | ||
1013 | local->ops->set_key && | ||
1014 | (keyconf = ieee80211_key_data2conf(local, | ||
1015 | sdata->keys[i]))) | ||
1016 | local->ops->set_key(local_to_hw(local), | ||
1017 | DISABLE_KEY, addr, | ||
1018 | keyconf, 0); | ||
1019 | kfree(keyconf); | ||
1020 | ieee80211_key_free(sdata->keys[i]); | ||
1021 | sdata->keys[i] = NULL; | ||
1022 | } | ||
1023 | sdata->default_key = NULL; | ||
1024 | } | ||
1025 | read_unlock(&local->sub_if_lock); | ||
1026 | |||
1027 | spin_lock_bh(&local->sta_lock); | ||
1028 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1029 | keyconf = NULL; | ||
1030 | if (sta->key && !sta->key->force_sw_encrypt && | ||
1031 | local->ops->set_key && | ||
1032 | (keyconf = ieee80211_key_data2conf(local, sta->key))) | ||
1033 | local->ops->set_key(local_to_hw(local), DISABLE_KEY, | ||
1034 | sta->addr, keyconf, sta->aid); | ||
1035 | kfree(keyconf); | ||
1036 | ieee80211_key_free(sta->key); | ||
1037 | sta->key = NULL; | ||
1038 | } | ||
1039 | spin_unlock_bh(&local->sta_lock); | ||
1040 | |||
1041 | memset(&key, 0, sizeof(key)); | ||
1042 | if (local->ops->set_key && | ||
1043 | local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS, | ||
1044 | NULL, &key, 0)) | ||
1045 | printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n", | ||
1046 | dev->name); | ||
1047 | |||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | |||
1052 | static int | ||
1053 | ieee80211_ioctl_force_unicast_rate(struct net_device *dev, | ||
1054 | struct ieee80211_sub_if_data *sdata, | ||
1055 | int rate) | ||
1056 | { | ||
1057 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1058 | struct ieee80211_hw_mode *mode; | ||
1059 | int i; | ||
1060 | |||
1061 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
1062 | return -ENOENT; | ||
1063 | |||
1064 | if (rate == 0) { | ||
1065 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | mode = local->oper_hw_mode; | ||
1070 | for (i = 0; i < mode->num_rates; i++) { | ||
1071 | if (mode->rates[i].rate == rate) { | ||
1072 | sdata->u.ap.force_unicast_rateidx = i; | ||
1073 | return 0; | ||
1074 | } | ||
1075 | } | ||
1076 | return -EINVAL; | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | static int | ||
1081 | ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev, | ||
1082 | struct ieee80211_sub_if_data *sdata, | ||
1083 | int rate) | ||
1084 | { | ||
1085 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1086 | struct ieee80211_hw_mode *mode; | ||
1087 | int i; | ||
1088 | |||
1089 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
1090 | return -ENOENT; | ||
1091 | |||
1092 | if (rate == 0) { | ||
1093 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | mode = local->oper_hw_mode; | ||
1098 | for (i = 0; i < mode->num_rates; i++) { | ||
1099 | if (mode->rates[i].rate == rate) { | ||
1100 | sdata->u.ap.max_ratectrl_rateidx = i; | ||
1101 | return 0; | ||
1102 | } | ||
1103 | } | ||
1104 | return -EINVAL; | ||
1105 | } | ||
1106 | |||
1107 | |||
1108 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, | 1059 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, |
1109 | struct ieee80211_key *key) | 1060 | struct ieee80211_key *key) |
1110 | { | 1061 | { |
@@ -1228,24 +1179,11 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1228 | sdata->ieee802_1x = value; | 1179 | sdata->ieee802_1x = value; |
1229 | break; | 1180 | break; |
1230 | 1181 | ||
1231 | case PRISM2_PARAM_ANTSEL_TX: | ||
1232 | local->hw.conf.antenna_sel_tx = value; | ||
1233 | if (ieee80211_hw_config(local)) | ||
1234 | ret = -EINVAL; | ||
1235 | break; | ||
1236 | |||
1237 | case PRISM2_PARAM_ANTSEL_RX: | ||
1238 | local->hw.conf.antenna_sel_rx = value; | ||
1239 | if (ieee80211_hw_config(local)) | ||
1240 | ret = -EINVAL; | ||
1241 | break; | ||
1242 | |||
1243 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1182 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
1244 | local->cts_protect_erp_frames = value; | 1183 | if (sdata->type != IEEE80211_IF_TYPE_AP) |
1245 | break; | 1184 | ret = -ENOENT; |
1246 | 1185 | else | |
1247 | case PRISM2_PARAM_DROP_UNENCRYPTED: | 1186 | sdata->use_protection = value; |
1248 | sdata->drop_unencrypted = value; | ||
1249 | break; | 1187 | break; |
1250 | 1188 | ||
1251 | case PRISM2_PARAM_PREAMBLE: | 1189 | case PRISM2_PARAM_PREAMBLE: |
@@ -1274,10 +1212,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1274 | local->next_mode = value; | 1212 | local->next_mode = value; |
1275 | break; | 1213 | break; |
1276 | 1214 | ||
1277 | case PRISM2_PARAM_CLEAR_KEYS: | ||
1278 | ret = ieee80211_ioctl_clear_keys(dev); | ||
1279 | break; | ||
1280 | |||
1281 | case PRISM2_PARAM_RADIO_ENABLED: | 1215 | case PRISM2_PARAM_RADIO_ENABLED: |
1282 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); | 1216 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); |
1283 | break; | 1217 | break; |
@@ -1292,22 +1226,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
1292 | local->sta_antenna_sel = value; | 1226 | local->sta_antenna_sel = value; |
1293 | break; | 1227 | break; |
1294 | 1228 | ||
1295 | case PRISM2_PARAM_FORCE_UNICAST_RATE: | ||
1296 | ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value); | ||
1297 | break; | ||
1298 | |||
1299 | case PRISM2_PARAM_MAX_RATECTRL_RATE: | ||
1300 | ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value); | ||
1301 | break; | ||
1302 | |||
1303 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
1304 | local->rate_ctrl_num_up = value; | ||
1305 | break; | ||
1306 | |||
1307 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
1308 | local->rate_ctrl_num_down = value; | ||
1309 | break; | ||
1310 | |||
1311 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1229 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
1312 | if (value < 0) | 1230 | if (value < 0) |
1313 | ret = -EINVAL; | 1231 | ret = -EINVAL; |
@@ -1387,20 +1305,8 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
1387 | *param = sdata->ieee802_1x; | 1305 | *param = sdata->ieee802_1x; |
1388 | break; | 1306 | break; |
1389 | 1307 | ||
1390 | case PRISM2_PARAM_ANTSEL_TX: | ||
1391 | *param = local->hw.conf.antenna_sel_tx; | ||
1392 | break; | ||
1393 | |||
1394 | case PRISM2_PARAM_ANTSEL_RX: | ||
1395 | *param = local->hw.conf.antenna_sel_rx; | ||
1396 | break; | ||
1397 | |||
1398 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1308 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
1399 | *param = local->cts_protect_erp_frames; | 1309 | *param = sdata->use_protection; |
1400 | break; | ||
1401 | |||
1402 | case PRISM2_PARAM_DROP_UNENCRYPTED: | ||
1403 | *param = sdata->drop_unencrypted; | ||
1404 | break; | 1310 | break; |
1405 | 1311 | ||
1406 | case PRISM2_PARAM_PREAMBLE: | 1312 | case PRISM2_PARAM_PREAMBLE: |
@@ -1426,14 +1332,6 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
1426 | *param = local->sta_antenna_sel; | 1332 | *param = local->sta_antenna_sel; |
1427 | break; | 1333 | break; |
1428 | 1334 | ||
1429 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
1430 | *param = local->rate_ctrl_num_up; | ||
1431 | break; | ||
1432 | |||
1433 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
1434 | *param = local->rate_ctrl_num_down; | ||
1435 | break; | ||
1436 | |||
1437 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1335 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
1438 | *param = local->hw.conf.tx_power_reduction; | 1336 | *param = local->hw.conf.tx_power_reduction; |
1439 | break; | 1337 | break; |
@@ -1801,7 +1699,7 @@ static const iw_handler ieee80211_handler[] = | |||
1801 | (iw_handler) NULL, /* SIOCGIWNICKN */ | 1699 | (iw_handler) NULL, /* SIOCGIWNICKN */ |
1802 | (iw_handler) NULL, /* -- hole -- */ | 1700 | (iw_handler) NULL, /* -- hole -- */ |
1803 | (iw_handler) NULL, /* -- hole -- */ | 1701 | (iw_handler) NULL, /* -- hole -- */ |
1804 | (iw_handler) NULL, /* SIOCSIWRATE */ | 1702 | (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ |
1805 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ | 1703 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ |
1806 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ | 1704 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ |
1807 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ | 1705 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ |