robust_av.c revision 1.1 1 1.1 christos /*
2 1.1 christos * wpa_supplicant - Robust AV procedures
3 1.1 christos * Copyright (c) 2020, The Linux Foundation
4 1.1 christos *
5 1.1 christos * This software may be distributed under the terms of the BSD license.
6 1.1 christos * See README for more details.
7 1.1 christos */
8 1.1 christos
9 1.1 christos #include "utils/includes.h"
10 1.1 christos #include "utils/common.h"
11 1.1 christos #include "utils/eloop.h"
12 1.1 christos #include "common/wpa_ctrl.h"
13 1.1 christos #include "common/ieee802_11_common.h"
14 1.1 christos #include "wpa_supplicant_i.h"
15 1.1 christos #include "driver_i.h"
16 1.1 christos #include "bss.h"
17 1.1 christos
18 1.1 christos
19 1.1 christos #define SCS_RESP_TIMEOUT 1
20 1.1 christos #define DSCP_REQ_TIMEOUT 5
21 1.1 christos
22 1.1 christos
23 1.1 christos void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
24 1.1 christos struct wpabuf *buf)
25 1.1 christos {
26 1.1 christos u8 *len, *len1;
27 1.1 christos
28 1.1 christos /* MSCS descriptor element */
29 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
30 1.1 christos len = wpabuf_put(buf, 1);
31 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR);
32 1.1 christos wpabuf_put_u8(buf, robust_av->request_type);
33 1.1 christos wpabuf_put_u8(buf, robust_av->up_bitmap);
34 1.1 christos wpabuf_put_u8(buf, robust_av->up_limit);
35 1.1 christos wpabuf_put_le32(buf, robust_av->stream_timeout);
36 1.1 christos
37 1.1 christos if (robust_av->request_type != SCS_REQ_REMOVE) {
38 1.1 christos /* TCLAS mask element */
39 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
40 1.1 christos len1 = wpabuf_put(buf, 1);
41 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK);
42 1.1 christos
43 1.1 christos /* Frame classifier */
44 1.1 christos wpabuf_put_data(buf, robust_av->frame_classifier,
45 1.1 christos robust_av->frame_classifier_len);
46 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
47 1.1 christos }
48 1.1 christos
49 1.1 christos *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
50 1.1 christos }
51 1.1 christos
52 1.1 christos
53 1.1 christos static int wpas_populate_type4_classifier(struct type4_params *type4_param,
54 1.1 christos struct wpabuf *buf)
55 1.1 christos {
56 1.1 christos /* classifier parameters */
57 1.1 christos wpabuf_put_u8(buf, type4_param->classifier_mask);
58 1.1 christos if (type4_param->ip_version == IPV4) {
59 1.1 christos wpabuf_put_u8(buf, IPV4); /* IP version */
60 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v4.src_ip.s_addr,
61 1.1 christos 4);
62 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v4.dst_ip.s_addr,
63 1.1 christos 4);
64 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v4.src_port);
65 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v4.dst_port);
66 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v4.dscp);
67 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v4.protocol);
68 1.1 christos wpabuf_put_u8(buf, 0); /* Reserved octet */
69 1.1 christos } else {
70 1.1 christos wpabuf_put_u8(buf, IPV6);
71 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v6.src_ip.s6_addr,
72 1.1 christos 16);
73 1.1 christos wpabuf_put_data(buf, &type4_param->ip_params.v6.dst_ip.s6_addr,
74 1.1 christos 16);
75 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v6.src_port);
76 1.1 christos wpabuf_put_be16(buf, type4_param->ip_params.v6.dst_port);
77 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v6.dscp);
78 1.1 christos wpabuf_put_u8(buf, type4_param->ip_params.v6.next_header);
79 1.1 christos wpabuf_put_data(buf, type4_param->ip_params.v6.flow_label, 3);
80 1.1 christos }
81 1.1 christos
82 1.1 christos return 0;
83 1.1 christos }
84 1.1 christos
85 1.1 christos
86 1.1 christos static int wpas_populate_type10_classifier(struct type10_params *type10_param,
87 1.1 christos struct wpabuf *buf)
88 1.1 christos {
89 1.1 christos /* classifier parameters */
90 1.1 christos wpabuf_put_u8(buf, type10_param->prot_instance);
91 1.1 christos wpabuf_put_u8(buf, type10_param->prot_number);
92 1.1 christos wpabuf_put_data(buf, type10_param->filter_value,
93 1.1 christos type10_param->filter_len);
94 1.1 christos wpabuf_put_data(buf, type10_param->filter_mask,
95 1.1 christos type10_param->filter_len);
96 1.1 christos return 0;
97 1.1 christos }
98 1.1 christos
99 1.1 christos
100 1.1 christos static bool tclas_elem_required(const struct qos_characteristics *qos_elem)
101 1.1 christos {
102 1.1 christos if (!qos_elem || !qos_elem->available)
103 1.1 christos return true;
104 1.1 christos
105 1.1 christos if (qos_elem->direction == SCS_DIRECTION_DOWN)
106 1.1 christos return true;
107 1.1 christos
108 1.1 christos return false;
109 1.1 christos }
110 1.1 christos
111 1.1 christos
112 1.1 christos static int wpas_populate_scs_descriptor_ie(struct scs_desc_elem *desc_elem,
113 1.1 christos struct wpabuf *buf,
114 1.1 christos bool allow_scs_traffic_desc)
115 1.1 christos {
116 1.1 christos u8 *len, *len1;
117 1.1 christos struct tclas_element *tclas_elem;
118 1.1 christos unsigned int i;
119 1.1 christos struct qos_characteristics *qos_elem;
120 1.1 christos u32 control_info = 0;
121 1.1 christos
122 1.1 christos /* SCS Descriptor element */
123 1.1 christos wpabuf_put_u8(buf, WLAN_EID_SCS_DESCRIPTOR);
124 1.1 christos len = wpabuf_put(buf, 1);
125 1.1 christos wpabuf_put_u8(buf, desc_elem->scs_id);
126 1.1 christos wpabuf_put_u8(buf, desc_elem->request_type);
127 1.1 christos if (desc_elem->request_type == SCS_REQ_REMOVE)
128 1.1 christos goto end;
129 1.1 christos
130 1.1 christos if (!tclas_elem_required(&desc_elem->qos_char_elem))
131 1.1 christos goto skip_tclas_elem;
132 1.1 christos
133 1.1 christos if (desc_elem->intra_access_priority || desc_elem->scs_up_avail) {
134 1.1 christos wpabuf_put_u8(buf, WLAN_EID_INTRA_ACCESS_CATEGORY_PRIORITY);
135 1.1 christos wpabuf_put_u8(buf, 1);
136 1.1 christos wpabuf_put_u8(buf, desc_elem->intra_access_priority);
137 1.1 christos }
138 1.1 christos
139 1.1 christos tclas_elem = desc_elem->tclas_elems;
140 1.1 christos
141 1.1 christos if (!tclas_elem)
142 1.1 christos return -1;
143 1.1 christos
144 1.1 christos for (i = 0; i < desc_elem->num_tclas_elem; i++, tclas_elem++) {
145 1.1 christos int ret;
146 1.1 christos
147 1.1 christos /* TCLAS element */
148 1.1 christos wpabuf_put_u8(buf, WLAN_EID_TCLAS);
149 1.1 christos len1 = wpabuf_put(buf, 1);
150 1.1 christos wpabuf_put_u8(buf, 255); /* User Priority: not compared */
151 1.1 christos /* Frame Classifier */
152 1.1 christos wpabuf_put_u8(buf, tclas_elem->classifier_type);
153 1.1 christos /* Frame classifier parameters */
154 1.1 christos switch (tclas_elem->classifier_type) {
155 1.1 christos case 4:
156 1.1 christos ret = wpas_populate_type4_classifier(
157 1.1 christos &tclas_elem->frame_classifier.type4_param,
158 1.1 christos buf);
159 1.1 christos break;
160 1.1 christos case 10:
161 1.1 christos ret = wpas_populate_type10_classifier(
162 1.1 christos &tclas_elem->frame_classifier.type10_param,
163 1.1 christos buf);
164 1.1 christos break;
165 1.1 christos default:
166 1.1 christos return -1;
167 1.1 christos }
168 1.1 christos
169 1.1 christos if (ret == -1) {
170 1.1 christos wpa_printf(MSG_ERROR,
171 1.1 christos "Failed to populate frame classifier");
172 1.1 christos return -1;
173 1.1 christos }
174 1.1 christos
175 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
176 1.1 christos }
177 1.1 christos
178 1.1 christos if (desc_elem->num_tclas_elem > 1) {
179 1.1 christos /* TCLAS Processing element */
180 1.1 christos wpabuf_put_u8(buf, WLAN_EID_TCLAS_PROCESSING);
181 1.1 christos wpabuf_put_u8(buf, 1);
182 1.1 christos wpabuf_put_u8(buf, desc_elem->tclas_processing);
183 1.1 christos }
184 1.1 christos
185 1.1 christos skip_tclas_elem:
186 1.1 christos if (allow_scs_traffic_desc && desc_elem->qos_char_elem.available) {
187 1.1 christos qos_elem = &desc_elem->qos_char_elem;
188 1.1 christos /* Element ID, Length, and Element ID Extension */
189 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
190 1.1 christos len1 = wpabuf_put(buf, 1);
191 1.1 christos wpabuf_put_u8(buf, WLAN_EID_EXT_QOS_CHARACTERISTICS);
192 1.1 christos
193 1.1 christos /* Remove invalid mask bits */
194 1.1 christos
195 1.1 christos /* Medium Time is applicable only for direct link */
196 1.1 christos if ((qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME) &&
197 1.1 christos qos_elem->direction != SCS_DIRECTION_DIRECT)
198 1.1 christos qos_elem->mask &= ~SCS_QOS_BIT_MEDIUM_TIME;
199 1.1 christos
200 1.1 christos /* Service Start Time LinkID is valid only when Service Start
201 1.1 christos * Time is present.
202 1.1 christos */
203 1.1 christos if ((qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID) &&
204 1.1 christos !(qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME))
205 1.1 christos qos_elem->mask &=
206 1.1 christos ~SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
207 1.1 christos
208 1.1 christos /* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element,
209 1.1 christos * Figure 9-1001av (Control Info field format)
210 1.1 christos */
211 1.1 christos control_info = ((u32) qos_elem->direction <<
212 1.1 christos EHT_QOS_CONTROL_INFO_DIRECTION_OFFSET);
213 1.1 christos control_info |= ((u32) desc_elem->intra_access_priority <<
214 1.1 christos EHT_QOS_CONTROL_INFO_TID_OFFSET);
215 1.1 christos control_info |= ((u32) desc_elem->intra_access_priority <<
216 1.1 christos EHT_QOS_CONTROL_INFO_USER_PRIORITY_OFFSET);
217 1.1 christos control_info |= ((u32) qos_elem->mask <<
218 1.1 christos EHT_QOS_CONTROL_INFO_PRESENCE_MASK_OFFSET);
219 1.1 christos
220 1.1 christos /* Control Info */
221 1.1 christos wpabuf_put_le32(buf, control_info);
222 1.1 christos /* Minimum Service Interval */
223 1.1 christos wpabuf_put_le32(buf, qos_elem->min_si);
224 1.1 christos /* Maximum Service Interval */
225 1.1 christos wpabuf_put_le32(buf, qos_elem->max_si);
226 1.1 christos /* Minimum Data Rate */
227 1.1 christos wpabuf_put_le24(buf, qos_elem->min_data_rate);
228 1.1 christos /* Delay Bound */
229 1.1 christos wpabuf_put_le24(buf, qos_elem->delay_bound);
230 1.1 christos
231 1.1 christos /* Maximum MSDU Size */
232 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MAX_MSDU_SIZE)
233 1.1 christos wpabuf_put_le16(buf, qos_elem->max_msdu_size);
234 1.1 christos /* Start Service Time */
235 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME)
236 1.1 christos wpabuf_put_le32(buf, qos_elem->service_start_time);
237 1.1 christos /* Service Start Time LinkID */
238 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID)
239 1.1 christos wpabuf_put_u8(buf,
240 1.1 christos qos_elem->service_start_time_link_id);
241 1.1 christos /* Mean Data Rate */
242 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEAN_DATA_RATE)
243 1.1 christos wpabuf_put_le24(buf, qos_elem->mean_data_rate);
244 1.1 christos /* Delayed Bounded Burst Size */
245 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE)
246 1.1 christos wpabuf_put_le32(buf, qos_elem->burst_size);
247 1.1 christos /* MSDU Lifetime */
248 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_LIFETIME)
249 1.1 christos wpabuf_put_le16(buf, qos_elem->msdu_lifetime);
250 1.1 christos /* MSDU Delivery Info */
251 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_DELIVERY_INFO)
252 1.1 christos wpabuf_put_u8(buf, qos_elem->msdu_delivery_info);
253 1.1 christos /* Medium Time */
254 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME)
255 1.1 christos wpabuf_put_le16(buf, qos_elem->medium_time);
256 1.1 christos
257 1.1 christos *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
258 1.1 christos }
259 1.1 christos
260 1.1 christos end:
261 1.1 christos *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
262 1.1 christos return 0;
263 1.1 christos }
264 1.1 christos
265 1.1 christos
266 1.1 christos int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
267 1.1 christos {
268 1.1 christos struct wpabuf *buf;
269 1.1 christos size_t buf_len;
270 1.1 christos int ret;
271 1.1 christos
272 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
273 1.1 christos return 0;
274 1.1 christos
275 1.1 christos if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) {
276 1.1 christos wpa_dbg(wpa_s, MSG_INFO,
277 1.1 christos "AP does not support MSCS - could not send MSCS Req");
278 1.1 christos return -1;
279 1.1 christos }
280 1.1 christos
281 1.1 christos if (!wpa_s->mscs_setup_done &&
282 1.1 christos wpa_s->robust_av.request_type != SCS_REQ_ADD) {
283 1.1 christos wpa_msg(wpa_s, MSG_INFO,
284 1.1 christos "MSCS: Failed to send MSCS Request: request type invalid");
285 1.1 christos return -1;
286 1.1 christos }
287 1.1 christos
288 1.1 christos buf_len = 3 + /* Action frame header */
289 1.1 christos 3 + /* MSCS descriptor IE header */
290 1.1 christos 1 + /* Request type */
291 1.1 christos 2 + /* User priority control */
292 1.1 christos 4 + /* Stream timeout */
293 1.1 christos 3 + /* TCLAS Mask IE header */
294 1.1 christos wpa_s->robust_av.frame_classifier_len;
295 1.1 christos
296 1.1 christos buf = wpabuf_alloc(buf_len);
297 1.1 christos if (!buf) {
298 1.1 christos wpa_printf(MSG_ERROR, "Failed to allocate MSCS req");
299 1.1 christos return -1;
300 1.1 christos }
301 1.1 christos
302 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
303 1.1 christos wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ);
304 1.1 christos wpa_s->robust_av.dialog_token++;
305 1.1 christos wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token);
306 1.1 christos
307 1.1 christos /* MSCS descriptor element */
308 1.1 christos wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf);
309 1.1 christos
310 1.1 christos wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf);
311 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
312 1.1 christos wpa_s->own_addr, wpa_s->bssid,
313 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0);
314 1.1 christos if (ret < 0)
315 1.1 christos wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request");
316 1.1 christos
317 1.1 christos wpabuf_free(buf);
318 1.1 christos return ret;
319 1.1 christos }
320 1.1 christos
321 1.1 christos
322 1.1 christos static size_t tclas_elem_len(const struct tclas_element *elem)
323 1.1 christos {
324 1.1 christos size_t buf_len = 0;
325 1.1 christos
326 1.1 christos buf_len += 2 + /* TCLAS element header */
327 1.1 christos 1 + /* User Priority */
328 1.1 christos 1 ; /* Classifier Type */
329 1.1 christos
330 1.1 christos if (elem->classifier_type == 4) {
331 1.1 christos enum ip_version ip_ver;
332 1.1 christos
333 1.1 christos buf_len += 1 + /* Classifier mask */
334 1.1 christos 1 + /* IP version */
335 1.1 christos 1 + /* user priority */
336 1.1 christos 2 + /* src_port */
337 1.1 christos 2 + /* dst_port */
338 1.1 christos 1 ; /* dscp */
339 1.1 christos ip_ver = elem->frame_classifier.type4_param.ip_version;
340 1.1 christos if (ip_ver == IPV4) {
341 1.1 christos buf_len += 4 + /* src_ip */
342 1.1 christos 4 + /* dst_ip */
343 1.1 christos 1 + /* protocol */
344 1.1 christos 1 ; /* Reserved */
345 1.1 christos } else if (ip_ver == IPV6) {
346 1.1 christos buf_len += 16 + /* src_ip */
347 1.1 christos 16 + /* dst_ip */
348 1.1 christos 1 + /* next_header */
349 1.1 christos 3 ; /* flow_label */
350 1.1 christos } else {
351 1.1 christos wpa_printf(MSG_ERROR, "%s: Incorrect IP version %d",
352 1.1 christos __func__, ip_ver);
353 1.1 christos return 0;
354 1.1 christos }
355 1.1 christos } else if (elem->classifier_type == 10) {
356 1.1 christos buf_len += 1 + /* protocol instance */
357 1.1 christos 1 + /* protocol number */
358 1.1 christos 2 * elem->frame_classifier.type10_param.filter_len;
359 1.1 christos } else {
360 1.1 christos wpa_printf(MSG_ERROR, "%s: Incorrect classifier type %u",
361 1.1 christos __func__, elem->classifier_type);
362 1.1 christos return 0;
363 1.1 christos }
364 1.1 christos
365 1.1 christos return buf_len;
366 1.1 christos }
367 1.1 christos
368 1.1 christos
369 1.1 christos static size_t qos_char_len(const struct qos_characteristics *qos_elem)
370 1.1 christos {
371 1.1 christos size_t buf_len = 0;
372 1.1 christos
373 1.1 christos buf_len += 1 + /* Element ID */
374 1.1 christos 1 + /* Length */
375 1.1 christos 1 + /* Element ID Extension */
376 1.1 christos 4 + /* Control Info */
377 1.1 christos 4 + /* Minimum Service Interval */
378 1.1 christos 4 + /* Maximum Service Interval */
379 1.1 christos 3 + /* Minimum Data Rate */
380 1.1 christos 3; /* Delay Bound */
381 1.1 christos
382 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MAX_MSDU_SIZE)
383 1.1 christos buf_len += 2; /* Maximum MSDU Size */
384 1.1 christos
385 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME) {
386 1.1 christos buf_len += 4; /* Service Start Time */
387 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_SERVICE_START_TIME_LINKID)
388 1.1 christos buf_len++; /* Service Start Time LinkID */
389 1.1 christos }
390 1.1 christos
391 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEAN_DATA_RATE)
392 1.1 christos buf_len += 3; /* Mean Data Rate */
393 1.1 christos
394 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE)
395 1.1 christos buf_len += 4; /* Delayed Bounded Burst Size */
396 1.1 christos
397 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_LIFETIME)
398 1.1 christos buf_len += 2; /* MSDU Lifetime */
399 1.1 christos
400 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MSDU_DELIVERY_INFO)
401 1.1 christos buf_len++; /* MSDU Delivery Info */
402 1.1 christos
403 1.1 christos if (qos_elem->mask & SCS_QOS_BIT_MEDIUM_TIME &&
404 1.1 christos qos_elem->direction == SCS_DIRECTION_DIRECT)
405 1.1 christos buf_len += 2; /* Medium Time */
406 1.1 christos
407 1.1 christos return buf_len;
408 1.1 christos }
409 1.1 christos
410 1.1 christos
411 1.1 christos static struct wpabuf * allocate_scs_buf(struct scs_desc_elem *desc_elem,
412 1.1 christos unsigned int num_scs_desc,
413 1.1 christos bool allow_scs_traffic_desc)
414 1.1 christos {
415 1.1 christos struct wpabuf *buf;
416 1.1 christos size_t buf_len = 0;
417 1.1 christos unsigned int i, j;
418 1.1 christos
419 1.1 christos buf_len = 3; /* Action frame header */
420 1.1 christos
421 1.1 christos for (i = 0; i < num_scs_desc; i++, desc_elem++) {
422 1.1 christos struct tclas_element *tclas_elem;
423 1.1 christos
424 1.1 christos buf_len += 2 + /* SCS descriptor IE header */
425 1.1 christos 1 + /* SCSID */
426 1.1 christos 1 ; /* Request type */
427 1.1 christos
428 1.1 christos if (desc_elem->request_type == SCS_REQ_REMOVE)
429 1.1 christos continue;
430 1.1 christos
431 1.1 christos if (allow_scs_traffic_desc &&
432 1.1 christos desc_elem->qos_char_elem.available)
433 1.1 christos buf_len += qos_char_len(&desc_elem->qos_char_elem);
434 1.1 christos
435 1.1 christos if (!tclas_elem_required(&desc_elem->qos_char_elem))
436 1.1 christos continue;
437 1.1 christos
438 1.1 christos if (desc_elem->intra_access_priority || desc_elem->scs_up_avail)
439 1.1 christos buf_len += 3;
440 1.1 christos
441 1.1 christos tclas_elem = desc_elem->tclas_elems;
442 1.1 christos if (!tclas_elem) {
443 1.1 christos wpa_printf(MSG_ERROR, "%s: TCLAS element null",
444 1.1 christos __func__);
445 1.1 christos return NULL;
446 1.1 christos }
447 1.1 christos
448 1.1 christos for (j = 0; j < desc_elem->num_tclas_elem; j++, tclas_elem++) {
449 1.1 christos size_t elen;
450 1.1 christos
451 1.1 christos elen = tclas_elem_len(tclas_elem);
452 1.1 christos if (elen == 0)
453 1.1 christos return NULL;
454 1.1 christos buf_len += elen;
455 1.1 christos }
456 1.1 christos
457 1.1 christos if (desc_elem->num_tclas_elem > 1) {
458 1.1 christos buf_len += 1 + /* TCLAS Processing eid */
459 1.1 christos 1 + /* length */
460 1.1 christos 1 ; /* processing */
461 1.1 christos }
462 1.1 christos }
463 1.1 christos
464 1.1 christos buf = wpabuf_alloc(buf_len);
465 1.1 christos if (!buf) {
466 1.1 christos wpa_printf(MSG_ERROR, "Failed to allocate SCS req");
467 1.1 christos return NULL;
468 1.1 christos }
469 1.1 christos
470 1.1 christos return buf;
471 1.1 christos }
472 1.1 christos
473 1.1 christos
474 1.1 christos static void scs_request_timer(void *eloop_ctx, void *timeout_ctx)
475 1.1 christos {
476 1.1 christos struct wpa_supplicant *wpa_s = eloop_ctx;
477 1.1 christos struct active_scs_elem *scs_desc, *prev;
478 1.1 christos
479 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
480 1.1 christos return;
481 1.1 christos
482 1.1 christos /* Once timeout is over, remove all SCS descriptors with no response */
483 1.1 christos dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids,
484 1.1 christos struct active_scs_elem, list) {
485 1.1 christos u8 bssid[ETH_ALEN] = { 0 };
486 1.1 christos const u8 *src;
487 1.1 christos
488 1.1 christos if (scs_desc->status == SCS_DESC_SUCCESS)
489 1.1 christos continue;
490 1.1 christos
491 1.1 christos if (wpa_s->current_bss)
492 1.1 christos src = wpa_s->current_bss->bssid;
493 1.1 christos else
494 1.1 christos src = bssid;
495 1.1 christos
496 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR
497 1.1 christos " SCSID=%u status_code=timedout", MAC2STR(src),
498 1.1 christos scs_desc->scs_id);
499 1.1 christos
500 1.1 christos dl_list_del(&scs_desc->list);
501 1.1 christos wpa_printf(MSG_INFO, "%s: SCSID %d removed after timeout",
502 1.1 christos __func__, scs_desc->scs_id);
503 1.1 christos os_free(scs_desc);
504 1.1 christos }
505 1.1 christos
506 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
507 1.1 christos wpa_s->ongoing_scs_req = false;
508 1.1 christos }
509 1.1 christos
510 1.1 christos
511 1.1 christos int wpas_send_scs_req(struct wpa_supplicant *wpa_s)
512 1.1 christos {
513 1.1 christos struct wpabuf *buf = NULL;
514 1.1 christos struct scs_desc_elem *desc_elem = NULL;
515 1.1 christos const struct ieee80211_eht_capabilities *eht;
516 1.1 christos const u8 *eht_ie;
517 1.1 christos int ret = -1;
518 1.1 christos unsigned int i;
519 1.1 christos bool allow_scs_traffic_desc = false;
520 1.1 christos
521 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
522 1.1 christos return -1;
523 1.1 christos
524 1.1 christos if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_SCS)) {
525 1.1 christos wpa_dbg(wpa_s, MSG_INFO,
526 1.1 christos "AP does not support SCS - could not send SCS Request");
527 1.1 christos return -1;
528 1.1 christos }
529 1.1 christos
530 1.1 christos desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems;
531 1.1 christos if (!desc_elem)
532 1.1 christos return -1;
533 1.1 christos
534 1.1 christos if (wpa_is_non_eht_scs_traffic_desc_supported(wpa_s->current_bss))
535 1.1 christos allow_scs_traffic_desc = true;
536 1.1 christos
537 1.1 christos /* Allow SCS Traffic descriptor support for EHT connection */
538 1.1 christos eht_ie = wpa_bss_get_ie_ext(wpa_s->current_bss,
539 1.1 christos WLAN_EID_EXT_EHT_CAPABILITIES);
540 1.1 christos if (wpa_s->connection_eht && eht_ie &&
541 1.1 christos eht_ie[1] >= 1 + IEEE80211_EHT_CAPAB_MIN_LEN) {
542 1.1 christos eht = (const struct ieee80211_eht_capabilities *) &eht_ie[3];
543 1.1 christos if (eht->mac_cap & EHT_MACCAP_SCS_TRAFFIC_DESC)
544 1.1 christos allow_scs_traffic_desc = true;
545 1.1 christos }
546 1.1 christos
547 1.1 christos if (!allow_scs_traffic_desc && desc_elem->qos_char_elem.available) {
548 1.1 christos wpa_dbg(wpa_s, MSG_INFO,
549 1.1 christos "Connection does not support EHT/non-EHT SCS Traffic Description - could not send SCS Request with QoS Characteristics");
550 1.1 christos return -1;
551 1.1 christos }
552 1.1 christos
553 1.1 christos buf = allocate_scs_buf(desc_elem,
554 1.1 christos wpa_s->scs_robust_av_req.num_scs_desc,
555 1.1 christos allow_scs_traffic_desc);
556 1.1 christos if (!buf)
557 1.1 christos return -1;
558 1.1 christos
559 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
560 1.1 christos wpabuf_put_u8(buf, ROBUST_AV_SCS_REQ);
561 1.1 christos wpa_s->scs_dialog_token++;
562 1.1 christos if (wpa_s->scs_dialog_token == 0)
563 1.1 christos wpa_s->scs_dialog_token++;
564 1.1 christos wpabuf_put_u8(buf, wpa_s->scs_dialog_token);
565 1.1 christos
566 1.1 christos for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc;
567 1.1 christos i++, desc_elem++) {
568 1.1 christos /* SCS Descriptor element */
569 1.1 christos if (wpas_populate_scs_descriptor_ie(desc_elem, buf,
570 1.1 christos allow_scs_traffic_desc) < 0)
571 1.1 christos goto end;
572 1.1 christos }
573 1.1 christos
574 1.1 christos wpa_hexdump_buf(MSG_DEBUG, "SCS Request", buf);
575 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
576 1.1 christos wpa_s->own_addr, wpa_s->bssid,
577 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0);
578 1.1 christos if (ret < 0) {
579 1.1 christos wpa_dbg(wpa_s, MSG_ERROR, "SCS: Failed to send SCS Request");
580 1.1 christos wpa_s->scs_dialog_token--;
581 1.1 christos goto end;
582 1.1 christos }
583 1.1 christos
584 1.1 christos desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems;
585 1.1 christos for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc;
586 1.1 christos i++, desc_elem++) {
587 1.1 christos struct active_scs_elem *active_scs_elem;
588 1.1 christos
589 1.1 christos if (desc_elem->request_type != SCS_REQ_ADD)
590 1.1 christos continue;
591 1.1 christos
592 1.1 christos active_scs_elem = os_malloc(sizeof(struct active_scs_elem));
593 1.1 christos if (!active_scs_elem)
594 1.1 christos break;
595 1.1 christos active_scs_elem->scs_id = desc_elem->scs_id;
596 1.1 christos active_scs_elem->status = SCS_DESC_SENT;
597 1.1 christos dl_list_add(&wpa_s->active_scs_ids, &active_scs_elem->list);
598 1.1 christos }
599 1.1 christos
600 1.1 christos /*
601 1.1 christos * Register a timeout after which this request will be removed from
602 1.1 christos * the cache.
603 1.1 christos */
604 1.1 christos eloop_register_timeout(SCS_RESP_TIMEOUT, 0, scs_request_timer, wpa_s,
605 1.1 christos NULL);
606 1.1 christos wpa_s->ongoing_scs_req = true;
607 1.1 christos
608 1.1 christos end:
609 1.1 christos wpabuf_free(buf);
610 1.1 christos free_up_scs_desc(&wpa_s->scs_robust_av_req);
611 1.1 christos
612 1.1 christos return ret;
613 1.1 christos }
614 1.1 christos
615 1.1 christos
616 1.1 christos void free_up_tclas_elem(struct scs_desc_elem *elem)
617 1.1 christos {
618 1.1 christos struct tclas_element *tclas_elems = elem->tclas_elems;
619 1.1 christos unsigned int num_tclas_elem = elem->num_tclas_elem;
620 1.1 christos struct tclas_element *tclas_data;
621 1.1 christos unsigned int j;
622 1.1 christos
623 1.1 christos elem->tclas_elems = NULL;
624 1.1 christos elem->num_tclas_elem = 0;
625 1.1 christos
626 1.1 christos if (!tclas_elems)
627 1.1 christos return;
628 1.1 christos
629 1.1 christos tclas_data = tclas_elems;
630 1.1 christos for (j = 0; j < num_tclas_elem; j++, tclas_data++) {
631 1.1 christos if (tclas_data->classifier_type != 10)
632 1.1 christos continue;
633 1.1 christos
634 1.1 christos os_free(tclas_data->frame_classifier.type10_param.filter_value);
635 1.1 christos os_free(tclas_data->frame_classifier.type10_param.filter_mask);
636 1.1 christos }
637 1.1 christos
638 1.1 christos os_free(tclas_elems);
639 1.1 christos }
640 1.1 christos
641 1.1 christos
642 1.1 christos void free_up_scs_desc(struct scs_robust_av_data *data)
643 1.1 christos {
644 1.1 christos struct scs_desc_elem *desc_elems = data->scs_desc_elems;
645 1.1 christos unsigned int num_scs_desc = data->num_scs_desc;
646 1.1 christos struct scs_desc_elem *desc_data;
647 1.1 christos unsigned int i;
648 1.1 christos
649 1.1 christos data->scs_desc_elems = NULL;
650 1.1 christos data->num_scs_desc = 0;
651 1.1 christos
652 1.1 christos if (!desc_elems)
653 1.1 christos return;
654 1.1 christos
655 1.1 christos desc_data = desc_elems;
656 1.1 christos for (i = 0; i < num_scs_desc; i++, desc_data++) {
657 1.1 christos if (desc_data->request_type == SCS_REQ_REMOVE ||
658 1.1 christos !desc_data->tclas_elems)
659 1.1 christos continue;
660 1.1 christos
661 1.1 christos free_up_tclas_elem(desc_data);
662 1.1 christos }
663 1.1 christos os_free(desc_elems);
664 1.1 christos }
665 1.1 christos
666 1.1 christos
667 1.1 christos /* Element ID Extension(1) + Request Type(1) + User Priority Control(2) +
668 1.1 christos * Stream Timeout(4) */
669 1.1 christos #define MSCS_DESCRIPTOR_FIXED_LEN 8
670 1.1 christos
671 1.1 christos static void wpas_parse_mscs_resp(struct wpa_supplicant *wpa_s,
672 1.1 christos u16 status, const u8 *bssid,
673 1.1 christos const u8 *mscs_desc_ie)
674 1.1 christos {
675 1.1 christos struct robust_av_data robust_av;
676 1.1 christos const u8 *pos;
677 1.1 christos
678 1.1 christos /* The MSCS Descriptor element is optional in the MSCS Response frame */
679 1.1 christos if (!mscs_desc_ie)
680 1.1 christos goto event_mscs_result;
681 1.1 christos
682 1.1 christos if (mscs_desc_ie[1] < MSCS_DESCRIPTOR_FIXED_LEN) {
683 1.1 christos wpa_printf(MSG_INFO,
684 1.1 christos "MSCS: Drop received frame: invalid MSCS Descriptor element length: %d",
685 1.1 christos mscs_desc_ie[1]);
686 1.1 christos return;
687 1.1 christos }
688 1.1 christos
689 1.1 christos os_memset(&robust_av, 0, sizeof(struct robust_av_data));
690 1.1 christos
691 1.1 christos /* Skip Element ID, Length, and Element ID Extension */
692 1.1 christos pos = &mscs_desc_ie[3];
693 1.1 christos
694 1.1 christos robust_av.request_type = *pos++;
695 1.1 christos
696 1.1 christos switch (robust_av.request_type) {
697 1.1 christos case SCS_REQ_CHANGE:
698 1.1 christos /*
699 1.1 christos * Inform the suggested set of parameters that could be accepted
700 1.1 christos * by the AP in response to a subsequent request by the station.
701 1.1 christos */
702 1.1 christos robust_av.up_bitmap = *pos++;
703 1.1 christos robust_av.up_limit = *pos++ & 0x07;
704 1.1 christos robust_av.stream_timeout = WPA_GET_LE32(pos);
705 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
706 1.1 christos " status_code=%u change up_bitmap=%u up_limit=%u stream_timeout=%u",
707 1.1 christos MAC2STR(bssid), status, robust_av.up_bitmap,
708 1.1 christos robust_av.up_limit, robust_av.stream_timeout);
709 1.1 christos wpa_s->mscs_setup_done = false;
710 1.1 christos return;
711 1.1 christos case SCS_REQ_ADD:
712 1.1 christos /*
713 1.1 christos * This type is used in (Re)Association Response frame MSCS
714 1.1 christos * Descriptor element if no change is required.
715 1.1 christos */
716 1.1 christos break;
717 1.1 christos default:
718 1.1 christos wpa_printf(MSG_INFO,
719 1.1 christos "MSCS: Drop received frame with unknown Request Type: %u",
720 1.1 christos robust_av.request_type);
721 1.1 christos return;
722 1.1 christos }
723 1.1 christos
724 1.1 christos event_mscs_result:
725 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
726 1.1 christos " status_code=%u", MAC2STR(bssid), status);
727 1.1 christos wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
728 1.1 christos }
729 1.1 christos
730 1.1 christos
731 1.1 christos void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
732 1.1 christos const u8 *src, const u8 *buf, size_t len)
733 1.1 christos {
734 1.1 christos u8 dialog_token;
735 1.1 christos u16 status_code;
736 1.1 christos const u8 *mscs_desc_ie;
737 1.1 christos
738 1.1 christos if (len < 3)
739 1.1 christos return;
740 1.1 christos
741 1.1 christos dialog_token = *buf++;
742 1.1 christos len--;
743 1.1 christos
744 1.1 christos /* AP sets dialog token to 0 for unsolicited response */
745 1.1 christos if (!dialog_token && !wpa_s->mscs_setup_done) {
746 1.1 christos wpa_printf(MSG_INFO,
747 1.1 christos "MSCS: Drop unsolicited received frame: inactive");
748 1.1 christos return;
749 1.1 christos }
750 1.1 christos
751 1.1 christos if (dialog_token && dialog_token != wpa_s->robust_av.dialog_token) {
752 1.1 christos wpa_printf(MSG_INFO,
753 1.1 christos "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
754 1.1 christos dialog_token, wpa_s->robust_av.dialog_token);
755 1.1 christos return;
756 1.1 christos }
757 1.1 christos
758 1.1 christos status_code = WPA_GET_LE16(buf);
759 1.1 christos buf += 2;
760 1.1 christos len -= 2;
761 1.1 christos
762 1.1 christos mscs_desc_ie = get_ie_ext(buf, len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
763 1.1 christos wpas_parse_mscs_resp(wpa_s, status_code, src, mscs_desc_ie);
764 1.1 christos }
765 1.1 christos
766 1.1 christos
767 1.1 christos void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
768 1.1 christos const u8 *ies, size_t ies_len)
769 1.1 christos {
770 1.1 christos const u8 *mscs_desc_ie, *mscs_status;
771 1.1 christos u16 status;
772 1.1 christos
773 1.1 christos /* Process optional MSCS Status subelement when MSCS IE is in
774 1.1 christos * (Re)Association Response frame */
775 1.1 christos if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config)
776 1.1 christos return;
777 1.1 christos
778 1.1 christos mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR);
779 1.1 christos if (!mscs_desc_ie || mscs_desc_ie[1] <= MSCS_DESCRIPTOR_FIXED_LEN)
780 1.1 christos return;
781 1.1 christos
782 1.1 christos /* Subelements start after element header and fixed fields */
783 1.1 christos mscs_status = get_ie(&mscs_desc_ie[2 + MSCS_DESCRIPTOR_FIXED_LEN],
784 1.1 christos mscs_desc_ie[1] - MSCS_DESCRIPTOR_FIXED_LEN,
785 1.1 christos MCSC_SUBELEM_STATUS);
786 1.1 christos if (!mscs_status || mscs_status[1] < 2)
787 1.1 christos return;
788 1.1 christos
789 1.1 christos status = WPA_GET_LE16(mscs_status + 2);
790 1.1 christos
791 1.1 christos wpas_parse_mscs_resp(wpa_s, status, bssid, mscs_desc_ie);
792 1.1 christos }
793 1.1 christos
794 1.1 christos
795 1.1 christos static void wpas_wait_for_dscp_req_timer(void *eloop_ctx, void *timeout_ctx)
796 1.1 christos {
797 1.1 christos struct wpa_supplicant *wpa_s = eloop_ctx;
798 1.1 christos
799 1.1 christos /* Once timeout is over, reset wait flag and allow sending DSCP query */
800 1.1 christos wpa_printf(MSG_DEBUG,
801 1.1 christos "QM: Wait time over for sending DSCP request - allow DSCP query");
802 1.1 christos wpa_s->wait_for_dscp_req = 0;
803 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait end");
804 1.1 christos }
805 1.1 christos
806 1.1 christos
807 1.1 christos void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
808 1.1 christos const u8 *ies, size_t ies_len)
809 1.1 christos {
810 1.1 christos const u8 *wfa_capa;
811 1.1 christos
812 1.1 christos wpa_s->connection_dscp = 0;
813 1.1 christos if (wpa_s->wait_for_dscp_req)
814 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
815 1.1 christos
816 1.1 christos if (!ies || ies_len == 0 || !wpa_s->enable_dscp_policy_capa)
817 1.1 christos return;
818 1.1 christos
819 1.1 christos wfa_capa = get_vendor_ie(ies, ies_len, WFA_CAPA_IE_VENDOR_TYPE);
820 1.1 christos if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
821 1.1 christos !(wfa_capa[7] & WFA_CAPA_QM_DSCP_POLICY))
822 1.1 christos return; /* AP does not enable QM DSCP Policy */
823 1.1 christos
824 1.1 christos wpa_s->connection_dscp = 1;
825 1.1 christos wpa_s->wait_for_dscp_req = !!(wfa_capa[7] &
826 1.1 christos WFA_CAPA_QM_UNSOLIC_DSCP);
827 1.1 christos if (!wpa_s->wait_for_dscp_req)
828 1.1 christos return;
829 1.1 christos
830 1.1 christos /* Register a timeout after which dscp query can be sent to AP. */
831 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait start");
832 1.1 christos eloop_register_timeout(DSCP_REQ_TIMEOUT, 0,
833 1.1 christos wpas_wait_for_dscp_req_timer, wpa_s, NULL);
834 1.1 christos }
835 1.1 christos
836 1.1 christos
837 1.1 christos void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s,
838 1.1 christos const u8 *src, const u8 *buf,
839 1.1 christos size_t len)
840 1.1 christos {
841 1.1 christos u8 dialog_token;
842 1.1 christos unsigned int i, count;
843 1.1 christos struct active_scs_elem *scs_desc, *prev;
844 1.1 christos
845 1.1 christos if (len < 2)
846 1.1 christos return;
847 1.1 christos if (!wpa_s->ongoing_scs_req) {
848 1.1 christos wpa_printf(MSG_INFO,
849 1.1 christos "SCS: Drop received response due to no ongoing request");
850 1.1 christos return;
851 1.1 christos }
852 1.1 christos
853 1.1 christos dialog_token = *buf++;
854 1.1 christos len--;
855 1.1 christos if (dialog_token != wpa_s->scs_dialog_token) {
856 1.1 christos wpa_printf(MSG_INFO,
857 1.1 christos "SCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
858 1.1 christos dialog_token, wpa_s->scs_dialog_token);
859 1.1 christos return;
860 1.1 christos }
861 1.1 christos
862 1.1 christos /* This Count field does not exist in the IEEE Std 802.11-2020
863 1.1 christos * definition of the SCS Response frame. However, it was accepted to
864 1.1 christos * be added into REVme per REVme/D0.0 CC35 CID 49 (edits in document
865 1.1 christos * 11-21-0688-07). */
866 1.1 christos count = *buf++;
867 1.1 christos len--;
868 1.1 christos if (count == 0 || count * 3 > len) {
869 1.1 christos wpa_printf(MSG_INFO,
870 1.1 christos "SCS: Drop received frame due to invalid count: %u (remaining %zu octets)",
871 1.1 christos count, len);
872 1.1 christos return;
873 1.1 christos }
874 1.1 christos
875 1.1 christos for (i = 0; i < count; i++) {
876 1.1 christos u8 id;
877 1.1 christos u16 status;
878 1.1 christos bool scs_desc_found = false;
879 1.1 christos
880 1.1 christos id = *buf++;
881 1.1 christos status = WPA_GET_LE16(buf);
882 1.1 christos buf += 2;
883 1.1 christos len -= 3;
884 1.1 christos
885 1.1 christos dl_list_for_each(scs_desc, &wpa_s->active_scs_ids,
886 1.1 christos struct active_scs_elem, list) {
887 1.1 christos if (id == scs_desc->scs_id) {
888 1.1 christos scs_desc_found = true;
889 1.1 christos break;
890 1.1 christos }
891 1.1 christos }
892 1.1 christos
893 1.1 christos if (!scs_desc_found) {
894 1.1 christos wpa_printf(MSG_INFO, "SCS: SCS ID invalid %u", id);
895 1.1 christos continue;
896 1.1 christos }
897 1.1 christos
898 1.1 christos if (status != WLAN_STATUS_SUCCESS) {
899 1.1 christos dl_list_del(&scs_desc->list);
900 1.1 christos os_free(scs_desc);
901 1.1 christos } else if (status == WLAN_STATUS_SUCCESS) {
902 1.1 christos scs_desc->status = SCS_DESC_SUCCESS;
903 1.1 christos }
904 1.1 christos
905 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR
906 1.1 christos " SCSID=%u status_code=%u", MAC2STR(src), id, status);
907 1.1 christos }
908 1.1 christos
909 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
910 1.1 christos wpa_s->ongoing_scs_req = false;
911 1.1 christos
912 1.1 christos dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids,
913 1.1 christos struct active_scs_elem, list) {
914 1.1 christos if (scs_desc->status != SCS_DESC_SUCCESS) {
915 1.1 christos wpa_msg(wpa_s, MSG_INFO,
916 1.1 christos WPA_EVENT_SCS_RESULT "bssid=" MACSTR
917 1.1 christos " SCSID=%u status_code=response_not_received",
918 1.1 christos MAC2STR(src), scs_desc->scs_id);
919 1.1 christos dl_list_del(&scs_desc->list);
920 1.1 christos os_free(scs_desc);
921 1.1 christos }
922 1.1 christos }
923 1.1 christos }
924 1.1 christos
925 1.1 christos
926 1.1 christos static void wpas_clear_active_scs_ids(struct wpa_supplicant *wpa_s)
927 1.1 christos {
928 1.1 christos struct active_scs_elem *scs_elem;
929 1.1 christos
930 1.1 christos while ((scs_elem = dl_list_first(&wpa_s->active_scs_ids,
931 1.1 christos struct active_scs_elem, list))) {
932 1.1 christos dl_list_del(&scs_elem->list);
933 1.1 christos os_free(scs_elem);
934 1.1 christos }
935 1.1 christos }
936 1.1 christos
937 1.1 christos
938 1.1 christos void wpas_scs_deinit(struct wpa_supplicant *wpa_s)
939 1.1 christos {
940 1.1 christos free_up_scs_desc(&wpa_s->scs_robust_av_req);
941 1.1 christos wpa_s->scs_dialog_token = 0;
942 1.1 christos wpas_clear_active_scs_ids(wpa_s);
943 1.1 christos eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
944 1.1 christos wpa_s->ongoing_scs_req = false;
945 1.1 christos }
946 1.1 christos
947 1.1 christos
948 1.1 christos static int write_ipv4_info(char *pos, int total_len,
949 1.1 christos const struct ipv4_params *v4,
950 1.1 christos u8 classifier_mask)
951 1.1 christos {
952 1.1 christos int res, rem_len;
953 1.1 christos char addr[INET_ADDRSTRLEN];
954 1.1 christos
955 1.1 christos rem_len = total_len;
956 1.1 christos
957 1.1 christos if (classifier_mask & BIT(1)) {
958 1.1 christos if (!inet_ntop(AF_INET, &v4->src_ip, addr, INET_ADDRSTRLEN)) {
959 1.1 christos wpa_printf(MSG_ERROR,
960 1.1 christos "QM: Failed to set IPv4 source address");
961 1.1 christos return -1;
962 1.1 christos }
963 1.1 christos
964 1.1 christos res = os_snprintf(pos, rem_len, " src_ip=%s", addr);
965 1.1 christos if (os_snprintf_error(rem_len, res))
966 1.1 christos return -1;
967 1.1 christos
968 1.1 christos pos += res;
969 1.1 christos rem_len -= res;
970 1.1 christos }
971 1.1 christos
972 1.1 christos if (classifier_mask & BIT(2)) {
973 1.1 christos if (!inet_ntop(AF_INET, &v4->dst_ip, addr, INET_ADDRSTRLEN)) {
974 1.1 christos wpa_printf(MSG_ERROR,
975 1.1 christos "QM: Failed to set IPv4 destination address");
976 1.1 christos return -1;
977 1.1 christos }
978 1.1 christos
979 1.1 christos res = os_snprintf(pos, rem_len, " dst_ip=%s", addr);
980 1.1 christos if (os_snprintf_error(rem_len, res))
981 1.1 christos return -1;
982 1.1 christos
983 1.1 christos pos += res;
984 1.1 christos rem_len -= res;
985 1.1 christos }
986 1.1 christos
987 1.1 christos if (classifier_mask & BIT(3)) {
988 1.1 christos res = os_snprintf(pos, rem_len, " src_port=%d", v4->src_port);
989 1.1 christos if (os_snprintf_error(rem_len, res))
990 1.1 christos return -1;
991 1.1 christos
992 1.1 christos pos += res;
993 1.1 christos rem_len -= res;
994 1.1 christos }
995 1.1 christos
996 1.1 christos if (classifier_mask & BIT(4)) {
997 1.1 christos res = os_snprintf(pos, rem_len, " dst_port=%d", v4->dst_port);
998 1.1 christos if (os_snprintf_error(rem_len, res))
999 1.1 christos return -1;
1000 1.1 christos
1001 1.1 christos pos += res;
1002 1.1 christos rem_len -= res;
1003 1.1 christos }
1004 1.1 christos
1005 1.1 christos if (classifier_mask & BIT(6)) {
1006 1.1 christos res = os_snprintf(pos, rem_len, " protocol=%d", v4->protocol);
1007 1.1 christos if (os_snprintf_error(rem_len, res))
1008 1.1 christos return -1;
1009 1.1 christos
1010 1.1 christos pos += res;
1011 1.1 christos rem_len -= res;
1012 1.1 christos }
1013 1.1 christos
1014 1.1 christos return total_len - rem_len;
1015 1.1 christos }
1016 1.1 christos
1017 1.1 christos
1018 1.1 christos static int write_ipv6_info(char *pos, int total_len,
1019 1.1 christos const struct ipv6_params *v6,
1020 1.1 christos u8 classifier_mask)
1021 1.1 christos {
1022 1.1 christos int res, rem_len;
1023 1.1 christos char addr[INET6_ADDRSTRLEN];
1024 1.1 christos
1025 1.1 christos rem_len = total_len;
1026 1.1 christos
1027 1.1 christos if (classifier_mask & BIT(1)) {
1028 1.1 christos if (!inet_ntop(AF_INET6, &v6->src_ip, addr, INET6_ADDRSTRLEN)) {
1029 1.1 christos wpa_printf(MSG_ERROR,
1030 1.1 christos "QM: Failed to set IPv6 source addr");
1031 1.1 christos return -1;
1032 1.1 christos }
1033 1.1 christos
1034 1.1 christos res = os_snprintf(pos, rem_len, " src_ip=%s", addr);
1035 1.1 christos if (os_snprintf_error(rem_len, res))
1036 1.1 christos return -1;
1037 1.1 christos
1038 1.1 christos pos += res;
1039 1.1 christos rem_len -= res;
1040 1.1 christos }
1041 1.1 christos
1042 1.1 christos if (classifier_mask & BIT(2)) {
1043 1.1 christos if (!inet_ntop(AF_INET6, &v6->dst_ip, addr, INET6_ADDRSTRLEN)) {
1044 1.1 christos wpa_printf(MSG_ERROR,
1045 1.1 christos "QM: Failed to set IPv6 destination addr");
1046 1.1 christos return -1;
1047 1.1 christos }
1048 1.1 christos
1049 1.1 christos res = os_snprintf(pos, rem_len, " dst_ip=%s", addr);
1050 1.1 christos if (os_snprintf_error(rem_len, res))
1051 1.1 christos return -1;
1052 1.1 christos
1053 1.1 christos pos += res;
1054 1.1 christos rem_len -= res;
1055 1.1 christos }
1056 1.1 christos
1057 1.1 christos if (classifier_mask & BIT(3)) {
1058 1.1 christos res = os_snprintf(pos, rem_len, " src_port=%d", v6->src_port);
1059 1.1 christos if (os_snprintf_error(rem_len, res))
1060 1.1 christos return -1;
1061 1.1 christos
1062 1.1 christos pos += res;
1063 1.1 christos rem_len -= res;
1064 1.1 christos }
1065 1.1 christos
1066 1.1 christos if (classifier_mask & BIT(4)) {
1067 1.1 christos res = os_snprintf(pos, rem_len, " dst_port=%d", v6->dst_port);
1068 1.1 christos if (os_snprintf_error(rem_len, res))
1069 1.1 christos return -1;
1070 1.1 christos
1071 1.1 christos pos += res;
1072 1.1 christos rem_len -= res;
1073 1.1 christos }
1074 1.1 christos
1075 1.1 christos if (classifier_mask & BIT(6)) {
1076 1.1 christos res = os_snprintf(pos, rem_len, " protocol=%d",
1077 1.1 christos v6->next_header);
1078 1.1 christos if (os_snprintf_error(rem_len, res))
1079 1.1 christos return -1;
1080 1.1 christos
1081 1.1 christos pos += res;
1082 1.1 christos rem_len -= res;
1083 1.1 christos }
1084 1.1 christos
1085 1.1 christos return total_len - rem_len;
1086 1.1 christos }
1087 1.1 christos
1088 1.1 christos
1089 1.1 christos struct dscp_policy_data {
1090 1.1 christos u8 policy_id;
1091 1.1 christos u8 req_type;
1092 1.1 christos u8 dscp;
1093 1.1 christos bool dscp_info;
1094 1.1 christos const u8 *frame_classifier;
1095 1.1 christos u8 frame_classifier_len;
1096 1.1 christos struct type4_params type4_param;
1097 1.1 christos const u8 *domain_name;
1098 1.1 christos u8 domain_name_len;
1099 1.1 christos u16 start_port;
1100 1.1 christos u16 end_port;
1101 1.1 christos bool port_range_info;
1102 1.1 christos };
1103 1.1 christos
1104 1.1 christos
1105 1.1 christos static int set_frame_classifier_type4_ipv4(struct dscp_policy_data *policy)
1106 1.1 christos {
1107 1.1 christos u8 classifier_mask;
1108 1.1 christos const u8 *frame_classifier = policy->frame_classifier;
1109 1.1 christos struct type4_params *type4_param = &policy->type4_param;
1110 1.1 christos
1111 1.1 christos if (policy->frame_classifier_len < 18) {
1112 1.1 christos wpa_printf(MSG_ERROR,
1113 1.1 christos "QM: Received IPv4 frame classifier with insufficient length %d",
1114 1.1 christos policy->frame_classifier_len);
1115 1.1 christos return -1;
1116 1.1 christos }
1117 1.1 christos
1118 1.1 christos classifier_mask = frame_classifier[1];
1119 1.1 christos
1120 1.1 christos /* Classifier Mask - bit 1 = Source IP Address */
1121 1.1 christos if (classifier_mask & BIT(1)) {
1122 1.1 christos type4_param->classifier_mask |= BIT(1);
1123 1.1 christos os_memcpy(&type4_param->ip_params.v4.src_ip,
1124 1.1 christos &frame_classifier[3], 4);
1125 1.1 christos }
1126 1.1 christos
1127 1.1 christos /* Classifier Mask - bit 2 = Destination IP Address */
1128 1.1 christos if (classifier_mask & BIT(2)) {
1129 1.1 christos if (policy->domain_name) {
1130 1.1 christos wpa_printf(MSG_ERROR,
1131 1.1 christos "QM: IPv4: Both domain name and destination IP address not expected");
1132 1.1 christos return -1;
1133 1.1 christos }
1134 1.1 christos
1135 1.1 christos type4_param->classifier_mask |= BIT(2);
1136 1.1 christos os_memcpy(&type4_param->ip_params.v4.dst_ip,
1137 1.1 christos &frame_classifier[7], 4);
1138 1.1 christos }
1139 1.1 christos
1140 1.1 christos /* Classifier Mask - bit 3 = Source Port */
1141 1.1 christos if (classifier_mask & BIT(3)) {
1142 1.1 christos type4_param->classifier_mask |= BIT(3);
1143 1.1 christos type4_param->ip_params.v4.src_port =
1144 1.1 christos WPA_GET_BE16(&frame_classifier[11]);
1145 1.1 christos }
1146 1.1 christos
1147 1.1 christos /* Classifier Mask - bit 4 = Destination Port */
1148 1.1 christos if (classifier_mask & BIT(4)) {
1149 1.1 christos if (policy->port_range_info) {
1150 1.1 christos wpa_printf(MSG_ERROR,
1151 1.1 christos "QM: IPv4: Both port range and destination port not expected");
1152 1.1 christos return -1;
1153 1.1 christos }
1154 1.1 christos
1155 1.1 christos type4_param->classifier_mask |= BIT(4);
1156 1.1 christos type4_param->ip_params.v4.dst_port =
1157 1.1 christos WPA_GET_BE16(&frame_classifier[13]);
1158 1.1 christos }
1159 1.1 christos
1160 1.1 christos /* Classifier Mask - bit 5 = DSCP (ignored) */
1161 1.1 christos
1162 1.1 christos /* Classifier Mask - bit 6 = Protocol */
1163 1.1 christos if (classifier_mask & BIT(6)) {
1164 1.1 christos type4_param->classifier_mask |= BIT(6);
1165 1.1 christos type4_param->ip_params.v4.protocol = frame_classifier[16];
1166 1.1 christos }
1167 1.1 christos
1168 1.1 christos return 0;
1169 1.1 christos }
1170 1.1 christos
1171 1.1 christos
1172 1.1 christos static int set_frame_classifier_type4_ipv6(struct dscp_policy_data *policy)
1173 1.1 christos {
1174 1.1 christos u8 classifier_mask;
1175 1.1 christos const u8 *frame_classifier = policy->frame_classifier;
1176 1.1 christos struct type4_params *type4_param = &policy->type4_param;
1177 1.1 christos
1178 1.1 christos if (policy->frame_classifier_len < 44) {
1179 1.1 christos wpa_printf(MSG_ERROR,
1180 1.1 christos "QM: Received IPv6 frame classifier with insufficient length %d",
1181 1.1 christos policy->frame_classifier_len);
1182 1.1 christos return -1;
1183 1.1 christos }
1184 1.1 christos
1185 1.1 christos classifier_mask = frame_classifier[1];
1186 1.1 christos
1187 1.1 christos /* Classifier Mask - bit 1 = Source IP Address */
1188 1.1 christos if (classifier_mask & BIT(1)) {
1189 1.1 christos type4_param->classifier_mask |= BIT(1);
1190 1.1 christos os_memcpy(&type4_param->ip_params.v6.src_ip,
1191 1.1 christos &frame_classifier[3], 16);
1192 1.1 christos }
1193 1.1 christos
1194 1.1 christos /* Classifier Mask - bit 2 = Destination IP Address */
1195 1.1 christos if (classifier_mask & BIT(2)) {
1196 1.1 christos if (policy->domain_name) {
1197 1.1 christos wpa_printf(MSG_ERROR,
1198 1.1 christos "QM: IPv6: Both domain name and destination IP address not expected");
1199 1.1 christos return -1;
1200 1.1 christos }
1201 1.1 christos type4_param->classifier_mask |= BIT(2);
1202 1.1 christos os_memcpy(&type4_param->ip_params.v6.dst_ip,
1203 1.1 christos &frame_classifier[19], 16);
1204 1.1 christos }
1205 1.1 christos
1206 1.1 christos /* Classifier Mask - bit 3 = Source Port */
1207 1.1 christos if (classifier_mask & BIT(3)) {
1208 1.1 christos type4_param->classifier_mask |= BIT(3);
1209 1.1 christos type4_param->ip_params.v6.src_port =
1210 1.1 christos WPA_GET_BE16(&frame_classifier[35]);
1211 1.1 christos }
1212 1.1 christos
1213 1.1 christos /* Classifier Mask - bit 4 = Destination Port */
1214 1.1 christos if (classifier_mask & BIT(4)) {
1215 1.1 christos if (policy->port_range_info) {
1216 1.1 christos wpa_printf(MSG_ERROR,
1217 1.1 christos "IPv6: Both port range and destination port not expected");
1218 1.1 christos return -1;
1219 1.1 christos }
1220 1.1 christos
1221 1.1 christos type4_param->classifier_mask |= BIT(4);
1222 1.1 christos type4_param->ip_params.v6.dst_port =
1223 1.1 christos WPA_GET_BE16(&frame_classifier[37]);
1224 1.1 christos }
1225 1.1 christos
1226 1.1 christos /* Classifier Mask - bit 5 = DSCP (ignored) */
1227 1.1 christos
1228 1.1 christos /* Classifier Mask - bit 6 = Next Header */
1229 1.1 christos if (classifier_mask & BIT(6)) {
1230 1.1 christos type4_param->classifier_mask |= BIT(6);
1231 1.1 christos type4_param->ip_params.v6.next_header = frame_classifier[40];
1232 1.1 christos }
1233 1.1 christos
1234 1.1 christos return 0;
1235 1.1 christos }
1236 1.1 christos
1237 1.1 christos
1238 1.1 christos static int wpas_set_frame_classifier_params(struct dscp_policy_data *policy)
1239 1.1 christos {
1240 1.1 christos const u8 *frame_classifier = policy->frame_classifier;
1241 1.1 christos u8 frame_classifier_len = policy->frame_classifier_len;
1242 1.1 christos
1243 1.1 christos if (frame_classifier_len < 3) {
1244 1.1 christos wpa_printf(MSG_ERROR,
1245 1.1 christos "QM: Received frame classifier with insufficient length %d",
1246 1.1 christos frame_classifier_len);
1247 1.1 christos return -1;
1248 1.1 christos }
1249 1.1 christos
1250 1.1 christos /* Only allowed Classifier Type: IP and higher layer parameters (4) */
1251 1.1 christos if (frame_classifier[0] != 4) {
1252 1.1 christos wpa_printf(MSG_ERROR,
1253 1.1 christos "QM: Received frame classifier with invalid classifier type %d",
1254 1.1 christos frame_classifier[0]);
1255 1.1 christos return -1;
1256 1.1 christos }
1257 1.1 christos
1258 1.1 christos /* Classifier Mask - bit 0 = Version */
1259 1.1 christos if (!(frame_classifier[1] & BIT(0))) {
1260 1.1 christos wpa_printf(MSG_ERROR,
1261 1.1 christos "QM: Received frame classifier without IP version");
1262 1.1 christos return -1;
1263 1.1 christos }
1264 1.1 christos
1265 1.1 christos /* Version (4 or 6) */
1266 1.1 christos if (frame_classifier[2] == 4) {
1267 1.1 christos if (set_frame_classifier_type4_ipv4(policy)) {
1268 1.1 christos wpa_printf(MSG_ERROR,
1269 1.1 christos "QM: Failed to set IPv4 parameters");
1270 1.1 christos return -1;
1271 1.1 christos }
1272 1.1 christos
1273 1.1 christos policy->type4_param.ip_version = IPV4;
1274 1.1 christos } else if (frame_classifier[2] == 6) {
1275 1.1 christos if (set_frame_classifier_type4_ipv6(policy)) {
1276 1.1 christos wpa_printf(MSG_ERROR,
1277 1.1 christos "QM: Failed to set IPv6 parameters");
1278 1.1 christos return -1;
1279 1.1 christos }
1280 1.1 christos
1281 1.1 christos policy->type4_param.ip_version = IPV6;
1282 1.1 christos } else {
1283 1.1 christos wpa_printf(MSG_ERROR,
1284 1.1 christos "QM: Received unknown IP version %d",
1285 1.1 christos frame_classifier[2]);
1286 1.1 christos return -1;
1287 1.1 christos }
1288 1.1 christos
1289 1.1 christos return 0;
1290 1.1 christos }
1291 1.1 christos
1292 1.1 christos
1293 1.1 christos static bool dscp_valid_domain_name(const char *str)
1294 1.1 christos {
1295 1.1 christos if (!str[0])
1296 1.1 christos return false;
1297 1.1 christos
1298 1.1 christos while (*str) {
1299 1.1 christos if (is_ctrl_char(*str) || *str == ' ' || *str == '=')
1300 1.1 christos return false;
1301 1.1 christos str++;
1302 1.1 christos }
1303 1.1 christos
1304 1.1 christos return true;
1305 1.1 christos }
1306 1.1 christos
1307 1.1 christos
1308 1.1 christos static void wpas_add_dscp_policy(struct wpa_supplicant *wpa_s,
1309 1.1 christos struct dscp_policy_data *policy)
1310 1.1 christos {
1311 1.1 christos int ip_ver = 0, res;
1312 1.1 christos char policy_str[1000], *pos;
1313 1.1 christos int len;
1314 1.1 christos
1315 1.1 christos if (!policy->frame_classifier && !policy->domain_name &&
1316 1.1 christos !policy->port_range_info) {
1317 1.1 christos wpa_printf(MSG_ERROR,
1318 1.1 christos "QM: Invalid DSCP policy - no attributes present");
1319 1.1 christos goto fail;
1320 1.1 christos }
1321 1.1 christos
1322 1.1 christos policy_str[0] = '\0';
1323 1.1 christos pos = policy_str;
1324 1.1 christos len = sizeof(policy_str);
1325 1.1 christos
1326 1.1 christos if (policy->frame_classifier) {
1327 1.1 christos struct type4_params *type4 = &policy->type4_param;
1328 1.1 christos
1329 1.1 christos if (wpas_set_frame_classifier_params(policy)) {
1330 1.1 christos wpa_printf(MSG_ERROR,
1331 1.1 christos "QM: Failed to set frame classifier parameters");
1332 1.1 christos goto fail;
1333 1.1 christos }
1334 1.1 christos
1335 1.1 christos if (type4->ip_version == IPV4)
1336 1.1 christos res = write_ipv4_info(pos, len, &type4->ip_params.v4,
1337 1.1 christos type4->classifier_mask);
1338 1.1 christos else
1339 1.1 christos res = write_ipv6_info(pos, len, &type4->ip_params.v6,
1340 1.1 christos type4->classifier_mask);
1341 1.1 christos
1342 1.1 christos if (res <= 0) {
1343 1.1 christos wpa_printf(MSG_ERROR,
1344 1.1 christos "QM: Failed to write IP parameters");
1345 1.1 christos goto fail;
1346 1.1 christos }
1347 1.1 christos
1348 1.1 christos ip_ver = type4->ip_version;
1349 1.1 christos
1350 1.1 christos pos += res;
1351 1.1 christos len -= res;
1352 1.1 christos }
1353 1.1 christos
1354 1.1 christos if (policy->port_range_info) {
1355 1.1 christos res = os_snprintf(pos, len, " start_port=%u end_port=%u",
1356 1.1 christos policy->start_port, policy->end_port);
1357 1.1 christos if (os_snprintf_error(len, res)) {
1358 1.1 christos wpa_printf(MSG_ERROR,
1359 1.1 christos "QM: Failed to write port range attributes for policy id = %d",
1360 1.1 christos policy->policy_id);
1361 1.1 christos goto fail;
1362 1.1 christos }
1363 1.1 christos
1364 1.1 christos pos += res;
1365 1.1 christos len -= res;
1366 1.1 christos }
1367 1.1 christos
1368 1.1 christos if (policy->domain_name) {
1369 1.1 christos char domain_name_str[250];
1370 1.1 christos
1371 1.1 christos if (policy->domain_name_len >= sizeof(domain_name_str)) {
1372 1.1 christos wpa_printf(MSG_ERROR,
1373 1.1 christos "QM: Domain name length higher than max expected");
1374 1.1 christos goto fail;
1375 1.1 christos }
1376 1.1 christos os_memcpy(domain_name_str, policy->domain_name,
1377 1.1 christos policy->domain_name_len);
1378 1.1 christos domain_name_str[policy->domain_name_len] = '\0';
1379 1.1 christos if (!dscp_valid_domain_name(domain_name_str)) {
1380 1.1 christos wpa_printf(MSG_ERROR, "QM: Invalid domain name string");
1381 1.1 christos goto fail;
1382 1.1 christos }
1383 1.1 christos res = os_snprintf(pos, len, " domain_name=%s", domain_name_str);
1384 1.1 christos if (os_snprintf_error(len, res)) {
1385 1.1 christos wpa_printf(MSG_ERROR,
1386 1.1 christos "QM: Failed to write domain name attribute for policy id = %d",
1387 1.1 christos policy->policy_id);
1388 1.1 christos goto fail;
1389 1.1 christos }
1390 1.1 christos }
1391 1.1 christos
1392 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
1393 1.1 christos "add policy_id=%u dscp=%u ip_version=%d%s",
1394 1.1 christos policy->policy_id, policy->dscp, ip_ver, policy_str);
1395 1.1 christos return;
1396 1.1 christos fail:
1397 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "reject policy_id=%u",
1398 1.1 christos policy->policy_id);
1399 1.1 christos }
1400 1.1 christos
1401 1.1 christos
1402 1.1 christos void wpas_dscp_deinit(struct wpa_supplicant *wpa_s)
1403 1.1 christos {
1404 1.1 christos wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
1405 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
1406 1.1 christos wpa_s->dscp_req_dialog_token = 0;
1407 1.1 christos wpa_s->dscp_query_dialog_token = 0;
1408 1.1 christos wpa_s->connection_dscp = 0;
1409 1.1 christos if (wpa_s->wait_for_dscp_req) {
1410 1.1 christos wpa_s->wait_for_dscp_req = 0;
1411 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
1412 1.1 christos }
1413 1.1 christos }
1414 1.1 christos
1415 1.1 christos
1416 1.1 christos static void wpas_fill_dscp_policy(struct dscp_policy_data *policy, u8 attr_id,
1417 1.1 christos u8 attr_len, const u8 *attr_data)
1418 1.1 christos {
1419 1.1 christos switch (attr_id) {
1420 1.1 christos case QM_ATTR_PORT_RANGE:
1421 1.1 christos if (attr_len < 4) {
1422 1.1 christos wpa_printf(MSG_ERROR,
1423 1.1 christos "QM: Received Port Range attribute with insufficient length %d",
1424 1.1 christos attr_len);
1425 1.1 christos break;
1426 1.1 christos }
1427 1.1 christos policy->start_port = WPA_GET_BE16(attr_data);
1428 1.1 christos policy->end_port = WPA_GET_BE16(attr_data + 2);
1429 1.1 christos policy->port_range_info = true;
1430 1.1 christos break;
1431 1.1 christos case QM_ATTR_DSCP_POLICY:
1432 1.1 christos if (attr_len < 3) {
1433 1.1 christos wpa_printf(MSG_ERROR,
1434 1.1 christos "QM: Received DSCP Policy attribute with insufficient length %d",
1435 1.1 christos attr_len);
1436 1.1 christos return;
1437 1.1 christos }
1438 1.1 christos policy->policy_id = attr_data[0];
1439 1.1 christos policy->req_type = attr_data[1];
1440 1.1 christos policy->dscp = attr_data[2];
1441 1.1 christos policy->dscp_info = true;
1442 1.1 christos break;
1443 1.1 christos case QM_ATTR_TCLAS:
1444 1.1 christos if (attr_len < 1) {
1445 1.1 christos wpa_printf(MSG_ERROR,
1446 1.1 christos "QM: Received TCLAS attribute with insufficient length %d",
1447 1.1 christos attr_len);
1448 1.1 christos return;
1449 1.1 christos }
1450 1.1 christos policy->frame_classifier = attr_data;
1451 1.1 christos policy->frame_classifier_len = attr_len;
1452 1.1 christos break;
1453 1.1 christos case QM_ATTR_DOMAIN_NAME:
1454 1.1 christos if (attr_len < 1) {
1455 1.1 christos wpa_printf(MSG_ERROR,
1456 1.1 christos "QM: Received domain name attribute with insufficient length %d",
1457 1.1 christos attr_len);
1458 1.1 christos return;
1459 1.1 christos }
1460 1.1 christos policy->domain_name = attr_data;
1461 1.1 christos policy->domain_name_len = attr_len;
1462 1.1 christos break;
1463 1.1 christos default:
1464 1.1 christos wpa_printf(MSG_ERROR, "QM: Received invalid QoS attribute %d",
1465 1.1 christos attr_id);
1466 1.1 christos break;
1467 1.1 christos }
1468 1.1 christos }
1469 1.1 christos
1470 1.1 christos
1471 1.1 christos void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
1472 1.1 christos const u8 *src,
1473 1.1 christos const u8 *buf, size_t len)
1474 1.1 christos {
1475 1.1 christos int rem_len;
1476 1.1 christos const u8 *qos_ie, *attr;
1477 1.1 christos int more, reset;
1478 1.1 christos
1479 1.1 christos if (!wpa_s->enable_dscp_policy_capa) {
1480 1.1 christos wpa_printf(MSG_ERROR,
1481 1.1 christos "QM: Ignore DSCP Policy frame since the capability is not enabled");
1482 1.1 christos return;
1483 1.1 christos }
1484 1.1 christos
1485 1.1 christos if (!pmf_in_use(wpa_s, src)) {
1486 1.1 christos wpa_printf(MSG_ERROR,
1487 1.1 christos "QM: Ignore DSCP Policy frame since PMF is not in use");
1488 1.1 christos return;
1489 1.1 christos }
1490 1.1 christos
1491 1.1 christos if (!wpa_s->connection_dscp) {
1492 1.1 christos wpa_printf(MSG_DEBUG,
1493 1.1 christos "QM: DSCP Policy capability not enabled for the current association - ignore QoS Management Action frames");
1494 1.1 christos return;
1495 1.1 christos }
1496 1.1 christos
1497 1.1 christos if (len < 1)
1498 1.1 christos return;
1499 1.1 christos
1500 1.1 christos /* Handle only DSCP Policy Request frame */
1501 1.1 christos if (buf[0] != QM_DSCP_POLICY_REQ) {
1502 1.1 christos wpa_printf(MSG_ERROR, "QM: Received unexpected QoS action frame %d",
1503 1.1 christos buf[0]);
1504 1.1 christos return;
1505 1.1 christos }
1506 1.1 christos
1507 1.1 christos if (len < 3) {
1508 1.1 christos wpa_printf(MSG_ERROR,
1509 1.1 christos "Received QoS Management DSCP Policy Request frame with invalid length %zu",
1510 1.1 christos len);
1511 1.1 christos return;
1512 1.1 christos }
1513 1.1 christos
1514 1.1 christos /* Clear wait_for_dscp_req on receiving first DSCP request from AP */
1515 1.1 christos if (wpa_s->wait_for_dscp_req) {
1516 1.1 christos wpa_s->wait_for_dscp_req = 0;
1517 1.1 christos eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
1518 1.1 christos }
1519 1.1 christos
1520 1.1 christos wpa_s->dscp_req_dialog_token = buf[1];
1521 1.1 christos more = buf[2] & DSCP_POLICY_CTRL_MORE;
1522 1.1 christos reset = buf[2] & DSCP_POLICY_CTRL_RESET;
1523 1.1 christos
1524 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_start%s%s",
1525 1.1 christos reset ? " clear_all" : "", more ? " more" : "");
1526 1.1 christos
1527 1.1 christos qos_ie = buf + 3;
1528 1.1 christos rem_len = len - 3;
1529 1.1 christos while (rem_len > 2) {
1530 1.1 christos struct dscp_policy_data policy;
1531 1.1 christos int rem_attrs_len, ie_len;
1532 1.1 christos
1533 1.1 christos ie_len = 2 + qos_ie[1];
1534 1.1 christos if (rem_len < ie_len)
1535 1.1 christos break;
1536 1.1 christos
1537 1.1 christos if (rem_len < 6 || qos_ie[0] != WLAN_EID_VENDOR_SPECIFIC ||
1538 1.1 christos qos_ie[1] < 4 ||
1539 1.1 christos WPA_GET_BE32(&qos_ie[2]) != QM_IE_VENDOR_TYPE) {
1540 1.1 christos rem_len -= ie_len;
1541 1.1 christos qos_ie += ie_len;
1542 1.1 christos continue;
1543 1.1 christos }
1544 1.1 christos
1545 1.1 christos os_memset(&policy, 0, sizeof(struct dscp_policy_data));
1546 1.1 christos attr = qos_ie + 6;
1547 1.1 christos rem_attrs_len = qos_ie[1] - 4;
1548 1.1 christos
1549 1.1 christos while (rem_attrs_len > 2) {
1550 1.1 christos u8 attr_id, attr_len;
1551 1.1 christos
1552 1.1 christos attr_id = *attr++;
1553 1.1 christos attr_len = *attr++;
1554 1.1 christos rem_attrs_len -= 2;
1555 1.1 christos if (attr_len > rem_attrs_len)
1556 1.1 christos break;
1557 1.1 christos wpas_fill_dscp_policy(&policy, attr_id, attr_len, attr);
1558 1.1 christos rem_attrs_len -= attr_len;
1559 1.1 christos attr += attr_len;
1560 1.1 christos }
1561 1.1 christos
1562 1.1 christos rem_len -= ie_len;
1563 1.1 christos qos_ie += ie_len;
1564 1.1 christos
1565 1.1 christos if (!policy.dscp_info) {
1566 1.1 christos wpa_printf(MSG_ERROR,
1567 1.1 christos "QM: Received QoS IE without DSCP Policy attribute");
1568 1.1 christos continue;
1569 1.1 christos }
1570 1.1 christos
1571 1.1 christos if (policy.req_type == DSCP_POLICY_REQ_ADD)
1572 1.1 christos wpas_add_dscp_policy(wpa_s, &policy);
1573 1.1 christos else if (policy.req_type == DSCP_POLICY_REQ_REMOVE)
1574 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
1575 1.1 christos "remove policy_id=%u", policy.policy_id);
1576 1.1 christos else
1577 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
1578 1.1 christos "reject policy_id=%u", policy.policy_id);
1579 1.1 christos }
1580 1.1 christos
1581 1.1 christos wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_end");
1582 1.1 christos }
1583 1.1 christos
1584 1.1 christos
1585 1.1 christos int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
1586 1.1 christos struct dscp_resp_data *resp_data)
1587 1.1 christos {
1588 1.1 christos struct wpabuf *buf = NULL;
1589 1.1 christos size_t buf_len;
1590 1.1 christos int ret = -1, i;
1591 1.1 christos u8 resp_control = 0;
1592 1.1 christos
1593 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
1594 1.1 christos wpa_printf(MSG_ERROR,
1595 1.1 christos "QM: Failed to send DSCP response - not connected to AP");
1596 1.1 christos return -1;
1597 1.1 christos }
1598 1.1 christos
1599 1.1 christos if (resp_data->solicited && !wpa_s->dscp_req_dialog_token) {
1600 1.1 christos wpa_printf(MSG_ERROR, "QM: No ongoing DSCP request");
1601 1.1 christos return -1;
1602 1.1 christos }
1603 1.1 christos
1604 1.1 christos if (!wpa_s->connection_dscp) {
1605 1.1 christos wpa_printf(MSG_ERROR,
1606 1.1 christos "QM: Failed to send DSCP response - DSCP capability not enabled for the current association");
1607 1.1 christos return -1;
1608 1.1 christos
1609 1.1 christos }
1610 1.1 christos
1611 1.1 christos buf_len = 1 + /* Category */
1612 1.1 christos 3 + /* OUI */
1613 1.1 christos 1 + /* OUI Type */
1614 1.1 christos 1 + /* OUI Subtype */
1615 1.1 christos 1 + /* Dialog Token */
1616 1.1 christos 1 + /* Response Control */
1617 1.1 christos 1 + /* Count */
1618 1.1 christos 2 * resp_data->num_policies; /* Status list */
1619 1.1 christos buf = wpabuf_alloc(buf_len);
1620 1.1 christos if (!buf) {
1621 1.1 christos wpa_printf(MSG_ERROR,
1622 1.1 christos "QM: Failed to allocate DSCP policy response");
1623 1.1 christos return -1;
1624 1.1 christos }
1625 1.1 christos
1626 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
1627 1.1 christos wpabuf_put_be24(buf, OUI_WFA);
1628 1.1 christos wpabuf_put_u8(buf, QM_ACTION_OUI_TYPE);
1629 1.1 christos wpabuf_put_u8(buf, QM_DSCP_POLICY_RESP);
1630 1.1 christos
1631 1.1 christos wpabuf_put_u8(buf, resp_data->solicited ?
1632 1.1 christos wpa_s->dscp_req_dialog_token : 0);
1633 1.1 christos
1634 1.1 christos if (resp_data->more)
1635 1.1 christos resp_control |= DSCP_POLICY_CTRL_MORE;
1636 1.1 christos if (resp_data->reset)
1637 1.1 christos resp_control |= DSCP_POLICY_CTRL_RESET;
1638 1.1 christos wpabuf_put_u8(buf, resp_control);
1639 1.1 christos
1640 1.1 christos wpabuf_put_u8(buf, resp_data->num_policies);
1641 1.1 christos for (i = 0; i < resp_data->num_policies; i++) {
1642 1.1 christos wpabuf_put_u8(buf, resp_data->policy[i].id);
1643 1.1 christos wpabuf_put_u8(buf, resp_data->policy[i].status);
1644 1.1 christos }
1645 1.1 christos
1646 1.1 christos wpa_hexdump_buf(MSG_MSGDUMP, "DSCP response frame: ", buf);
1647 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
1648 1.1 christos wpa_s->own_addr, wpa_s->bssid,
1649 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0);
1650 1.1 christos if (ret < 0) {
1651 1.1 christos wpa_msg(wpa_s, MSG_INFO, "QM: Failed to send DSCP response");
1652 1.1 christos goto fail;
1653 1.1 christos }
1654 1.1 christos
1655 1.1 christos /*
1656 1.1 christos * Mark DSCP request complete whether response sent is solicited or
1657 1.1 christos * unsolicited
1658 1.1 christos */
1659 1.1 christos wpa_s->dscp_req_dialog_token = 0;
1660 1.1 christos
1661 1.1 christos fail:
1662 1.1 christos wpabuf_free(buf);
1663 1.1 christos return ret;
1664 1.1 christos }
1665 1.1 christos
1666 1.1 christos
1667 1.1 christos int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name,
1668 1.1 christos size_t domain_name_length)
1669 1.1 christos {
1670 1.1 christos struct wpabuf *buf = NULL;
1671 1.1 christos int ret, dscp_query_size;
1672 1.1 christos
1673 1.1 christos if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
1674 1.1 christos return -1;
1675 1.1 christos
1676 1.1 christos if (!wpa_s->connection_dscp) {
1677 1.1 christos wpa_printf(MSG_ERROR,
1678 1.1 christos "QM: Failed to send DSCP query - DSCP capability not enabled for the current association");
1679 1.1 christos return -1;
1680 1.1 christos }
1681 1.1 christos
1682 1.1 christos if (wpa_s->wait_for_dscp_req) {
1683 1.1 christos wpa_printf(MSG_INFO, "QM: Wait until AP sends a DSCP request");
1684 1.1 christos return -1;
1685 1.1 christos }
1686 1.1 christos
1687 1.1 christos #define DOMAIN_NAME_OFFSET (4 /* OUI */ + 1 /* Attr Id */ + 1 /* Attr len */)
1688 1.1 christos
1689 1.1 christos if (domain_name_length > 255 - DOMAIN_NAME_OFFSET) {
1690 1.1 christos wpa_printf(MSG_ERROR, "QM: Too long domain name");
1691 1.1 christos return -1;
1692 1.1 christos }
1693 1.1 christos
1694 1.1 christos dscp_query_size = 1 + /* Category */
1695 1.1 christos 4 + /* OUI Type */
1696 1.1 christos 1 + /* OUI subtype */
1697 1.1 christos 1; /* Dialog Token */
1698 1.1 christos if (domain_name && domain_name_length)
1699 1.1 christos dscp_query_size += 1 + /* Element ID */
1700 1.1 christos 1 + /* IE Length */
1701 1.1 christos DOMAIN_NAME_OFFSET + domain_name_length;
1702 1.1 christos
1703 1.1 christos buf = wpabuf_alloc(dscp_query_size);
1704 1.1 christos if (!buf) {
1705 1.1 christos wpa_printf(MSG_ERROR, "QM: Failed to allocate DSCP query");
1706 1.1 christos return -1;
1707 1.1 christos }
1708 1.1 christos
1709 1.1 christos wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
1710 1.1 christos wpabuf_put_be32(buf, QM_ACTION_VENDOR_TYPE);
1711 1.1 christos wpabuf_put_u8(buf, QM_DSCP_POLICY_QUERY);
1712 1.1 christos wpa_s->dscp_query_dialog_token++;
1713 1.1 christos if (wpa_s->dscp_query_dialog_token == 0)
1714 1.1 christos wpa_s->dscp_query_dialog_token++;
1715 1.1 christos wpabuf_put_u8(buf, wpa_s->dscp_query_dialog_token);
1716 1.1 christos
1717 1.1 christos if (domain_name && domain_name_length) {
1718 1.1 christos /* Domain Name attribute */
1719 1.1 christos wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1720 1.1 christos wpabuf_put_u8(buf, DOMAIN_NAME_OFFSET + domain_name_length);
1721 1.1 christos wpabuf_put_be32(buf, QM_IE_VENDOR_TYPE);
1722 1.1 christos wpabuf_put_u8(buf, QM_ATTR_DOMAIN_NAME);
1723 1.1 christos wpabuf_put_u8(buf, domain_name_length);
1724 1.1 christos wpabuf_put_data(buf, domain_name, domain_name_length);
1725 1.1 christos }
1726 1.1 christos #undef DOMAIN_NAME_OFFSET
1727 1.1 christos
1728 1.1 christos ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
1729 1.1 christos wpa_s->own_addr, wpa_s->bssid,
1730 1.1 christos wpabuf_head(buf), wpabuf_len(buf), 0);
1731 1.1 christos if (ret < 0) {
1732 1.1 christos wpa_dbg(wpa_s, MSG_ERROR, "QM: Failed to send DSCP query");
1733 1.1 christos wpa_s->dscp_query_dialog_token--;
1734 1.1 christos }
1735 1.1 christos
1736 1.1 christos wpabuf_free(buf);
1737 1.1 christos return ret;
1738 1.1 christos }
1739