Coverage Report

Created: 2025-11-03 06:51

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