@@ -664,27 +664,95 @@ void free_up_scs_desc(struct scs_robust_av_data *data)
}
+static void wpas_parse_mscs_resp(struct wpa_supplicant *wpa_s,
+ u16 status, const u8 *bssid,
+ const u8 *mscs_desc_ie)
+{
+ struct robust_av_data robust_av;
+ const u8 *pos;
+
+ /* it is optional in robust av action frame */
+ if (!mscs_desc_ie)
+ goto event_mscs_result;
+
+ /* ext_id(1) + request type(1) + upc(2) + stream timeout(4) */
+ if (mscs_desc_ie[1] < 8) {
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop received frame: invalid descriptor IE len: %d",
+ mscs_desc_ie[1]);
+ return;
+ }
+
+ os_memset(&robust_av, 0, sizeof(struct robust_av_data));
+
+ pos = &mscs_desc_ie[3];
+ robust_av.request_type = *pos++;
+
+ switch (robust_av.request_type) {
+ case SCS_REQ_CHANGE:
+ /*
+ * inform the suggested set of parameters that could be accepted
+ * by the AP in response to a subsequent request by the station
+ */
+ robust_av.up_bitmap = *pos++;
+ robust_av.up_limit = *pos++;
+ robust_av.stream_timeout = WPA_GET_LE32(pos);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+ " status_code=%u change up_bitmap=%u up_limit=%u stream_timeout=%u",
+ MAC2STR(bssid), status, robust_av.up_bitmap,
+ robust_av.up_limit, robust_av.stream_timeout);
+ wpa_s->mscs_setup_done = false;
+ return;
+ case SCS_REQ_ADD:
+ /*
+ * this type is used in assoc response MSCS descriptor element
+ * if no change required.
+ */
+ break;
+ default:
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop received frame with invalid type: %u",
+ robust_av.request_type);
+ return;
+ }
+
+event_mscs_result:
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
+ " status_code=%u", MAC2STR(bssid), status);
+ wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
+}
+
void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
const u8 *src, const u8 *buf, size_t len)
{
u8 dialog_token;
u16 status_code;
+ const u8 *pos = buf;
+ const u8 *mscs_desc_ie;
if (len < 3)
return;
- dialog_token = *buf++;
- if (dialog_token != wpa_s->robust_av.dialog_token) {
+ dialog_token = *pos++;
+ /* AP sets dialog token to 0 for unsolicited response */
+ if (!dialog_token && !wpa_s->mscs_setup_done) {
wpa_printf(MSG_INFO,
- "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
+ "MSCS: Drop unsolicited received frame: inactive");
+ return;
+ } else if (dialog_token &&
+ dialog_token != wpa_s->robust_av.dialog_token) {
+ wpa_printf(MSG_INFO,
+ "MSCS: Drop frame: dialog token mismatch (got:%u expected:%u",
dialog_token, wpa_s->robust_av.dialog_token);
return;
}
- status_code = WPA_GET_LE16(buf);
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
- " status_code=%u", MAC2STR(src), status_code);
- wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
+ status_code = WPA_GET_LE16(pos);
+
+ /* skip 3 bytes of dialog token(1) + status code(2) */
+ mscs_desc_ie = get_ie_ext(buf + 3, len - 3,
+ WLAN_EID_EXT_MSCS_DESCRIPTOR);
+ wpas_parse_mscs_resp(wpa_s, status_code, src, mscs_desc_ie);
}
@@ -712,9 +780,8 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
return;
status = WPA_GET_LE16(mscs_status + 2);
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
- " status_code=%u", MAC2STR(bssid), status);
- wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
+
+ wpas_parse_mscs_resp(wpa_s, status, bssid, mscs_desc_ie);
}