mac80211: accept public action frames with mismatched BSSID
Arik's patch "mac80211: allow action frames with unknown
BSSID in GO mode" allowed any action frames in P2P mode
to go through, but only to cooked monitor interfaces as
the IEEE80211_RX_RA_MATCH was still cleared. As a result
my no-monitor patches broke invitation responses.
Instead of allowing any action frames in P2P GO mode to
go through with a wrong BSSID like that patch did, allow
all public action frames. They will never be processed
by mac80211, but can be reported via nl80211 then.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 66cedf6..17f2a76 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1695,6 +1695,23 @@
}
/**
+ * ieee80211_is_public_action - check if frame is a public action frame
+ * @hdr: the frame
+ * @len: length of the frame
+ */
+static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
+ size_t len)
+{
+ struct ieee80211_mgmt *mgmt = (void *)hdr;
+
+ if (len < IEEE80211_MIN_ACTION_SIZE)
+ return false;
+ if (!ieee80211_is_action(hdr->frame_control))
+ return false;
+ return mgmt->u.action.category == WLAN_CATEGORY_PUBLIC;
+}
+
+/**
* ieee80211_fhss_chan_to_freq - get channel frequency
* @channel: the FHSS channel
*
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2a85fdf..7d22641 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2797,10 +2797,17 @@
return 0;
} else if (!ieee80211_bssid_match(bssid,
sdata->vif.addr)) {
+ /*
+ * Accept public action frames even when the
+ * BSSID doesn't match, this is used for P2P
+ * and location updates. Note that mac80211
+ * itself never looks at these frames.
+ */
if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
- !ieee80211_is_beacon(hdr->frame_control) &&
- !(ieee80211_is_action(hdr->frame_control) &&
- sdata->vif.p2p))
+ ieee80211_is_public_action(hdr, skb->len))
+ return 1;
+ if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+ !ieee80211_is_beacon(hdr->frame_control))
return 0;
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
}