1 /* 2 * wpa_supplicant - Robust AV procedures 3 * Copyright (c) 2020, The Linux Foundation 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 #include "utils/common.h" 11 #include "common/wpa_ctrl.h" 12 #include "common/ieee802_11_common.h" 13 #include "wpa_supplicant_i.h" 14 #include "driver_i.h" 15 #include "bss.h" 16 17 18 void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, 19 struct wpabuf *buf) 20 { 21 u8 *len, *len1; 22 23 /* MSCS descriptor element */ 24 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 25 len = wpabuf_put(buf, 1); 26 wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR); 27 wpabuf_put_u8(buf, robust_av->request_type); 28 wpabuf_put_u8(buf, robust_av->up_bitmap); 29 wpabuf_put_u8(buf, robust_av->up_limit); 30 wpabuf_put_le32(buf, robust_av->stream_timeout); 31 32 if (robust_av->request_type != SCS_REQ_REMOVE) { 33 /* TCLAS mask element */ 34 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 35 len1 = wpabuf_put(buf, 1); 36 wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK); 37 38 /* Frame classifier */ 39 wpabuf_put_data(buf, robust_av->frame_classifier, 40 robust_av->frame_classifier_len); 41 *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; 42 } 43 44 *len = (u8 *) wpabuf_put(buf, 0) - len - 1; 45 } 46 47 48 int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) 49 { 50 struct wpabuf *buf; 51 size_t buf_len; 52 int ret; 53 54 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) 55 return 0; 56 57 if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) { 58 wpa_dbg(wpa_s, MSG_INFO, 59 "AP does not support MSCS - could not send MSCS Req"); 60 return -1; 61 } 62 63 if (!wpa_s->mscs_setup_done && 64 wpa_s->robust_av.request_type != SCS_REQ_ADD) { 65 wpa_msg(wpa_s, MSG_INFO, 66 "MSCS: Failed to send MSCS Request: request type invalid"); 67 return -1; 68 } 69 70 buf_len = 3 + /* Action frame header */ 71 3 + /* MSCS descriptor IE header */ 72 1 + /* Request type */ 73 2 + /* User priority control */ 74 4 + /* Stream timeout */ 75 3 + /* TCLAS Mask IE header */ 76 wpa_s->robust_av.frame_classifier_len; 77 78 buf = wpabuf_alloc(buf_len); 79 if (!buf) { 80 wpa_printf(MSG_ERROR, "Failed to allocate MSCS req"); 81 return -1; 82 } 83 84 wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING); 85 wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ); 86 wpa_s->robust_av.dialog_token++; 87 wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token); 88 89 /* MSCS descriptor element */ 90 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf); 91 92 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf); 93 ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 94 wpa_s->own_addr, wpa_s->bssid, 95 wpabuf_head(buf), wpabuf_len(buf), 0); 96 if (ret < 0) 97 wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request"); 98 99 wpabuf_free(buf); 100 return ret; 101 } 102 103 104 void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, 105 const u8 *src, const u8 *buf, size_t len) 106 { 107 u8 dialog_token; 108 u16 status_code; 109 110 if (len < 3) 111 return; 112 113 dialog_token = *buf++; 114 if (dialog_token != wpa_s->robust_av.dialog_token) { 115 wpa_printf(MSG_INFO, 116 "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u", 117 dialog_token, wpa_s->robust_av.dialog_token); 118 return; 119 } 120 121 status_code = WPA_GET_LE16(buf); 122 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR 123 " status_code=%u", MAC2STR(src), status_code); 124 wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS; 125 } 126 127 128 void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, 129 const u8 *ies, size_t ies_len) 130 { 131 const u8 *mscs_desc_ie, *mscs_status; 132 u16 status; 133 134 /* Process optional MSCS Status subelement when MSCS IE is in 135 * (Re)Association Response frame */ 136 if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config) 137 return; 138 139 mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR); 140 if (!mscs_desc_ie || mscs_desc_ie[1] <= 8) 141 return; 142 143 /* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) + 144 * request type(1) + upc(2) + stream timeout(4) =) 10. 145 */ 146 mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8, 147 MCSC_SUBELEM_STATUS); 148 if (!mscs_status || mscs_status[1] < 2) 149 return; 150 151 status = WPA_GET_LE16(mscs_status + 2); 152 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR 153 " status_code=%u", MAC2STR(bssid), status); 154 wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS; 155 } 156