diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-05-28 07:01:53 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-05-29 03:11:56 -0400 |
commit | 31eba5bc56a9324f056d28569a4f89f39c1c3f70 (patch) | |
tree | b070a7f1871763d66562678ff23daa4613a3eab9 /net/mac80211/iface.c | |
parent | e057d3c31bdf87616b415c4b2cbf7310f54b9219 (diff) |
mac80211: support active monitor interfaces
Support them only if the driver advertises support for them via
IEEE80211_HW_SUPPORTS_ACTIVE_MONITOR. Unlike normal monitor interfaces,
they are added to the driver, along with their MAC address.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 29 |
1 files changed, 23 insertions, 6 deletions
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 | ||