Page MenuHomeFreeBSD

D49575.id152884.diff
No OneTemporary

D49575.id152884.diff

diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -2732,3 +2732,57 @@
*/
return (!ieee80211_is_key_global(vap, key));
}
+
+/**
+ * Determine whether the given control frame is from a known node
+ * and destined to us.
+ *
+ * In some instances a control frame won't have a TA (eg ACKs), so
+ * we should only verify the RA for those.
+ *
+ * @param ni ieee80211_node representing the sender, or BSS node
+ * @param m0 mbuf representing the 802.11 frame.
+ * @returns false if the frame is not a CTL frame (with a warning logged);
+ * true if the frame is from a known sender / valid recipient,
+ * false otherwise.
+ */
+bool
+ieee80211_is_ctl_frame_for_vap(struct ieee80211_node *ni, const struct mbuf *m0)
+{
+ const struct ieee80211vap *vap = ni->ni_vap;
+ const struct ieee80211_frame *wh;
+ uint8_t subtype;
+
+ wh = mtod(m0, const struct ieee80211_frame *);
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ /* Verify it's a ctl frame. */
+ KASSERT(IEEE80211_IS_CTL(wh), ("%s: not a CTL frame (fc[0]=0x%04x)",
+ __func__, wh->i_fc[0]));
+ if (!IEEE80211_IS_CTL(wh)) {
+ if_printf(vap->iv_ifp,
+ "%s: not a control frame (fc[0]=0x%04x)\n",
+ __func__, wh->i_fc[0]);
+ return (false);
+ }
+
+ /* Verify the TA if present. */
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_CTS:
+ case IEEE80211_FC0_SUBTYPE_ACK:
+ /* No TA. */
+ break;
+ default:
+ /*
+ * Verify TA matches ni->ni_macaddr; for unknown
+ * sources it will be the BSS node and ni->ni_macaddr
+ * will the BSS MAC.
+ */
+ if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr))
+ return (false);
+ break;
+ }
+
+ /* Verify the RA */
+ return (IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr));
+}
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -661,7 +661,8 @@
case IEEE80211_FC0_TYPE_CTL:
vap->iv_stats.is_rx_ctl++;
IEEE80211_NODE_STAT(ni, rx_ctrl);
- vap->iv_recv_ctl(ni, m, subtype);
+ if (ieee80211_is_ctl_frame_for_vap(ni, m))
+ vap->iv_recv_ctl(ni, m, subtype);
goto out;
default:
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -889,7 +889,8 @@
case IEEE80211_FC0_TYPE_CTL:
vap->iv_stats.is_rx_ctl++;
IEEE80211_NODE_STAT(ni, rx_ctrl);
- vap->iv_recv_ctl(ni, m, subtype);
+ if (ieee80211_is_ctl_frame_for_vap(ni, m))
+ vap->iv_recv_ctl(ni, m, subtype);
goto out;
default:
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -972,7 +972,8 @@
case IEEE80211_FC0_TYPE_CTL:
vap->iv_stats.is_rx_ctl++;
IEEE80211_NODE_STAT(ni, rx_ctrl);
- vap->iv_recv_ctl(ni, m, subtype);
+ if (ieee80211_is_ctl_frame_for_vap(ni, m))
+ vap->iv_recv_ctl(ni, m, subtype);
goto out;
default:
@@ -2054,6 +2055,7 @@
static void
sta_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
{
+
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_BAR:
ieee80211_recv_bar(ni, m);
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -842,6 +842,9 @@
bool ieee80211_is_key_unicast(const struct ieee80211vap *vap,
const struct ieee80211_key *key);
+bool ieee80211_is_ctl_frame_for_vap(struct ieee80211_node *,
+ const struct mbuf *);
+
void ieee80211_radiotap_attach(struct ieee80211com *,
struct ieee80211_radiotap_header *th, int tlen,
uint32_t tx_radiotap,

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 12, 10:12 PM (7 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25233107
Default Alt Text
D49575.id152884.diff (3 KB)

Event Timeline