diff options
Diffstat (limited to 'net/mac80211/wext.c')
-rw-r--r-- | net/mac80211/wext.c | 145 |
1 files changed, 118 insertions, 27 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index e8404212ad57..34fa8ed1e784 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -142,7 +142,39 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, | |||
142 | struct iw_request_info *info, | 142 | struct iw_request_info *info, |
143 | char *name, char *extra) | 143 | char *name, char *extra) |
144 | { | 144 | { |
145 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
146 | struct ieee80211_supported_band *sband; | ||
147 | u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0; | ||
148 | |||
149 | |||
150 | sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
151 | if (sband) { | ||
152 | is_a = 1; | ||
153 | is_ht |= sband->ht_info.ht_supported; | ||
154 | } | ||
155 | |||
156 | sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
157 | if (sband) { | ||
158 | int i; | ||
159 | /* Check for mandatory rates */ | ||
160 | for (i = 0; i < sband->n_bitrates; i++) { | ||
161 | if (sband->bitrates[i].bitrate == 10) | ||
162 | is_b = 1; | ||
163 | if (sband->bitrates[i].bitrate == 60) | ||
164 | is_g = 1; | ||
165 | } | ||
166 | is_ht |= sband->ht_info.ht_supported; | ||
167 | } | ||
168 | |||
145 | strcpy(name, "IEEE 802.11"); | 169 | strcpy(name, "IEEE 802.11"); |
170 | if (is_a) | ||
171 | strcat(name, "a"); | ||
172 | if (is_b) | ||
173 | strcat(name, "b"); | ||
174 | if (is_g) | ||
175 | strcat(name, "g"); | ||
176 | if (is_ht) | ||
177 | strcat(name, "n"); | ||
146 | 178 | ||
147 | return 0; | 179 | return 0; |
148 | } | 180 | } |
@@ -176,14 +208,26 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
176 | range->num_encoding_sizes = 2; | 208 | range->num_encoding_sizes = 2; |
177 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; | 209 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; |
178 | 210 | ||
179 | range->max_qual.qual = local->hw.max_signal; | 211 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || |
180 | range->max_qual.level = local->hw.max_rssi; | 212 | local->hw.flags & IEEE80211_HW_SIGNAL_DB) |
181 | range->max_qual.noise = local->hw.max_noise; | 213 | range->max_qual.level = local->hw.max_signal; |
214 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
215 | range->max_qual.level = -110; | ||
216 | else | ||
217 | range->max_qual.level = 0; | ||
218 | |||
219 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
220 | range->max_qual.noise = -110; | ||
221 | else | ||
222 | range->max_qual.noise = 0; | ||
223 | |||
224 | range->max_qual.qual = 100; | ||
182 | range->max_qual.updated = local->wstats_flags; | 225 | range->max_qual.updated = local->wstats_flags; |
183 | 226 | ||
184 | range->avg_qual.qual = local->hw.max_signal/2; | 227 | range->avg_qual.qual = 50; |
185 | range->avg_qual.level = 0; | 228 | /* not always true but better than nothing */ |
186 | range->avg_qual.noise = 0; | 229 | range->avg_qual.level = range->max_qual.level / 2; |
230 | range->avg_qual.noise = range->max_qual.noise / 2; | ||
187 | range->avg_qual.updated = local->wstats_flags; | 231 | range->avg_qual.updated = local->wstats_flags; |
188 | 232 | ||
189 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 233 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
@@ -252,15 +296,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
252 | return -EINVAL; | 296 | return -EINVAL; |
253 | } | 297 | } |
254 | 298 | ||
255 | if (type == sdata->vif.type) | 299 | return ieee80211_if_change_type(sdata, type); |
256 | return 0; | ||
257 | if (netif_running(dev)) | ||
258 | return -EBUSY; | ||
259 | |||
260 | ieee80211_if_reinit(dev); | ||
261 | ieee80211_if_set_type(dev, type); | ||
262 | |||
263 | return 0; | ||
264 | } | 300 | } |
265 | 301 | ||
266 | 302 | ||
@@ -408,7 +444,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
408 | memset(sdata->u.ap.ssid + len, 0, | 444 | memset(sdata->u.ap.ssid + len, 0, |
409 | IEEE80211_MAX_SSID_LEN - len); | 445 | IEEE80211_MAX_SSID_LEN - len); |
410 | sdata->u.ap.ssid_len = len; | 446 | sdata->u.ap.ssid_len = len; |
411 | return ieee80211_if_config(dev); | 447 | return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); |
412 | } | 448 | } |
413 | return -EOPNOTSUPP; | 449 | return -EOPNOTSUPP; |
414 | } | 450 | } |
@@ -562,7 +598,7 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
562 | if (local->sta_sw_scanning || local->sta_hw_scanning) | 598 | if (local->sta_sw_scanning || local->sta_hw_scanning) |
563 | return -EAGAIN; | 599 | return -EAGAIN; |
564 | 600 | ||
565 | res = ieee80211_sta_scan_results(dev, extra, data->length); | 601 | res = ieee80211_sta_scan_results(dev, info, extra, data->length); |
566 | if (res >= 0) { | 602 | if (res >= 0) { |
567 | data->length = res; | 603 | data->length = res; |
568 | return 0; | 604 | return 0; |
@@ -583,16 +619,14 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
583 | struct ieee80211_supported_band *sband; | 619 | struct ieee80211_supported_band *sband; |
584 | 620 | ||
585 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 621 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
586 | if (!sdata->bss) | ||
587 | return -ENODEV; | ||
588 | 622 | ||
589 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 623 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
590 | 624 | ||
591 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | 625 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates |
592 | * target_rate = X, rate->fixed = 1 means only rate X | 626 | * target_rate = X, rate->fixed = 1 means only rate X |
593 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | 627 | * target_rate = X, rate->fixed = 0 means all rates <= X */ |
594 | sdata->bss->max_ratectrl_rateidx = -1; | 628 | sdata->max_ratectrl_rateidx = -1; |
595 | sdata->bss->force_unicast_rateidx = -1; | 629 | sdata->force_unicast_rateidx = -1; |
596 | if (rate->value < 0) | 630 | if (rate->value < 0) |
597 | return 0; | 631 | return 0; |
598 | 632 | ||
@@ -601,9 +635,9 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
601 | int this_rate = brate->bitrate; | 635 | int this_rate = brate->bitrate; |
602 | 636 | ||
603 | if (target_rate == this_rate) { | 637 | if (target_rate == this_rate) { |
604 | sdata->bss->max_ratectrl_rateidx = i; | 638 | sdata->max_ratectrl_rateidx = i; |
605 | if (rate->fixed) | 639 | if (rate->fixed) |
606 | sdata->bss->force_unicast_rateidx = i; | 640 | sdata->force_unicast_rateidx = i; |
607 | err = 0; | 641 | err = 0; |
608 | break; | 642 | break; |
609 | } | 643 | } |
@@ -716,6 +750,9 @@ static int ieee80211_ioctl_siwrts(struct net_device *dev, | |||
716 | 750 | ||
717 | if (rts->disabled) | 751 | if (rts->disabled) |
718 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 752 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
753 | else if (!rts->fixed) | ||
754 | /* if the rts value is not fixed, then take default */ | ||
755 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
719 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) | 756 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) |
720 | return -EINVAL; | 757 | return -EINVAL; |
721 | else | 758 | else |
@@ -753,6 +790,8 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, | |||
753 | 790 | ||
754 | if (frag->disabled) | 791 | if (frag->disabled) |
755 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 792 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; |
793 | else if (!frag->fixed) | ||
794 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
756 | else if (frag->value < 256 || | 795 | else if (frag->value < 256 || |
757 | frag->value > IEEE80211_MAX_FRAG_THRESHOLD) | 796 | frag->value > IEEE80211_MAX_FRAG_THRESHOLD) |
758 | return -EINVAL; | 797 | return -EINVAL; |
@@ -944,6 +983,58 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
944 | erq->length = sdata->keys[idx]->conf.keylen; | 983 | erq->length = sdata->keys[idx]->conf.keylen; |
945 | erq->flags |= IW_ENCODE_ENABLED; | 984 | erq->flags |= IW_ENCODE_ENABLED; |
946 | 985 | ||
986 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | ||
987 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
988 | switch (ifsta->auth_alg) { | ||
989 | case WLAN_AUTH_OPEN: | ||
990 | case WLAN_AUTH_LEAP: | ||
991 | erq->flags |= IW_ENCODE_OPEN; | ||
992 | break; | ||
993 | case WLAN_AUTH_SHARED_KEY: | ||
994 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
995 | break; | ||
996 | } | ||
997 | } | ||
998 | |||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | ||
1003 | struct iw_request_info *info, | ||
1004 | struct iw_param *wrq, | ||
1005 | char *extra) | ||
1006 | { | ||
1007 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1008 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1009 | |||
1010 | if (wrq->disabled) { | ||
1011 | conf->flags &= ~IEEE80211_CONF_PS; | ||
1012 | return ieee80211_hw_config(local); | ||
1013 | } | ||
1014 | |||
1015 | switch (wrq->flags & IW_POWER_MODE) { | ||
1016 | case IW_POWER_ON: /* If not specified */ | ||
1017 | case IW_POWER_MODE: /* If set all mask */ | ||
1018 | case IW_POWER_ALL_R: /* If explicitely state all */ | ||
1019 | conf->flags |= IEEE80211_CONF_PS; | ||
1020 | break; | ||
1021 | default: /* Otherwise we don't support it */ | ||
1022 | return -EINVAL; | ||
1023 | } | ||
1024 | |||
1025 | return ieee80211_hw_config(local); | ||
1026 | } | ||
1027 | |||
1028 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | ||
1029 | struct iw_request_info *info, | ||
1030 | union iwreq_data *wrqu, | ||
1031 | char *extra) | ||
1032 | { | ||
1033 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1034 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1035 | |||
1036 | wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); | ||
1037 | |||
947 | return 0; | 1038 | return 0; |
948 | } | 1039 | } |
949 | 1040 | ||
@@ -1015,8 +1106,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
1015 | wstats->qual.noise = 0; | 1106 | wstats->qual.noise = 0; |
1016 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | 1107 | wstats->qual.updated = IW_QUAL_ALL_INVALID; |
1017 | } else { | 1108 | } else { |
1018 | wstats->qual.level = sta->last_rssi; | 1109 | wstats->qual.level = sta->last_signal; |
1019 | wstats->qual.qual = sta->last_signal; | 1110 | wstats->qual.qual = sta->last_qual; |
1020 | wstats->qual.noise = sta->last_noise; | 1111 | wstats->qual.noise = sta->last_noise; |
1021 | wstats->qual.updated = local->wstats_flags; | 1112 | wstats->qual.updated = local->wstats_flags; |
1022 | } | 1113 | } |
@@ -1149,8 +1240,8 @@ static const iw_handler ieee80211_handler[] = | |||
1149 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ | 1240 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ |
1150 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ | 1241 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ |
1151 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ | 1242 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ |
1152 | (iw_handler) NULL, /* SIOCSIWPOWER */ | 1243 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ |
1153 | (iw_handler) NULL, /* SIOCGIWPOWER */ | 1244 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
1154 | (iw_handler) NULL, /* -- hole -- */ | 1245 | (iw_handler) NULL, /* -- hole -- */ |
1155 | (iw_handler) NULL, /* -- hole -- */ | 1246 | (iw_handler) NULL, /* -- hole -- */ |
1156 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ | 1247 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ |