summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAviya Erenfeld <aviya.erenfeld@intel.com>2016-08-29 16:25:16 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-09-12 05:44:52 -0400
commit42bd20d99857e69e368d5421ea402127d5835cd3 (patch)
tree1ca2460a76e67311a2f5fa9cb0acda1c0a0e32d5
parent480dd46b9d6812e5fb7172c305ee0f1154c26eed (diff)
mac80211: add support for MU-MIMO air sniffer
add support to MU-MIMO air sniffer according groupID: in monitor mode, use a given MU-MIMO groupID to monitor stations that belongs to that group using MU-MIMO. add support for following a station according to its MAC address using VHT MU-MIMO sniffer: the monitors wait until they get an action MU-MIMO notification frame, then parses it in order to find the groupID that corresponds to the given MAC address and monitors packets destined to that groupID using VHT MU-MIMO. Signed-off-by: Aviya Erenfeld <aviya.erenfeld@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/cfg.c23
-rw-r--r--net/mac80211/driver-ops.h3
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c5
-rw-r--r--net/mac80211/rx.c20
5 files changed, 51 insertions, 3 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f2c8cd22d317..5d4afead804e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -73,8 +73,29 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
73 sdata->u.mgd.use_4addr = params->use_4addr; 73 sdata->u.mgd.use_4addr = params->use_4addr;
74 } 74 }
75 75
76 if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { 76 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
77 struct ieee80211_local *local = sdata->local; 77 struct ieee80211_local *local = sdata->local;
78 struct ieee80211_sub_if_data *monitor_sdata;
79 u32 mu_mntr_cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
80
81 monitor_sdata = rtnl_dereference(local->monitor_sdata);
82 if (monitor_sdata &&
83 wiphy_ext_feature_isset(wiphy, mu_mntr_cap_flag)) {
84 memcpy(monitor_sdata->vif.bss_conf.mu_group.membership,
85 params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
86 memcpy(monitor_sdata->vif.bss_conf.mu_group.position,
87 params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
88 WLAN_USER_POSITION_LEN);
89 monitor_sdata->vif.mu_mimo_owner = true;
90 ieee80211_bss_info_change_notify(monitor_sdata,
91 BSS_CHANGED_MU_GROUPS);
92
93 ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr,
94 params->macaddr);
95 }
96
97 if (!flags)
98 return 0;
78 99
79 if (ieee80211_sdata_running(sdata)) { 100 if (ieee80211_sdata_running(sdata)) {
80 u32 mask = MONITOR_FLAG_COOK_FRAMES | 101 u32 mask = MONITOR_FLAG_COOK_FRAMES |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 42a41ae405ba..c39f93b48791 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -162,7 +162,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
162 return; 162 return;
163 163
164 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 164 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
165 sdata->vif.type == NL80211_IFTYPE_MONITOR)) 165 (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
166 !sdata->vif.mu_mimo_owner)))
166 return; 167 return;
167 168
168 if (!check_sdata_in_driver(sdata)) 169 if (!check_sdata_in_driver(sdata))
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9211cce10d3e..75761686a98b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -3,7 +3,7 @@
3 * Copyright 2005, Devicescape Software, Inc. 3 * Copyright 2005, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH 6 * Copyright 2013-2015 Intel Mobile Communications GmbH
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -826,6 +826,7 @@ struct txq_info {
826 826
827struct ieee80211_if_mntr { 827struct ieee80211_if_mntr {
828 u32 flags; 828 u32 flags;
829 u8 mu_follow_addr[ETH_ALEN] __aligned(2);
829}; 830};
830 831
831struct ieee80211_sub_if_data { 832struct ieee80211_sub_if_data {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c8509d95e09d..b0abddc714ef 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -43,6 +43,8 @@
43 * by either the RTNL, the iflist_mtx or RCU. 43 * by either the RTNL, the iflist_mtx or RCU.
44 */ 44 */
45 45
46static void ieee80211_iface_work(struct work_struct *work);
47
46bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) 48bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
47{ 49{
48 struct ieee80211_chanctx_conf *chanctx_conf; 50 struct ieee80211_chanctx_conf *chanctx_conf;
@@ -448,6 +450,9 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
448 return ret; 450 return ret;
449 } 451 }
450 452
453 skb_queue_head_init(&sdata->skb_queue);
454 INIT_WORK(&sdata->work, ieee80211_iface_work);
455
451 return 0; 456 return 0;
452} 457}
453 458
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 708c3b1e49a1..6a265aa73a46 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -485,6 +485,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
485 struct net_device *prev_dev = NULL; 485 struct net_device *prev_dev = NULL;
486 int present_fcs_len = 0; 486 int present_fcs_len = 0;
487 unsigned int rtap_vendor_space = 0; 487 unsigned int rtap_vendor_space = 0;
488 struct ieee80211_mgmt *mgmt;
489 struct ieee80211_sub_if_data *monitor_sdata =
490 rcu_dereference(local->monitor_sdata);
488 491
489 if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) { 492 if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
490 struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data; 493 struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
@@ -585,6 +588,23 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
585 ieee80211_rx_stats(sdata->dev, skb->len); 588 ieee80211_rx_stats(sdata->dev, skb->len);
586 } 589 }
587 590
591 mgmt = (void *)skb->data;
592 if (monitor_sdata &&
593 skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + VHT_MUMIMO_GROUPS_DATA_LEN &&
594 ieee80211_is_action(mgmt->frame_control) &&
595 mgmt->u.action.category == WLAN_CATEGORY_VHT &&
596 mgmt->u.action.u.vht_group_notif.action_code == WLAN_VHT_ACTION_GROUPID_MGMT &&
597 is_valid_ether_addr(monitor_sdata->u.mntr.mu_follow_addr) &&
598 ether_addr_equal(mgmt->da, monitor_sdata->u.mntr.mu_follow_addr)) {
599 struct sk_buff *mu_skb = skb_copy(skb, GFP_ATOMIC);
600
601 if (mu_skb) {
602 mu_skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
603 skb_queue_tail(&monitor_sdata->skb_queue, mu_skb);
604 ieee80211_queue_work(&local->hw, &monitor_sdata->work);
605 }
606 }
607
588 if (prev_dev) { 608 if (prev_dev) {
589 skb->dev = prev_dev; 609 skb->dev = prev_dev;
590 netif_receive_skb(skb); 610 netif_receive_skb(skb);