diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 4 | ||||
-rw-r--r-- | include/net/cfg80211.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 13 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 3 | ||||
-rw-r--r-- | net/mac80211/iface.c | 29 | ||||
-rw-r--r-- | net/mac80211/tx.c | 5 | ||||
-rw-r--r-- | net/mac80211/util.c | 6 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 10 |
10 files changed, 75 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 12337aac2947..dc50020d746d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -84,6 +84,15 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | |||
84 | .types = BIT(NL80211_IFTYPE_STATION) | | 84 | .types = BIT(NL80211_IFTYPE_STATION) | |
85 | BIT(NL80211_IFTYPE_AP), | 85 | BIT(NL80211_IFTYPE_AP), |
86 | }, | 86 | }, |
87 | { | ||
88 | .max = 1, | ||
89 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
90 | BIT(NL80211_IFTYPE_P2P_GO), | ||
91 | }, | ||
92 | { | ||
93 | .max = 1, | ||
94 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE), | ||
95 | }, | ||
87 | }; | 96 | }; |
88 | 97 | ||
89 | static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { | 98 | static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { |
@@ -164,7 +173,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
164 | hw->chanctx_data_size = sizeof(u16); | 173 | hw->chanctx_data_size = sizeof(u16); |
165 | 174 | ||
166 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 175 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
167 | BIT(NL80211_IFTYPE_AP); | 176 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
177 | BIT(NL80211_IFTYPE_AP) | | ||
178 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
179 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
168 | 180 | ||
169 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 181 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
170 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 182 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 69bbf6fdd2d3..cb34c7895f2a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -2169,6 +2169,7 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { | |||
2169 | #endif | 2169 | #endif |
2170 | BIT(NL80211_IFTYPE_AP) | | 2170 | BIT(NL80211_IFTYPE_AP) | |
2171 | BIT(NL80211_IFTYPE_P2P_GO) }, | 2171 | BIT(NL80211_IFTYPE_P2P_GO) }, |
2172 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | ||
2172 | }; | 2173 | }; |
2173 | 2174 | ||
2174 | static struct ieee80211_iface_combination hwsim_if_comb = { | 2175 | static struct ieee80211_iface_combination hwsim_if_comb = { |
@@ -2294,7 +2295,8 @@ static int __init init_mac80211_hwsim(void) | |||
2294 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 2295 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
2295 | BIT(NL80211_IFTYPE_P2P_GO) | | 2296 | BIT(NL80211_IFTYPE_P2P_GO) | |
2296 | BIT(NL80211_IFTYPE_ADHOC) | | 2297 | BIT(NL80211_IFTYPE_ADHOC) | |
2297 | BIT(NL80211_IFTYPE_MESH_POINT); | 2298 | BIT(NL80211_IFTYPE_MESH_POINT) | |
2299 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2298 | 2300 | ||
2299 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 2301 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
2300 | IEEE80211_HW_SIGNAL_DBM | | 2302 | IEEE80211_HW_SIGNAL_DBM | |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b3b076a46d50..6dd19593e333 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -961,6 +961,7 @@ struct station_info { | |||
961 | * @MONITOR_FLAG_CONTROL: pass control frames | 961 | * @MONITOR_FLAG_CONTROL: pass control frames |
962 | * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering | 962 | * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering |
963 | * @MONITOR_FLAG_COOK_FRAMES: report frames after processing | 963 | * @MONITOR_FLAG_COOK_FRAMES: report frames after processing |
964 | * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address | ||
964 | */ | 965 | */ |
965 | enum monitor_flags { | 966 | enum monitor_flags { |
966 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, | 967 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, |
@@ -968,6 +969,7 @@ enum monitor_flags { | |||
968 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, | 969 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, |
969 | MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS, | 970 | MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS, |
970 | MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES, | 971 | MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES, |
972 | MONITOR_FLAG_ACTIVE = 1<<NL80211_MNTR_FLAG_ACTIVE, | ||
971 | }; | 973 | }; |
972 | 974 | ||
973 | /** | 975 | /** |
@@ -2867,7 +2869,6 @@ struct cfg80211_cached_keys; | |||
2867 | * @mgmt_registrations_lock: lock for the list | 2869 | * @mgmt_registrations_lock: lock for the list |
2868 | * @mtx: mutex used to lock data in this struct, may be used by drivers | 2870 | * @mtx: mutex used to lock data in this struct, may be used by drivers |
2869 | * and some API functions require it held | 2871 | * and some API functions require it held |
2870 | * @cleanup_work: work struct used for cleanup that can't be done directly | ||
2871 | * @beacon_interval: beacon interval used on this device for transmitting | 2872 | * @beacon_interval: beacon interval used on this device for transmitting |
2872 | * beacons, 0 when not valid | 2873 | * beacons, 0 when not valid |
2873 | * @address: The address for this device, valid only if @netdev is %NULL | 2874 | * @address: The address for this device, valid only if @netdev is %NULL |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 32b060ea5266..5920715278c2 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -2428,6 +2428,8 @@ enum nl80211_survey_info { | |||
2428 | * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering | 2428 | * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering |
2429 | * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. | 2429 | * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. |
2430 | * overrides all other flags. | 2430 | * overrides all other flags. |
2431 | * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address | ||
2432 | * and ACK incoming unicast packets. | ||
2431 | * | 2433 | * |
2432 | * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use | 2434 | * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use |
2433 | * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag | 2435 | * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag |
@@ -2439,6 +2441,7 @@ enum nl80211_mntr_flags { | |||
2439 | NL80211_MNTR_FLAG_CONTROL, | 2441 | NL80211_MNTR_FLAG_CONTROL, |
2440 | NL80211_MNTR_FLAG_OTHER_BSS, | 2442 | NL80211_MNTR_FLAG_OTHER_BSS, |
2441 | NL80211_MNTR_FLAG_COOK_FRAMES, | 2443 | NL80211_MNTR_FLAG_COOK_FRAMES, |
2444 | NL80211_MNTR_FLAG_ACTIVE, | ||
2442 | 2445 | ||
2443 | /* keep last */ | 2446 | /* keep last */ |
2444 | __NL80211_MNTR_FLAG_AFTER_LAST, | 2447 | __NL80211_MNTR_FLAG_AFTER_LAST, |
@@ -3595,6 +3598,7 @@ enum nl80211_feature_flags { | |||
3595 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, | 3598 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, |
3596 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, | 3599 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, |
3597 | NL80211_FEATURE_USERSPACE_MPM = 1 << 16, | 3600 | NL80211_FEATURE_USERSPACE_MPM = 1 << 16, |
3601 | NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17, | ||
3598 | }; | 3602 | }; |
3599 | 3603 | ||
3600 | /** | 3604 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 232edf78d5a9..30622101d3b5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -73,16 +73,19 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
73 | struct ieee80211_local *local = sdata->local; | 73 | struct ieee80211_local *local = sdata->local; |
74 | 74 | ||
75 | if (ieee80211_sdata_running(sdata)) { | 75 | if (ieee80211_sdata_running(sdata)) { |
76 | u32 mask = MONITOR_FLAG_COOK_FRAMES | | ||
77 | MONITOR_FLAG_ACTIVE; | ||
78 | |||
76 | /* | 79 | /* |
77 | * Prohibit MONITOR_FLAG_COOK_FRAMES to be | 80 | * Prohibit MONITOR_FLAG_COOK_FRAMES and |
78 | * changed while the interface is up. | 81 | * MONITOR_FLAG_ACTIVE to be changed while the |
82 | * interface is up. | ||
79 | * Else we would need to add a lot of cruft | 83 | * Else we would need to add a lot of cruft |
80 | * to update everything: | 84 | * to update everything: |
81 | * cooked_mntrs, monitor and all fif_* counters | 85 | * cooked_mntrs, monitor and all fif_* counters |
82 | * reconfigure hardware | 86 | * reconfigure hardware |
83 | */ | 87 | */ |
84 | if ((*flags & MONITOR_FLAG_COOK_FRAMES) != | 88 | if ((*flags & mask) != (sdata->u.mntr_flags & mask)) |
85 | (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | ||
86 | return -EBUSY; | 89 | return -EBUSY; |
87 | 90 | ||
88 | ieee80211_adjust_monitor_flags(sdata, -1); | 91 | ieee80211_adjust_monitor_flags(sdata, -1); |
@@ -2375,7 +2378,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2375 | local->dynamic_ps_forced_timeout = timeout; | 2378 | local->dynamic_ps_forced_timeout = timeout; |
2376 | 2379 | ||
2377 | /* no change, but if automatic follow powersave */ | 2380 | /* no change, but if automatic follow powersave */ |
2381 | sdata_lock(sdata); | ||
2378 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); | 2382 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); |
2383 | sdata_unlock(sdata); | ||
2379 | 2384 | ||
2380 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 2385 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
2381 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2386 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 169664c122e2..b931c96a596f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -146,7 +146,8 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
146 | 146 | ||
147 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 147 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
148 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && | 148 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
149 | !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)))) | 149 | !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF) && |
150 | !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)))) | ||
150 | return -EINVAL; | 151 | return -EINVAL; |
151 | 152 | ||
152 | trace_drv_add_interface(local, sdata); | 153 | trace_drv_add_interface(local, sdata); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ceef64426a8d..7cabaf261fed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -159,7 +159,8 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) | 162 | static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, |
163 | bool check_dup) | ||
163 | { | 164 | { |
164 | struct ieee80211_sub_if_data *sdata; | 165 | struct ieee80211_sub_if_data *sdata; |
165 | u64 new, mask, tmp; | 166 | u64 new, mask, tmp; |
@@ -179,10 +180,13 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) | |||
179 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | 180 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | |
180 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | 181 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); |
181 | 182 | ||
183 | if (!check_dup) | ||
184 | return ret; | ||
182 | 185 | ||
183 | mutex_lock(&local->iflist_mtx); | 186 | mutex_lock(&local->iflist_mtx); |
184 | list_for_each_entry(sdata, &local->interfaces, list) { | 187 | list_for_each_entry(sdata, &local->interfaces, list) { |
185 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | 188 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
189 | !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | ||
186 | continue; | 190 | continue; |
187 | 191 | ||
188 | m = sdata->vif.addr; | 192 | m = sdata->vif.addr; |
@@ -204,12 +208,17 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) | |||
204 | { | 208 | { |
205 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 209 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
206 | struct sockaddr *sa = addr; | 210 | struct sockaddr *sa = addr; |
211 | bool check_dup = true; | ||
207 | int ret; | 212 | int ret; |
208 | 213 | ||
209 | if (ieee80211_sdata_running(sdata)) | 214 | if (ieee80211_sdata_running(sdata)) |
210 | return -EBUSY; | 215 | return -EBUSY; |
211 | 216 | ||
212 | ret = ieee80211_verify_mac(sdata->local, sa->sa_data); | 217 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
218 | !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | ||
219 | check_dup = false; | ||
220 | |||
221 | ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup); | ||
213 | if (ret) | 222 | if (ret) |
214 | return ret; | 223 | return ret; |
215 | 224 | ||
@@ -541,7 +550,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
541 | break; | 550 | break; |
542 | } | 551 | } |
543 | 552 | ||
544 | if (local->monitors == 0 && local->open_count == 0) { | 553 | if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) { |
554 | res = drv_add_interface(local, sdata); | ||
555 | if (res) | ||
556 | goto err_stop; | ||
557 | } else if (local->monitors == 0 && local->open_count == 0) { | ||
545 | res = ieee80211_add_virtual_monitor(local); | 558 | res = ieee80211_add_virtual_monitor(local); |
546 | if (res) | 559 | if (res) |
547 | goto err_stop; | 560 | goto err_stop; |
@@ -919,7 +932,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
919 | mutex_lock(&local->mtx); | 932 | mutex_lock(&local->mtx); |
920 | ieee80211_recalc_idle(local); | 933 | ieee80211_recalc_idle(local); |
921 | mutex_unlock(&local->mtx); | 934 | mutex_unlock(&local->mtx); |
922 | break; | 935 | |
936 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | ||
937 | break; | ||
938 | |||
939 | /* fall through */ | ||
923 | default: | 940 | default: |
924 | if (going_down) | 941 | if (going_down) |
925 | drv_remove_interface(local, sdata); | 942 | drv_remove_interface(local, sdata); |
@@ -1068,7 +1085,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { | |||
1068 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | 1085 | .ndo_start_xmit = ieee80211_monitor_start_xmit, |
1069 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 1086 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
1070 | .ndo_change_mtu = ieee80211_change_mtu, | 1087 | .ndo_change_mtu = ieee80211_change_mtu, |
1071 | .ndo_set_mac_address = eth_mac_addr, | 1088 | .ndo_set_mac_address = ieee80211_change_mac, |
1072 | .ndo_select_queue = ieee80211_monitor_select_queue, | 1089 | .ndo_select_queue = ieee80211_monitor_select_queue, |
1073 | }; | 1090 | }; |
1074 | 1091 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9972e07a2f96..34be9336b5d1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -398,13 +398,14 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
398 | if (ieee80211_has_order(hdr->frame_control)) | 398 | if (ieee80211_has_order(hdr->frame_control)) |
399 | return TX_CONTINUE; | 399 | return TX_CONTINUE; |
400 | 400 | ||
401 | if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
402 | info->hw_queue = tx->sdata->vif.cab_queue; | ||
403 | |||
401 | /* no stations in PS mode */ | 404 | /* no stations in PS mode */ |
402 | if (!atomic_read(&ps->num_sta_ps)) | 405 | if (!atomic_read(&ps->num_sta_ps)) |
403 | return TX_CONTINUE; | 406 | return TX_CONTINUE; |
404 | 407 | ||
405 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; | 408 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; |
406 | if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
407 | info->hw_queue = tx->sdata->vif.cab_queue; | ||
408 | 409 | ||
409 | /* device releases frame after DTIM beacon */ | 410 | /* device releases frame after DTIM beacon */ |
410 | if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) | 411 | if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 2a8d759324c2..89a83770d152 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -560,6 +560,9 @@ void ieee80211_iterate_active_interfaces( | |||
560 | list_for_each_entry(sdata, &local->interfaces, list) { | 560 | list_for_each_entry(sdata, &local->interfaces, list) { |
561 | switch (sdata->vif.type) { | 561 | switch (sdata->vif.type) { |
562 | case NL80211_IFTYPE_MONITOR: | 562 | case NL80211_IFTYPE_MONITOR: |
563 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | ||
564 | continue; | ||
565 | break; | ||
563 | case NL80211_IFTYPE_AP_VLAN: | 566 | case NL80211_IFTYPE_AP_VLAN: |
564 | continue; | 567 | continue; |
565 | default: | 568 | default: |
@@ -598,6 +601,9 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
598 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 601 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
599 | switch (sdata->vif.type) { | 602 | switch (sdata->vif.type) { |
600 | case NL80211_IFTYPE_MONITOR: | 603 | case NL80211_IFTYPE_MONITOR: |
604 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | ||
605 | continue; | ||
606 | break; | ||
601 | case NL80211_IFTYPE_AP_VLAN: | 607 | case NL80211_IFTYPE_AP_VLAN: |
602 | continue; | 608 | continue; |
603 | default: | 609 | default: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fb6abcb359a1..31d265f36d2c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2227,6 +2227,7 @@ static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { | |||
2227 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, | 2227 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, |
2228 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, | 2228 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, |
2229 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, | 2229 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, |
2230 | [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG }, | ||
2230 | }; | 2231 | }; |
2231 | 2232 | ||
2232 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) | 2233 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) |
@@ -2338,6 +2339,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
2338 | change = true; | 2339 | change = true; |
2339 | } | 2340 | } |
2340 | 2341 | ||
2342 | if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2343 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2344 | return -EOPNOTSUPP; | ||
2345 | |||
2341 | if (change) | 2346 | if (change) |
2342 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); | 2347 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); |
2343 | else | 2348 | else |
@@ -2395,6 +2400,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2395 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 2400 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
2396 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 2401 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
2397 | &flags); | 2402 | &flags); |
2403 | |||
2404 | if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2405 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2406 | return -EOPNOTSUPP; | ||
2407 | |||
2398 | wdev = rdev_add_virtual_intf(rdev, | 2408 | wdev = rdev_add_virtual_intf(rdev, |
2399 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 2409 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
2400 | type, err ? NULL : &flags, ¶ms); | 2410 | type, err ? NULL : &flags, ¶ms); |