Coverage Report

Created: 2026-04-12 06:28

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