Commit 31eba5bc authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e057d3c3
...@@ -73,16 +73,19 @@ static int ieee80211_change_iface(struct wiphy *wiphy, ...@@ -73,16 +73,19 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
if (ieee80211_sdata_running(sdata)) { if (ieee80211_sdata_running(sdata)) {
u32 mask = MONITOR_FLAG_COOK_FRAMES |
MONITOR_FLAG_ACTIVE;
/* /*
* Prohibit MONITOR_FLAG_COOK_FRAMES to be * Prohibit MONITOR_FLAG_COOK_FRAMES and
* changed while the interface is up. * MONITOR_FLAG_ACTIVE to be changed while the
* interface is up.
* Else we would need to add a lot of cruft * Else we would need to add a lot of cruft
* to update everything: * to update everything:
* cooked_mntrs, monitor and all fif_* counters * cooked_mntrs, monitor and all fif_* counters
* reconfigure hardware * reconfigure hardware
*/ */
if ((*flags & MONITOR_FLAG_COOK_FRAMES) != if ((*flags & mask) != (sdata->u.mntr_flags & mask))
(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
return -EBUSY; return -EBUSY;
ieee80211_adjust_monitor_flags(sdata, -1); ieee80211_adjust_monitor_flags(sdata, -1);
......
...@@ -146,7 +146,8 @@ static inline int drv_add_interface(struct ieee80211_local *local, ...@@ -146,7 +146,8 @@ static inline int drv_add_interface(struct ieee80211_local *local,
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
(sdata->vif.type == NL80211_IFTYPE_MONITOR && (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)))) !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF) &&
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))))
return -EINVAL; return -EINVAL;
trace_drv_add_interface(local, sdata); trace_drv_add_interface(local, sdata);
......
...@@ -159,7 +159,8 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) ...@@ -159,7 +159,8 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return 0; return 0;
} }
static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
bool check_dup)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
u64 new, mask, tmp; u64 new, mask, tmp;
...@@ -179,10 +180,13 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) ...@@ -179,10 +180,13 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
if (!check_dup)
return ret;
mutex_lock(&local->iflist_mtx); mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
continue; continue;
m = sdata->vif.addr; m = sdata->vif.addr;
...@@ -204,12 +208,17 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) ...@@ -204,12 +208,17 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sockaddr *sa = addr; struct sockaddr *sa = addr;
bool check_dup = true;
int ret; int ret;
if (ieee80211_sdata_running(sdata)) if (ieee80211_sdata_running(sdata))
return -EBUSY; return -EBUSY;
ret = ieee80211_verify_mac(sdata->local, sa->sa_data); if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
check_dup = false;
ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup);
if (ret) if (ret)
return ret; return ret;
...@@ -541,7 +550,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ...@@ -541,7 +550,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
break; break;
} }
if (local->monitors == 0 && local->open_count == 0) { if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
res = drv_add_interface(local, sdata);
if (res)
goto err_stop;
} else if (local->monitors == 0 && local->open_count == 0) {
res = ieee80211_add_virtual_monitor(local); res = ieee80211_add_virtual_monitor(local);
if (res) if (res)
goto err_stop; goto err_stop;
...@@ -919,7 +932,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -919,7 +932,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
break; break;
/* fall through */
default: default:
if (going_down) if (going_down)
drv_remove_interface(local, sdata); drv_remove_interface(local, sdata);
...@@ -1068,7 +1085,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { ...@@ -1068,7 +1085,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
.ndo_start_xmit = ieee80211_monitor_start_xmit, .ndo_start_xmit = ieee80211_monitor_start_xmit,
.ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_set_rx_mode = ieee80211_set_multicast_list,
.ndo_change_mtu = ieee80211_change_mtu, .ndo_change_mtu = ieee80211_change_mtu,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = ieee80211_change_mac,
.ndo_select_queue = ieee80211_monitor_select_queue, .ndo_select_queue = ieee80211_monitor_select_queue,
}; };
......
...@@ -560,6 +560,9 @@ void ieee80211_iterate_active_interfaces( ...@@ -560,6 +560,9 @@ void ieee80211_iterate_active_interfaces(
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
switch (sdata->vif.type) { switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
continue;
break;
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
continue; continue;
default: default:
...@@ -598,6 +601,9 @@ void ieee80211_iterate_active_interfaces_atomic( ...@@ -598,6 +601,9 @@ void ieee80211_iterate_active_interfaces_atomic(
list_for_each_entry_rcu(sdata, &local->interfaces, list) { list_for_each_entry_rcu(sdata, &local->interfaces, list) {
switch (sdata->vif.type) { switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
continue;
break;
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
continue; continue;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment