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
wpas_populate_mscs_descriptor_ie(struct robust_av_data * robust_av,struct wpabuf * buf)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
wpas_send_mscs_req(struct wpa_supplicant * wpa_s)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
wpas_handle_robust_av_recv_action(struct wpa_supplicant * wpa_s,const u8 * src,const u8 * buf,size_t len)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 = *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
wpas_handle_assoc_resp_mscs(struct wpa_supplicant * wpa_s,const u8 * bssid,const u8 * ies,size_t ies_len)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