diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -161,6 +161,7 @@ /* 0001-0011 Reserved 0x10-0x30 */ /* Were: CF_ACK, CF_POLL, CF_ACPL */ #define IEEE80211_FC0_SUBTYPE_NODATA 0x40 /* Null */ /* 0101-0111 Reserved 0x50-0x70 */ /* Were: CFACK, CFPOLL, CF_ACK_CF_ACK */ +#define IEEE80211_FC0_SUBTYPE_QOS_MASK_ANY 0x80 /* QoS mask - matching any subtypes 8..15 */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA 0x80 /* QoS Data */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA_CFACK 0x90 /* QoS Data +CF-Ack */ #define IEEE80211_FC0_SUBTYPE_QOS_DATA_CFPOLL 0xa0 /* QoS Data +CF-Poll */ @@ -190,24 +191,55 @@ #define IEEE80211_CTL_EXT_TDD_BF 0x0b /* TDD Beamforming, 80211ay-2021 */ /* 1100-1111 Reserved 0xc-0xf */ -#define IEEE80211_IS_MGMT(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_MGT)) +/* Check the version field */ +#define IEEE80211_IS_FC0_CHECK_VER(wh, v) \ + (((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v)) + +/* Check the version and type field */ +#define IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, v, t) \ + (((((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v))) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == (t))) + +/* Check the version, type and subtype field */ +#define IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, v, t, st) \ + (((((wh)->i_fc[0] & IEEE80211_FC0_VERSION_MASK) == (v))) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == (t)) && \ + (((wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == (st))) + +#define IEEE80211_IS_MGMT(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_MGT)) #define IEEE80211_IS_CTL(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_CTL)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_CTL)) #define IEEE80211_IS_DATA(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_DATA)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA)) #define IEEE80211_IS_EXT(wh) \ - (!! (((wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK) \ - == IEEE80211_FC0_TYPE_EXT)) + (IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_EXT)) #define IEEE80211_FC0_QOSDATA \ (IEEE80211_FC0_TYPE_DATA|IEEE80211_FC0_SUBTYPE_QOS_DATA|IEEE80211_FC0_VERSION_0) -#define IEEE80211_IS_QOSDATA(wh) \ - ((wh)->i_fc[0] == IEEE80211_FC0_QOSDATA) +/* + * Return true if the frame is any of the QOS frame types, not just + * data frames. Matching on the IEEE80211_FC0_SUBTYPE_QOS_ANY bit + * being set also matches on subtypes 8..15. + */ +#define IEEE80211_IS_QOS_ANY(wh) \ + ((IEEE80211_IS_FC0_CHECK_VER_TYPE(wh, IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA)) && \ + ((wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS_MASK_ANY)) + +/* + * Return true if this frame is QOS data, and only QOS data. + */ +#define IEEE80211_IS_QOSDATA(wh) \ + (IEEE80211_IS_FC0_CHECK_VER_TYPE_SUBTYPE(wh, \ + IEEE80211_FC0_VERSION_0, \ + IEEE80211_FC0_TYPE_DATA, \ + IEEE80211_FC0_SUBTYPE_QOS_DATA)) #define IEEE80211_FC1_DIR_MASK 0x03 #define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ 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 @@ -362,8 +362,7 @@ */ wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", wh->i_fc[0], wh->i_fc[1]); diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -860,7 +860,8 @@ break; } - if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS_DATA) { + /* Match on any QOS frame, not just data */ + if (IEEE80211_IS_QOS_ANY(wh)) { const struct ieee80211_qosframe *qwh = (const struct ieee80211_qosframe *) wh; hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID; 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 @@ -532,8 +532,7 @@ */ wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", wh->i_fc[0], wh->i_fc[1]); diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -1014,7 +1014,7 @@ /* NB: m_len known to be sufficient */ wh = mtod(m, struct ieee80211_qosframe *); - if (wh->i_fc[0] != IEEE80211_FC0_QOSDATA) { + if (!IEEE80211_IS_QOSDATA(wh)) { /* * Not QoS data, shouldn't get here but just * return it to the caller for processing. diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1564,8 +1564,7 @@ */ wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]); vap->iv_stats.is_rx_badversion++; diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -603,8 +603,7 @@ return (EINVAL); wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) return (EINVAL); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 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 @@ -568,8 +568,7 @@ vap->iv_stats.is_rx_tooshort++; goto err; } - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", wh->i_fc[0], wh->i_fc[1]); diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -465,8 +465,7 @@ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) ni->ni_inact = ni->ni_inact_reload; - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { + if (!IEEE80211_IS_FC0_CHECK_VER(wh, IEEE80211_FC0_VERSION_0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", wh->i_fc[0], wh->i_fc[1]);