diff options
author | Aviya Erenfeld <aviya.erenfeld@intel.com> | 2016-08-29 16:25:16 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-09-12 05:44:52 -0400 |
commit | 42bd20d99857e69e368d5421ea402127d5835cd3 (patch) | |
tree | 1ca2460a76e67311a2f5fa9cb0acda1c0a0e32d5 | |
parent | 480dd46b9d6812e5fb7172c305ee0f1154c26eed (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.c | 23 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/iface.c | 5 | ||||
-rw-r--r-- | net/mac80211/rx.c | 20 |
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 | ||
827 | struct ieee80211_if_mntr { | 827 | struct ieee80211_if_mntr { |
828 | u32 flags; | 828 | u32 flags; |
829 | u8 mu_follow_addr[ETH_ALEN] __aligned(2); | ||
829 | }; | 830 | }; |
830 | 831 | ||
831 | struct ieee80211_sub_if_data { | 832 | struct 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 | ||
46 | static void ieee80211_iface_work(struct work_struct *work); | ||
47 | |||
46 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | 48 | bool __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); |