aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-05-28 07:01:53 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-29 03:11:56 -0400
commit31eba5bc56a9324f056d28569a4f89f39c1c3f70 (patch)
treeb070a7f1871763d66562678ff23daa4613a3eab9 /net/mac80211/iface.c
parente057d3c31bdf87616b415c4b2cbf7310f54b9219 (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.c29
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
162static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) 162static 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