From c903257fb1aabaec124c5e3f3d7f5b209b1b605b Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Thu, 29 Jul 2021 20:02:22 +0530 Subject: [PATCH] DSCP: Parse WFA Capabilities element in (Re)Association Response frame Add support to parse WFA Capabilities element from the (Re)Association Response frame. Also register a timeout for the station to wait before sending a new DSCP query if requested by AP. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/README | 11 +++++ wpa_supplicant/events.c | 3 ++ wpa_supplicant/robust_av.c | 67 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 4 ++ 4 files changed, 85 insertions(+) diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 231f16661..98cbf3e0a 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -1136,6 +1136,17 @@ is as shown below: - External applications shall clear active DSCP policies upon receiving "CTRL-EVENT-DISCONNECTED" or "CTRL-EVENT-DSCP-POLICY clear_all" events. +- Control interface event message format to indicate wpa_supplicant started + a timer to wait until the unsolicited DSCP request from the AP. + + <3>CTRL-EVENT-DSCP-POLICY request_wait start + +- Control interface event message format to indicate timeout to receive the + unsolicited DSCP request. This event is expected only when an unsolicited + DSCP request is not received from the AP before timeout. + + <3>CTRL-EVENT-DSCP-POLICY request_wait end + DSCP Response: A QoS Management STA that enables DSCP Policy capability shall respond with DSCP response on receipt of a successful DSCP request from its diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e9af7585b..72a2a9c15 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2977,6 +2977,9 @@ no_pfs: wpa_s->assoc_freq = data->assoc_info.freq; + wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); + return 0; } diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index eed140dbc..4eabf2448 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -17,6 +17,7 @@ #define SCS_RESP_TIMEOUT 1 +#define DSCP_REQ_TIMEOUT 5 void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, @@ -550,6 +551,48 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, } +static void wpas_wait_for_dscp_req_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + /* Once timeout is over, reset wait flag and allow sending DSCP query */ + wpa_printf(MSG_DEBUG, + "QM: Wait time over for sending DSCP request - allow DSCP query"); + wpa_s->wait_for_dscp_req = 0; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait end"); +} + + +void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len) +{ + const u8 *wfa_capa; + + wpa_s->connection_dscp = 0; + if (wpa_s->wait_for_dscp_req) + eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); + + if (!ies || ies_len == 0 || !wpa_s->enable_dscp_policy_capa) + return; + + wfa_capa = get_vendor_ie(ies, ies_len, WFA_CAPA_IE_VENDOR_TYPE); + if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 || + !(wfa_capa[7] & WFA_CAPA_QM_DSCP_POLICY)) + return; /* AP does not enable QM DSCP Policy */ + + wpa_s->connection_dscp = 1; + wpa_s->wait_for_dscp_req = !!(wfa_capa[7] & + WFA_CAPA_QM_UNSOLIC_DSCP); + if (!wpa_s->wait_for_dscp_req) + return; + + /* Register a timeout after which dscp query can be sent to AP. */ + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait start"); + eloop_register_timeout(DSCP_REQ_TIMEOUT, 0, + wpas_wait_for_dscp_req_timer, wpa_s, NULL); +} + + void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *buf, size_t len) @@ -1116,6 +1159,11 @@ void wpas_dscp_deinit(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies"); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all"); wpa_s->dscp_req_dialog_token = 0; + wpa_s->connection_dscp = 0; + if (wpa_s->wait_for_dscp_req) { + wpa_s->wait_for_dscp_req = 0; + eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); + } } @@ -1194,6 +1242,12 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s, return; } + if (!wpa_s->connection_dscp) { + wpa_printf(MSG_DEBUG, + "QM: DSCP Policy capability not enabled for the current association - ignore QoS Management Action frames"); + return; + } + if (len < 1) return; @@ -1211,6 +1265,12 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s, return; } + /* Clear wait_for_dscp_req on receiving first DSCP request from AP */ + if (wpa_s->wait_for_dscp_req) { + wpa_s->wait_for_dscp_req = 0; + eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL); + } + wpa_s->dscp_req_dialog_token = buf[1]; more = buf[2] & DSCP_POLICY_CTRL_MORE; reset = buf[2] & DSCP_POLICY_CTRL_RESET; @@ -1289,6 +1349,13 @@ int wpas_send_dscp_response(struct wpa_supplicant *wpa_s, return -1; } + if (!wpa_s->connection_dscp) { + wpa_printf(MSG_ERROR, + "QM: Failed to send DSCP response - DSCP capability not enabled for the current association"); + return -1; + + } + buf_len = 1 + /* Category */ 3 + /* OUI */ 1 + /* OUI Type */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 93a386355..428dfe8e6 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1515,6 +1515,8 @@ struct wpa_supplicant { bool ongoing_scs_req; u8 dscp_req_dialog_token; unsigned int enable_dscp_policy_capa:1; + unsigned int connection_dscp:1; + unsigned int wait_for_dscp_req:1; }; @@ -1861,6 +1863,8 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s, void wpas_dscp_deinit(struct wpa_supplicant *wpa_s); int wpas_send_dscp_response(struct wpa_supplicant *wpa_s, struct dscp_resp_data *resp_data); +void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len); int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid, int akmp, int cipher,