diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 4c8f37291..4fdc3b2d9 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -604,6 +604,7 @@ #define WLAN_ACTION_UNPROTECTED_DMG 20 #define WLAN_ACTION_VHT 21 #define WLAN_ACTION_FILS 26 +#define WLAN_ACTION_PROTECTED_FTM 34 #define WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED 126 #define WLAN_ACTION_VENDOR_SPECIFIC 127 /* Note: 128-255 used to report errors by setting category | 0x80 */ @@ -644,6 +645,7 @@ #define WLAN_PA_FTM_REQUEST 32 #define WLAN_PA_FTM 33 #define WLAN_PA_FILS_DISCOVERY 34 +#define WLAN_PA_LOCATION_MEASUREMENT_REPORT 47 /* Protected Dual of Public Action frames (IEEE Std 802.11-2016, 9.6.11, * Table 9-332) */ @@ -701,6 +703,11 @@ #define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4 #define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5 +/* Protected Fine Timing Frame Action Field value */ +#define WLAN_PROT_FTM_REQUEST 1 +#define WLAN_PROT_FTM 2 +#define WLAN_PROT_FTM_REPORT 3 + /* Radio Measurement capabilities (from RM Enabled Capabilities element) * IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */ /* byte 1 (out of 5) */ diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 4c243f97e..f7690e07f 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1916,8 +1916,126 @@ static void rx_mgmt_action_sa_query(struct wlantest *wt, } +static void +rx_mgmt_location_measurement_report(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + const u8 *pos = mgmt->u.action.u.public_action.variable; + const u8 *end = ((const u8 *) mgmt) + len; + + if (end - pos < 1) { + add_note(wt, MSG_INFO, + "Too short Location Measurement Report frame from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + + wpa_printf(MSG_DEBUG, "Location Measurement Report " MACSTR " --> " + MACSTR " (dialog token %u)", + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), *pos); + pos++; + + if (!no_ack) + add_note(wt, MSG_INFO, + "Protected Fine Timing Measurement Report incorrectly as an Action frame from " + MACSTR, MAC2STR(mgmt->sa)); + + wpa_hexdump(MSG_MSGDUMP, "Location Measurement Report contents", + pos, end - pos); +} + + +static void rx_mgmt_action_no_bss_public(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + switch (mgmt->u.action.u.public_action.action) { + case WLAN_PA_LOCATION_MEASUREMENT_REPORT: + rx_mgmt_location_measurement_report(wt, mgmt, len, no_ack); + break; + } +} + + +static void rx_mgmt_prot_ftm_request(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement Request " + MACSTR " --> " MACSTR, + MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); + if (no_ack) + add_note(wt, MSG_INFO, + "Protected Fine Timing Measurement Request incorrectly as an Action No Ack frame from " + MACSTR, MAC2STR(mgmt->sa)); +} + + +static void rx_mgmt_prot_ftm(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement " + MACSTR " --> " MACSTR, + MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); + if (no_ack) + add_note(wt, MSG_INFO, + "Protected Fine Timing Measurement incorrectly as an Action No Ack frame from " + MACSTR, MAC2STR(mgmt->sa)); +} + + +static void rx_mgmt_prot_ftm_report(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement Report " + MACSTR " --> " MACSTR, + MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); + if (!no_ack) + add_note(wt, MSG_INFO, + "Protected Fine Timing Measurement Report incorrectly as an Action frame from " + MACSTR, MAC2STR(mgmt->sa)); +} + + +static void +rx_mgmt_action_no_bss_protected_ftm(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, + size_t len, bool no_ack) +{ + switch (mgmt->u.action.u.public_action.action) { + case WLAN_PROT_FTM_REQUEST: + rx_mgmt_prot_ftm_request(wt, mgmt, len, no_ack); + break; + case WLAN_PROT_FTM: + rx_mgmt_prot_ftm(wt, mgmt, len, no_ack); + break; + case WLAN_PROT_FTM_REPORT: + rx_mgmt_prot_ftm_report(wt, mgmt, len, no_ack); + break; + } +} + + +static void rx_mgmt_action_no_bss(struct wlantest *wt, + const struct ieee80211_mgmt *mgmt, size_t len, + bool no_ack) +{ + switch (mgmt->u.action.category) { + case WLAN_ACTION_PUBLIC: + rx_mgmt_action_no_bss_public(wt, mgmt, len, no_ack); + break; + case WLAN_ACTION_PROTECTED_FTM: + rx_mgmt_action_no_bss_protected_ftm(wt, mgmt, len, no_ack); + break; + } +} + + static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len, - int valid) + int valid, bool no_ack) { const struct ieee80211_mgmt *mgmt; struct wlantest_bss *bss; @@ -1932,6 +2050,24 @@ static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len, MAC2STR(mgmt->bssid), mgmt->u.action.category); return; /* Ignore group addressed Action frames for now */ } + + if (len < 24 + 2) { + add_note(wt, MSG_INFO, "Too short Action frame from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } + + wpa_printf(MSG_DEBUG, "ACTION%s " MACSTR " -> " MACSTR + " BSSID=" MACSTR " (category=%u) (valid=%d)", + no_ack ? "-NO-ACK" : "", + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->bssid), + mgmt->u.action.category, valid); + wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24); + + if (is_broadcast_ether_addr(mgmt->bssid)) { + rx_mgmt_action_no_bss(wt, mgmt, len, no_ack); + return; + } bss = bss_get(wt, mgmt->bssid); if (bss == NULL) return; @@ -1942,18 +2078,6 @@ static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len, if (sta == NULL) return; - if (len < 24 + 1) { - add_note(wt, MSG_INFO, "Too short Action frame from " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR - " (category=%u) (valid=%d)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - mgmt->u.action.category, valid); - wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24); - if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && sta->state < STATE3) { add_note(wt, MSG_INFO, "Action frame sent when STA is not in " @@ -2423,10 +2547,10 @@ void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len) rx_mgmt_disassoc(wt, data, len, valid); break; case WLAN_FC_STYPE_ACTION: - rx_mgmt_action(wt, data, len, valid); + rx_mgmt_action(wt, data, len, valid, false); break; case WLAN_FC_STYPE_ACTION_NO_ACK: - rx_mgmt_action(wt, data, len, valid); + rx_mgmt_action(wt, data, len, valid, true); break; }