|
@@ -485,6 +485,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|
|
struct net_device *prev_dev = NULL;
|
|
|
int present_fcs_len = 0;
|
|
|
unsigned int rtap_vendor_space = 0;
|
|
|
+ struct ieee80211_mgmt *mgmt;
|
|
|
+ struct ieee80211_sub_if_data *monitor_sdata =
|
|
|
+ rcu_dereference(local->monitor_sdata);
|
|
|
|
|
|
if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
|
|
|
struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
|
|
@@ -585,6 +588,23 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|
|
ieee80211_rx_stats(sdata->dev, skb->len);
|
|
|
}
|
|
|
|
|
|
+ mgmt = (void *)skb->data;
|
|
|
+ if (monitor_sdata &&
|
|
|
+ skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + VHT_MUMIMO_GROUPS_DATA_LEN &&
|
|
|
+ ieee80211_is_action(mgmt->frame_control) &&
|
|
|
+ mgmt->u.action.category == WLAN_CATEGORY_VHT &&
|
|
|
+ mgmt->u.action.u.vht_group_notif.action_code == WLAN_VHT_ACTION_GROUPID_MGMT &&
|
|
|
+ is_valid_ether_addr(monitor_sdata->u.mntr.mu_follow_addr) &&
|
|
|
+ ether_addr_equal(mgmt->da, monitor_sdata->u.mntr.mu_follow_addr)) {
|
|
|
+ struct sk_buff *mu_skb = skb_copy(skb, GFP_ATOMIC);
|
|
|
+
|
|
|
+ if (mu_skb) {
|
|
|
+ mu_skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
|
|
|
+ skb_queue_tail(&monitor_sdata->skb_queue, mu_skb);
|
|
|
+ ieee80211_queue_work(&local->hw, &monitor_sdata->work);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (prev_dev) {
|
|
|
skb->dev = prev_dev;
|
|
|
netif_receive_skb(skb);
|