diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 244 |
1 files changed, 134 insertions, 110 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509..18bd0e55060 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -19,33 +19,6 @@ | |||
19 | #include "rate.h" | 19 | #include "rate.h" |
20 | #include "mesh.h" | 20 | #include "mesh.h" |
21 | 21 | ||
22 | static bool nl80211_type_check(enum nl80211_iftype type) | ||
23 | { | ||
24 | switch (type) { | ||
25 | case NL80211_IFTYPE_ADHOC: | ||
26 | case NL80211_IFTYPE_STATION: | ||
27 | case NL80211_IFTYPE_MONITOR: | ||
28 | #ifdef CONFIG_MAC80211_MESH | ||
29 | case NL80211_IFTYPE_MESH_POINT: | ||
30 | #endif | ||
31 | case NL80211_IFTYPE_AP: | ||
32 | case NL80211_IFTYPE_AP_VLAN: | ||
33 | case NL80211_IFTYPE_WDS: | ||
34 | return true; | ||
35 | default: | ||
36 | return false; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static bool nl80211_params_check(enum nl80211_iftype type, | ||
41 | struct vif_params *params) | ||
42 | { | ||
43 | if (!nl80211_type_check(type)) | ||
44 | return false; | ||
45 | |||
46 | return true; | ||
47 | } | ||
48 | |||
49 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 22 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, |
50 | enum nl80211_iftype type, u32 *flags, | 23 | enum nl80211_iftype type, u32 *flags, |
51 | struct vif_params *params) | 24 | struct vif_params *params) |
@@ -55,9 +28,6 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
55 | struct ieee80211_sub_if_data *sdata; | 28 | struct ieee80211_sub_if_data *sdata; |
56 | int err; | 29 | int err; |
57 | 30 | ||
58 | if (!nl80211_params_check(type, params)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | err = ieee80211_if_add(local, name, &dev, type, params); | 31 | err = ieee80211_if_add(local, name, &dev, type, params); |
62 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) | 32 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
63 | return err; | 33 | return err; |
@@ -82,12 +52,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
82 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 52 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
83 | int ret; | 53 | int ret; |
84 | 54 | ||
85 | if (ieee80211_sdata_running(sdata)) | ||
86 | return -EBUSY; | ||
87 | |||
88 | if (!nl80211_params_check(type, params)) | ||
89 | return -EINVAL; | ||
90 | |||
91 | ret = ieee80211_if_change_type(sdata, type); | 55 | ret = ieee80211_if_change_type(sdata, type); |
92 | if (ret) | 56 | if (ret) |
93 | return ret; | 57 | return ret; |
@@ -104,54 +68,71 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
104 | params && params->use_4addr >= 0) | 68 | params && params->use_4addr >= 0) |
105 | sdata->u.mgd.use_4addr = params->use_4addr; | 69 | sdata->u.mgd.use_4addr = params->use_4addr; |
106 | 70 | ||
107 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) | 71 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { |
108 | sdata->u.mntr_flags = *flags; | 72 | struct ieee80211_local *local = sdata->local; |
73 | |||
74 | if (ieee80211_sdata_running(sdata)) { | ||
75 | /* | ||
76 | * Prohibit MONITOR_FLAG_COOK_FRAMES to be | ||
77 | * changed while the interface is up. | ||
78 | * Else we would need to add a lot of cruft | ||
79 | * to update everything: | ||
80 | * cooked_mntrs, monitor and all fif_* counters | ||
81 | * reconfigure hardware | ||
82 | */ | ||
83 | if ((*flags & MONITOR_FLAG_COOK_FRAMES) != | ||
84 | (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | ||
85 | return -EBUSY; | ||
86 | |||
87 | ieee80211_adjust_monitor_flags(sdata, -1); | ||
88 | sdata->u.mntr_flags = *flags; | ||
89 | ieee80211_adjust_monitor_flags(sdata, 1); | ||
90 | |||
91 | ieee80211_configure_filter(local); | ||
92 | } else { | ||
93 | /* | ||
94 | * Because the interface is down, ieee80211_do_stop | ||
95 | * and ieee80211_do_open take care of "everything" | ||
96 | * mentioned in the comment above. | ||
97 | */ | ||
98 | sdata->u.mntr_flags = *flags; | ||
99 | } | ||
100 | } | ||
109 | 101 | ||
110 | return 0; | 102 | return 0; |
111 | } | 103 | } |
112 | 104 | ||
113 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 105 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
114 | u8 key_idx, const u8 *mac_addr, | 106 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
115 | struct key_params *params) | 107 | struct key_params *params) |
116 | { | 108 | { |
117 | struct ieee80211_sub_if_data *sdata; | 109 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
118 | struct sta_info *sta = NULL; | 110 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | ||
120 | struct ieee80211_key *key; | 111 | struct ieee80211_key *key; |
121 | int err; | 112 | int err; |
122 | 113 | ||
123 | if (!netif_running(dev)) | 114 | if (!ieee80211_sdata_running(sdata)) |
124 | return -ENETDOWN; | 115 | return -ENETDOWN; |
125 | 116 | ||
126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 117 | /* reject WEP and TKIP keys if WEP failed to initialize */ |
127 | |||
128 | switch (params->cipher) { | 118 | switch (params->cipher) { |
129 | case WLAN_CIPHER_SUITE_WEP40: | 119 | case WLAN_CIPHER_SUITE_WEP40: |
130 | case WLAN_CIPHER_SUITE_WEP104: | ||
131 | alg = ALG_WEP; | ||
132 | break; | ||
133 | case WLAN_CIPHER_SUITE_TKIP: | 120 | case WLAN_CIPHER_SUITE_TKIP: |
134 | alg = ALG_TKIP; | 121 | case WLAN_CIPHER_SUITE_WEP104: |
135 | break; | 122 | if (IS_ERR(sdata->local->wep_tx_tfm)) |
136 | case WLAN_CIPHER_SUITE_CCMP: | 123 | return -EINVAL; |
137 | alg = ALG_CCMP; | ||
138 | break; | ||
139 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
140 | alg = ALG_AES_CMAC; | ||
141 | break; | 124 | break; |
142 | default: | 125 | default: |
143 | return -EINVAL; | 126 | break; |
144 | } | 127 | } |
145 | 128 | ||
146 | /* reject WEP and TKIP keys if WEP failed to initialize */ | 129 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
147 | if ((alg == ALG_WEP || alg == ALG_TKIP) && | 130 | params->key, params->seq_len, params->seq); |
148 | IS_ERR(sdata->local->wep_tx_tfm)) | 131 | if (IS_ERR(key)) |
149 | return -EINVAL; | 132 | return PTR_ERR(key); |
150 | 133 | ||
151 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, | 134 | if (pairwise) |
152 | params->seq_len, params->seq); | 135 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
153 | if (!key) | ||
154 | return -ENOMEM; | ||
155 | 136 | ||
156 | mutex_lock(&sdata->local->sta_mtx); | 137 | mutex_lock(&sdata->local->sta_mtx); |
157 | 138 | ||
@@ -164,9 +145,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
164 | } | 145 | } |
165 | } | 146 | } |
166 | 147 | ||
167 | ieee80211_key_link(key, sdata, sta); | 148 | err = ieee80211_key_link(key, sdata, sta); |
149 | if (err) | ||
150 | ieee80211_key_free(sdata->local, key); | ||
168 | 151 | ||
169 | err = 0; | ||
170 | out_unlock: | 152 | out_unlock: |
171 | mutex_unlock(&sdata->local->sta_mtx); | 153 | mutex_unlock(&sdata->local->sta_mtx); |
172 | 154 | ||
@@ -174,7 +156,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
174 | } | 156 | } |
175 | 157 | ||
176 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 158 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
177 | u8 key_idx, const u8 *mac_addr) | 159 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
178 | { | 160 | { |
179 | struct ieee80211_sub_if_data *sdata; | 161 | struct ieee80211_sub_if_data *sdata; |
180 | struct sta_info *sta; | 162 | struct sta_info *sta; |
@@ -191,10 +173,17 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
191 | if (!sta) | 173 | if (!sta) |
192 | goto out_unlock; | 174 | goto out_unlock; |
193 | 175 | ||
194 | if (sta->key) { | 176 | if (pairwise) { |
195 | ieee80211_key_free(sdata->local, sta->key); | 177 | if (sta->ptk) { |
196 | WARN_ON(sta->key); | 178 | ieee80211_key_free(sdata->local, sta->ptk); |
197 | ret = 0; | 179 | ret = 0; |
180 | } | ||
181 | } else { | ||
182 | if (sta->gtk[key_idx]) { | ||
183 | ieee80211_key_free(sdata->local, | ||
184 | sta->gtk[key_idx]); | ||
185 | ret = 0; | ||
186 | } | ||
198 | } | 187 | } |
199 | 188 | ||
200 | goto out_unlock; | 189 | goto out_unlock; |
@@ -216,7 +205,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
216 | } | 205 | } |
217 | 206 | ||
218 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | 207 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
219 | u8 key_idx, const u8 *mac_addr, void *cookie, | 208 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
209 | void *cookie, | ||
220 | void (*callback)(void *cookie, | 210 | void (*callback)(void *cookie, |
221 | struct key_params *params)) | 211 | struct key_params *params)) |
222 | { | 212 | { |
@@ -224,7 +214,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
224 | struct sta_info *sta = NULL; | 214 | struct sta_info *sta = NULL; |
225 | u8 seq[6] = {0}; | 215 | u8 seq[6] = {0}; |
226 | struct key_params params; | 216 | struct key_params params; |
227 | struct ieee80211_key *key; | 217 | struct ieee80211_key *key = NULL; |
228 | u32 iv32; | 218 | u32 iv32; |
229 | u16 iv16; | 219 | u16 iv16; |
230 | int err = -ENOENT; | 220 | int err = -ENOENT; |
@@ -238,7 +228,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
238 | if (!sta) | 228 | if (!sta) |
239 | goto out; | 229 | goto out; |
240 | 230 | ||
241 | key = sta->key; | 231 | if (pairwise) |
232 | key = sta->ptk; | ||
233 | else if (key_idx < NUM_DEFAULT_KEYS) | ||
234 | key = sta->gtk[key_idx]; | ||
242 | } else | 235 | } else |
243 | key = sdata->keys[key_idx]; | 236 | key = sdata->keys[key_idx]; |
244 | 237 | ||
@@ -247,10 +240,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
247 | 240 | ||
248 | memset(¶ms, 0, sizeof(params)); | 241 | memset(¶ms, 0, sizeof(params)); |
249 | 242 | ||
250 | switch (key->conf.alg) { | 243 | params.cipher = key->conf.cipher; |
251 | case ALG_TKIP: | ||
252 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | ||
253 | 244 | ||
245 | switch (key->conf.cipher) { | ||
246 | case WLAN_CIPHER_SUITE_TKIP: | ||
254 | iv32 = key->u.tkip.tx.iv32; | 247 | iv32 = key->u.tkip.tx.iv32; |
255 | iv16 = key->u.tkip.tx.iv16; | 248 | iv16 = key->u.tkip.tx.iv16; |
256 | 249 | ||
@@ -268,8 +261,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
268 | params.seq = seq; | 261 | params.seq = seq; |
269 | params.seq_len = 6; | 262 | params.seq_len = 6; |
270 | break; | 263 | break; |
271 | case ALG_CCMP: | 264 | case WLAN_CIPHER_SUITE_CCMP: |
272 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | ||
273 | seq[0] = key->u.ccmp.tx_pn[5]; | 265 | seq[0] = key->u.ccmp.tx_pn[5]; |
274 | seq[1] = key->u.ccmp.tx_pn[4]; | 266 | seq[1] = key->u.ccmp.tx_pn[4]; |
275 | seq[2] = key->u.ccmp.tx_pn[3]; | 267 | seq[2] = key->u.ccmp.tx_pn[3]; |
@@ -279,14 +271,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
279 | params.seq = seq; | 271 | params.seq = seq; |
280 | params.seq_len = 6; | 272 | params.seq_len = 6; |
281 | break; | 273 | break; |
282 | case ALG_WEP: | 274 | case WLAN_CIPHER_SUITE_AES_CMAC: |
283 | if (key->conf.keylen == 5) | ||
284 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | ||
285 | else | ||
286 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | ||
287 | break; | ||
288 | case ALG_AES_CMAC: | ||
289 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
290 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 275 | seq[0] = key->u.aes_cmac.tx_pn[5]; |
291 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 276 | seq[1] = key->u.aes_cmac.tx_pn[4]; |
292 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 277 | seq[2] = key->u.aes_cmac.tx_pn[3]; |
@@ -342,13 +327,19 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
342 | STATION_INFO_TX_BYTES | | 327 | STATION_INFO_TX_BYTES | |
343 | STATION_INFO_RX_PACKETS | | 328 | STATION_INFO_RX_PACKETS | |
344 | STATION_INFO_TX_PACKETS | | 329 | STATION_INFO_TX_PACKETS | |
345 | STATION_INFO_TX_BITRATE; | 330 | STATION_INFO_TX_RETRIES | |
331 | STATION_INFO_TX_FAILED | | ||
332 | STATION_INFO_TX_BITRATE | | ||
333 | STATION_INFO_RX_DROP_MISC; | ||
346 | 334 | ||
347 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 335 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
348 | sinfo->rx_bytes = sta->rx_bytes; | 336 | sinfo->rx_bytes = sta->rx_bytes; |
349 | sinfo->tx_bytes = sta->tx_bytes; | 337 | sinfo->tx_bytes = sta->tx_bytes; |
350 | sinfo->rx_packets = sta->rx_packets; | 338 | sinfo->rx_packets = sta->rx_packets; |
351 | sinfo->tx_packets = sta->tx_packets; | 339 | sinfo->tx_packets = sta->tx_packets; |
340 | sinfo->tx_retries = sta->tx_retry_count; | ||
341 | sinfo->tx_failed = sta->tx_retry_failed; | ||
342 | sinfo->rx_dropped_misc = sta->rx_dropped; | ||
352 | 343 | ||
353 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 344 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
354 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 345 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
@@ -634,6 +625,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
634 | struct sta_info *sta, | 625 | struct sta_info *sta, |
635 | struct station_parameters *params) | 626 | struct station_parameters *params) |
636 | { | 627 | { |
628 | unsigned long flags; | ||
637 | u32 rates; | 629 | u32 rates; |
638 | int i, j; | 630 | int i, j; |
639 | struct ieee80211_supported_band *sband; | 631 | struct ieee80211_supported_band *sband; |
@@ -642,7 +634,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
642 | 634 | ||
643 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 635 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
644 | 636 | ||
645 | spin_lock_bh(&sta->lock); | 637 | spin_lock_irqsave(&sta->flaglock, flags); |
646 | mask = params->sta_flags_mask; | 638 | mask = params->sta_flags_mask; |
647 | set = params->sta_flags_set; | 639 | set = params->sta_flags_set; |
648 | 640 | ||
@@ -669,7 +661,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
669 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 661 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
670 | sta->flags |= WLAN_STA_MFP; | 662 | sta->flags |= WLAN_STA_MFP; |
671 | } | 663 | } |
672 | spin_unlock_bh(&sta->lock); | 664 | spin_unlock_irqrestore(&sta->flaglock, flags); |
673 | 665 | ||
674 | /* | 666 | /* |
675 | * cfg80211 validates this (1-2007) and allows setting the AID | 667 | * cfg80211 validates this (1-2007) and allows setting the AID |
@@ -1143,9 +1135,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1143 | p.uapsd = false; | 1135 | p.uapsd = false; |
1144 | 1136 | ||
1145 | if (drv_conf_tx(local, params->queue, &p)) { | 1137 | if (drv_conf_tx(local, params->queue, &p)) { |
1146 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1138 | wiphy_debug(local->hw.wiphy, |
1147 | "parameters for queue %d\n", | 1139 | "failed to set TX queue parameters for queue %d\n", |
1148 | wiphy_name(local->hw.wiphy), params->queue); | 1140 | params->queue); |
1149 | return -EINVAL; | 1141 | return -EINVAL; |
1150 | } | 1142 | } |
1151 | 1143 | ||
@@ -1207,15 +1199,26 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1207 | struct net_device *dev, | 1199 | struct net_device *dev, |
1208 | struct cfg80211_scan_request *req) | 1200 | struct cfg80211_scan_request *req) |
1209 | { | 1201 | { |
1210 | struct ieee80211_sub_if_data *sdata; | 1202 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1211 | |||
1212 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1213 | 1203 | ||
1214 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1204 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1215 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1205 | case NL80211_IFTYPE_STATION: |
1216 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 1206 | case NL80211_IFTYPE_ADHOC: |
1217 | (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | 1207 | case NL80211_IFTYPE_MESH_POINT: |
1208 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1209 | break; | ||
1210 | case NL80211_IFTYPE_P2P_GO: | ||
1211 | if (sdata->local->ops->hw_scan) | ||
1212 | break; | ||
1213 | /* FIXME: implement NoA while scanning in software */ | ||
1214 | return -EOPNOTSUPP; | ||
1215 | case NL80211_IFTYPE_AP: | ||
1216 | if (sdata->u.ap.beacon) | ||
1217 | return -EOPNOTSUPP; | ||
1218 | break; | ||
1219 | default: | ||
1218 | return -EOPNOTSUPP; | 1220 | return -EOPNOTSUPP; |
1221 | } | ||
1219 | 1222 | ||
1220 | return ieee80211_request_scan(sdata, req); | 1223 | return ieee80211_request_scan(sdata, req); |
1221 | } | 1224 | } |
@@ -1362,7 +1365,7 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) | |||
1362 | } | 1365 | } |
1363 | 1366 | ||
1364 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, | 1367 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, |
1365 | u8 *addr) | 1368 | const u8 *addr) |
1366 | { | 1369 | { |
1367 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1370 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1368 | 1371 | ||
@@ -1411,7 +1414,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1411 | if (!sdata->u.mgd.associated || | 1414 | if (!sdata->u.mgd.associated || |
1412 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 1415 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
1413 | mutex_lock(&sdata->local->iflist_mtx); | 1416 | mutex_lock(&sdata->local->iflist_mtx); |
1414 | ieee80211_recalc_smps(sdata->local, sdata); | 1417 | ieee80211_recalc_smps(sdata->local); |
1415 | mutex_unlock(&sdata->local->iflist_mtx); | 1418 | mutex_unlock(&sdata->local->iflist_mtx); |
1416 | return 0; | 1419 | return 0; |
1417 | } | 1420 | } |
@@ -1541,11 +1544,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1541 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1544 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1542 | } | 1545 | } |
1543 | 1546 | ||
1544 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1547 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1545 | struct ieee80211_channel *chan, | 1548 | struct ieee80211_channel *chan, |
1546 | enum nl80211_channel_type channel_type, | 1549 | enum nl80211_channel_type channel_type, |
1547 | bool channel_type_valid, | 1550 | bool channel_type_valid, |
1548 | const u8 *buf, size_t len, u64 *cookie) | 1551 | const u8 *buf, size_t len, u64 *cookie) |
1549 | { | 1552 | { |
1550 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1553 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1551 | struct ieee80211_local *local = sdata->local; | 1554 | struct ieee80211_local *local = sdata->local; |
@@ -1566,7 +1569,11 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1566 | 1569 | ||
1567 | switch (sdata->vif.type) { | 1570 | switch (sdata->vif.type) { |
1568 | case NL80211_IFTYPE_ADHOC: | 1571 | case NL80211_IFTYPE_ADHOC: |
1569 | if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1572 | case NL80211_IFTYPE_AP: |
1573 | case NL80211_IFTYPE_AP_VLAN: | ||
1574 | case NL80211_IFTYPE_P2P_GO: | ||
1575 | if (!ieee80211_is_action(mgmt->frame_control) || | ||
1576 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | ||
1570 | break; | 1577 | break; |
1571 | rcu_read_lock(); | 1578 | rcu_read_lock(); |
1572 | sta = sta_info_get(sdata, mgmt->da); | 1579 | sta = sta_info_get(sdata, mgmt->da); |
@@ -1575,8 +1582,7 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1575 | return -ENOLINK; | 1582 | return -ENOLINK; |
1576 | break; | 1583 | break; |
1577 | case NL80211_IFTYPE_STATION: | 1584 | case NL80211_IFTYPE_STATION: |
1578 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | 1585 | case NL80211_IFTYPE_P2P_CLIENT: |
1579 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1580 | break; | 1586 | break; |
1581 | default: | 1587 | default: |
1582 | return -EOPNOTSUPP; | 1588 | return -EOPNOTSUPP; |
@@ -1598,6 +1604,23 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1598 | return 0; | 1604 | return 0; |
1599 | } | 1605 | } |
1600 | 1606 | ||
1607 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | ||
1608 | struct net_device *dev, | ||
1609 | u16 frame_type, bool reg) | ||
1610 | { | ||
1611 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1612 | |||
1613 | if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) | ||
1614 | return; | ||
1615 | |||
1616 | if (reg) | ||
1617 | local->probe_req_reg++; | ||
1618 | else | ||
1619 | local->probe_req_reg--; | ||
1620 | |||
1621 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | ||
1622 | } | ||
1623 | |||
1601 | struct cfg80211_ops mac80211_config_ops = { | 1624 | struct cfg80211_ops mac80211_config_ops = { |
1602 | .add_virtual_intf = ieee80211_add_iface, | 1625 | .add_virtual_intf = ieee80211_add_iface, |
1603 | .del_virtual_intf = ieee80211_del_iface, | 1626 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1647,6 +1670,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1647 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1670 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1648 | .remain_on_channel = ieee80211_remain_on_channel, | 1671 | .remain_on_channel = ieee80211_remain_on_channel, |
1649 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1672 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1650 | .action = ieee80211_action, | 1673 | .mgmt_tx = ieee80211_mgmt_tx, |
1651 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1674 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1675 | .mgmt_frame_register = ieee80211_mgmt_frame_register, | ||
1652 | }; | 1676 | }; |