Search Linux Wireless

[no subject]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



                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);

So I'm not sure if the patch is what we want...
I'm also wondering, if we couldn't/shouldn't also drop %MONITOR_FLAG_ACTIVE
and %MONITOR_FLAG_COOK_FRAMES. I did not find a single use for them.
Thus, I'm also not sure I handle them correctly here. A monitor
interface with %MONITOR_FLAG_COOK_FRAMES was not picking up any frames
with or without this patch.. And %MONITOR_FLAG_ACTIVE does not work for
iwlmvm.
(At least one of them was probably for ancient versions of hostapd...)

Alexander
---
 net/mac80211/cfg.c         |  9 +++++----
 net/mac80211/ethtool.c     |  7 ++++---
 net/mac80211/ieee80211_i.h |  2 +-
 net/mac80211/iface.c       | 26 ++++++++++++++++++--------
 net/mac80211/pm.c          |  1 -
 net/mac80211/scan.c        |  2 +-
 net/mac80211/util.c        |  2 +-
 7 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b8495d5f2297..fbdd6b46b154 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4366,10 +4366,11 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
 	if (chanctx_conf) {
 		*chandef = link->conf->chanreq.oper;
 		ret = 0;
-	} else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
-		   local->open_count > 0 &&
-		   local->open_count == local->monitors &&
-		   sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+	} else if (local->virt_monitors &&
+		   local->open_count == local->virt_monitors &&
+		   sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+		   !(sdata->u.mntr.flags & (MONITOR_FLAG_ACTIVE |
+					    MONITOR_FLAG_COOK_FRAMES))) {
 		*chandef = local->monitor_chanreq.oper;
 		ret = 0;
 	}
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
index 42f7ee142ce3..52a278232c9d 100644
--- a/net/mac80211/ethtool.c
+++ b/net/mac80211/ethtool.c
@@ -157,9 +157,10 @@ static void ieee80211_get_stats(struct net_device *dev,
 	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
 	if (chanctx_conf)
 		channel = chanctx_conf->def.chan;
-	else if (local->open_count > 0 &&
-		 local->open_count == local->monitors &&
-		 sdata->vif.type == NL80211_IFTYPE_MONITOR)
+	else if (local->virt_monitors &&
+		 sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+		 !(sdata->u.mntr.flags & (MONITOR_FLAG_ACTIVE |
+					  MONITOR_FLAG_COOK_FRAMES)))
 		channel = local->monitor_chanreq.oper.chan;
 	else
 		channel = NULL;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a98133d5c362..8aceec18ffaf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1367,7 +1367,7 @@ struct ieee80211_local {
 	spinlock_t queue_stop_reason_lock;
 
 	int open_count;
-	int monitors, cooked_mntrs, tx_mntrs;
+	int monitors, virt_monitors, cooked_mntrs, tx_mntrs;
 	/* number of interfaces with corresponding FIF_ flags */
 	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
 	    fif_probe_req;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2e170dbde732..b0c02942dac3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -589,6 +589,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 			break;
 		}
 
+		if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
+		    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
+		    !WARN_ON(local->virt_monitors <= 0))
+			local->virt_monitors--;
+
 		local->monitors--;
 		if (local->monitors == 0) {
 			local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
@@ -686,7 +691,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 	case NL80211_IFTYPE_AP_VLAN:
 		break;
 	case NL80211_IFTYPE_MONITOR:
-		if (local->monitors == 0)
+		if (local->virt_monitors == 0)
 			ieee80211_del_virtual_monitor(local);
 
 		ieee80211_recalc_idle(local);
@@ -723,7 +728,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 	ieee80211_configure_filter(local);
 	ieee80211_hw_config(local, hw_reconf_flags);
 
-	if (local->monitors == local->open_count)
+	if (local->virt_monitors &&
+	    local->virt_monitors == local->open_count)
 		ieee80211_add_virtual_monitor(local);
 }
 
@@ -1129,7 +1135,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 	lockdep_assert_wiphy(local->hw.wiphy);
 
 	if (local->monitor_sdata ||
-	    ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+	    WARN_ON(ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)))
 		return 0;
 
 	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
@@ -1336,15 +1342,19 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 			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);
-			if (res)
-				goto err_stop;
+		} else {
+			if (local->virt_monitors == 0 &&
+			    local->open_count == 0) {
+				res = ieee80211_add_virtual_monitor(local);
+				if (res)
+					goto err_stop;
+			}
+			local->virt_monitors++;
 		}
 
 		/* must be before the call to ieee80211_configure_filter */
 		local->monitors++;
-		if (local->monitors == 1) {
+		if (local->monitors == 1 && local->virt_monitors == 1) {
 			local->hw.conf.flags |= IEEE80211_CONF_MONITOR;
 			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
 		}
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 7be52345f218..b914a1eeba82 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -150,7 +150,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			continue;
 		switch (sdata->vif.type) {
 		case NL80211_IFTYPE_AP_VLAN:
-		case NL80211_IFTYPE_MONITOR:
 			continue;
 		case NL80211_IFTYPE_STATION:
 			ieee80211_mgd_quiesce(sdata);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index cb7079071885..4eb0cf5f73ca 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -334,7 +334,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 	}
 
 	/* Do not update the BSS table in case of only monitor interfaces */
-	if (local->open_count == local->monitors)
+	if (local->open_count == local->monitors + local->cooked_mntrs)
 		return;
 
 	bss = ieee80211_bss_info_update(local, rx_status,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7b656326e68a..86320ecf306c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2153,7 +2153,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
  wake_up:
 
-	if (local->monitors == local->open_count && local->monitors > 0)
+	if (local->virt_monitors == local->open_count && local->monitors > 0)
 		ieee80211_add_virtual_monitor(local);
 
 	/*
-- 
2.48.1





[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux