Coverage Report

Created: 2025-04-24 06:18

/src/hostap/src/common/ieee802_11_common.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * IEEE 802.11 Common routines
3
 * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "includes.h"
10
11
#include "common.h"
12
#include "defs.h"
13
#include "wpa_common.h"
14
#include "drivers/driver.h"
15
#include "qca-vendor.h"
16
#include "ieee802_11_defs.h"
17
#include "ieee802_11_common.h"
18
19
20
static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
21
              struct ieee802_11_elems *elems,
22
              int show_errors)
23
19.9k
{
24
19.9k
  unsigned int oui;
25
26
  /* first 3 bytes in vendor specific information element are the IEEE
27
   * OUI of the vendor. The following byte is used a vendor specific
28
   * sub-type. */
29
19.9k
  if (elen < 4) {
30
9.04k
    if (show_errors) {
31
0
      wpa_printf(MSG_MSGDUMP, "short vendor specific "
32
0
           "information element ignored (len=%lu)",
33
0
           (unsigned long) elen);
34
0
    }
35
9.04k
    return -1;
36
9.04k
  }
37
38
10.8k
  oui = WPA_GET_BE24(pos);
39
10.8k
  switch (oui) {
40
2.34k
  case OUI_MICROSOFT:
41
    /* Microsoft/Wi-Fi information elements are further typed and
42
     * subtyped */
43
2.34k
    switch (pos[3]) {
44
205
    case 1:
45
      /* Microsoft OUI (00:50:F2) with OUI Type 1:
46
       * real WPA information element */
47
205
      elems->wpa_ie = pos;
48
205
      elems->wpa_ie_len = elen;
49
205
      break;
50
1.43k
    case WMM_OUI_TYPE:
51
      /* WMM information element */
52
1.43k
      if (elen < 5) {
53
448
        wpa_printf(MSG_MSGDUMP, "short WMM "
54
448
             "information element ignored "
55
448
             "(len=%lu)",
56
448
             (unsigned long) elen);
57
448
        return -1;
58
448
      }
59
982
      switch (pos[4]) {
60
206
      case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
61
425
      case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
62
        /*
63
         * Share same pointer since only one of these
64
         * is used and they start with same data.
65
         * Length field can be used to distinguish the
66
         * IEs.
67
         */
68
425
        elems->wmm = pos;
69
425
        elems->wmm_len = elen;
70
425
        break;
71
281
      case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
72
281
        elems->wmm_tspec = pos;
73
281
        elems->wmm_tspec_len = elen;
74
281
        break;
75
276
      default:
76
276
        wpa_printf(MSG_EXCESSIVE, "unknown WMM "
77
276
             "information element ignored "
78
276
             "(subtype=%d len=%lu)",
79
276
             pos[4], (unsigned long) elen);
80
276
        return -1;
81
982
      }
82
706
      break;
83
706
    case 4:
84
      /* Wi-Fi Protected Setup (WPS) IE */
85
400
      elems->wps_ie = pos;
86
400
      elems->wps_ie_len = elen;
87
400
      break;
88
305
    default:
89
305
      wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
90
305
           "information element ignored "
91
305
           "(type=%d len=%lu)",
92
305
           pos[3], (unsigned long) elen);
93
305
      return -1;
94
2.34k
    }
95
1.31k
    break;
96
97
4.90k
  case OUI_WFA:
98
4.90k
    switch (pos[3]) {
99
197
    case P2P_OUI_TYPE:
100
      /* Wi-Fi Alliance - P2P IE */
101
197
      elems->p2p = pos;
102
197
      elems->p2p_len = elen;
103
197
      break;
104
263
    case WFD_OUI_TYPE:
105
      /* Wi-Fi Alliance - WFD IE */
106
263
      elems->wfd = pos;
107
263
      elems->wfd_len = elen;
108
263
      break;
109
271
    case HS20_INDICATION_OUI_TYPE:
110
      /* Hotspot 2.0 */
111
271
      elems->hs20 = pos;
112
271
      elems->hs20_len = elen;
113
271
      break;
114
496
    case MBO_OUI_TYPE:
115
      /* MBO-OCE */
116
496
      elems->mbo = pos;
117
496
      elems->mbo_len = elen;
118
496
      break;
119
229
    case HS20_ROAMING_CONS_SEL_OUI_TYPE:
120
      /* Hotspot 2.0 Roaming Consortium Selection */
121
229
      elems->roaming_cons_sel = pos;
122
229
      elems->roaming_cons_sel_len = elen;
123
229
      break;
124
244
    case MULTI_AP_OUI_TYPE:
125
244
      elems->multi_ap = pos;
126
244
      elems->multi_ap_len = elen;
127
244
      break;
128
202
    case OWE_OUI_TYPE:
129
      /* OWE Transition Mode element */
130
202
      break;
131
402
    case DPP_CC_OUI_TYPE:
132
      /* DPP Configurator Connectivity element */
133
402
      break;
134
322
    case SAE_PK_OUI_TYPE:
135
322
      elems->sae_pk = pos + 4;
136
322
      elems->sae_pk_len = elen - 4;
137
322
      break;
138
194
    case WFA_CAPA_OUI_TYPE:
139
194
      elems->wfa_capab = pos + 4;
140
194
      elems->wfa_capab_len = elen - 4;
141
194
      break;
142
201
    case WFA_RSNE_OVERRIDE_OUI_TYPE:
143
201
      elems->rsne_override = pos;
144
201
      elems->rsne_override_len = elen;
145
201
      break;
146
219
    case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
147
219
      elems->rsne_override_2 = pos;
148
219
      elems->rsne_override_2_len = elen;
149
219
      break;
150
274
    case WFA_RSNXE_OVERRIDE_OUI_TYPE:
151
274
      elems->rsnxe_override = pos;
152
274
      elems->rsnxe_override_len = elen;
153
274
      break;
154
515
    case WFA_RSN_SELECTION_OUI_TYPE:
155
515
      if (elen < 4 + 1) {
156
311
        wpa_printf(MSG_DEBUG,
157
311
             "Too short RSN Selection element ignored");
158
311
        return -1;
159
311
      }
160
204
      elems->rsn_selection = pos + 4;
161
204
      elems->rsn_selection_len = elen - 4;
162
204
      break;
163
198
    case P2P2_OUI_TYPE:
164
      /* Wi-Fi Alliance - P2P2 IE */
165
198
      elems->p2p2_ie = pos;
166
198
      elems->p2p2_ie_len = elen;
167
198
      break;
168
679
    default:
169
679
      wpa_printf(MSG_MSGDUMP, "Unknown WFA "
170
679
           "information element ignored "
171
679
           "(type=%d len=%lu)",
172
679
           pos[3], (unsigned long) elen);
173
679
      return -1;
174
4.90k
    }
175
3.91k
    break;
176
177
3.91k
  case OUI_BROADCOM:
178
1.77k
    switch (pos[3]) {
179
292
    case VENDOR_HT_CAPAB_OUI_TYPE:
180
292
      elems->vendor_ht_cap = pos;
181
292
      elems->vendor_ht_cap_len = elen;
182
292
      break;
183
1.16k
    case VENDOR_VHT_TYPE:
184
1.16k
      if (elen > 4 &&
185
1.16k
          (pos[4] == VENDOR_VHT_SUBTYPE ||
186
938
           pos[4] == VENDOR_VHT_SUBTYPE2)) {
187
611
        elems->vendor_vht = pos;
188
611
        elems->vendor_vht_len = elen;
189
611
      } else
190
550
        return -1;
191
611
      break;
192
611
    default:
193
321
      wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
194
321
           "information element ignored "
195
321
           "(type=%d len=%lu)",
196
321
           pos[3], (unsigned long) elen);
197
321
      return -1;
198
1.77k
    }
199
903
    break;
200
201
903
  case OUI_QCA:
202
486
    switch (pos[3]) {
203
204
    case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
204
204
      elems->pref_freq_list = pos;
205
204
      elems->pref_freq_list_len = elen;
206
204
      break;
207
282
    default:
208
282
      wpa_printf(MSG_EXCESSIVE,
209
282
           "Unknown QCA information element ignored (type=%d len=%lu)",
210
282
           pos[3], (unsigned long) elen);
211
282
      return -1;
212
486
    }
213
204
    break;
214
215
1.38k
  default:
216
1.38k
    wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
217
1.38k
         "information element ignored (vendor OUI "
218
1.38k
         "%02x:%02x:%02x len=%lu)",
219
1.38k
         pos[0], pos[1], pos[2], (unsigned long) elen);
220
1.38k
    return -1;
221
10.8k
  }
222
223
6.33k
  return 0;
224
10.8k
}
225
226
227
static int ieee802_11_parse_mle(const u8 *pos, size_t elen, size_t **total_len,
228
        struct ieee802_11_elems *elems,
229
        int show_errors)
230
3.10k
{
231
3.10k
  u8 mle_type = pos[0] & MULTI_LINK_CONTROL_TYPE_MASK;
232
233
3.10k
  switch (mle_type) {
234
461
  case MULTI_LINK_CONTROL_TYPE_BASIC:
235
461
    elems->basic_mle = pos;
236
461
    elems->basic_mle_len = elen;
237
461
    *total_len = &elems->basic_mle_len;
238
461
    break;
239
1.11k
  case MULTI_LINK_CONTROL_TYPE_PROBE_REQ:
240
1.11k
    elems->probe_req_mle = pos;
241
1.11k
    elems->probe_req_mle_len = elen;
242
1.11k
    *total_len = &elems->probe_req_mle_len;
243
1.11k
    break;
244
431
  case MULTI_LINK_CONTROL_TYPE_RECONF:
245
431
    elems->reconf_mle = pos;
246
431
    elems->reconf_mle_len = elen;
247
431
    *total_len = &elems->reconf_mle_len;
248
431
    break;
249
429
  case MULTI_LINK_CONTROL_TYPE_TDLS:
250
429
    elems->tdls_mle = pos;
251
429
    elems->tdls_mle_len = elen;
252
429
    *total_len = &elems->tdls_mle_len;
253
429
    break;
254
261
  case MULTI_LINK_CONTROL_TYPE_PRIOR_ACCESS:
255
261
    elems->prior_access_mle = pos;
256
261
    elems->prior_access_mle_len = elen;
257
261
    *total_len = &elems->prior_access_mle_len;
258
261
    break;
259
405
  default:
260
405
    if (show_errors) {
261
0
      wpa_printf(MSG_MSGDUMP,
262
0
           "Unknown Multi-Link element type %u",
263
0
           mle_type);
264
0
    }
265
405
    return -1;
266
3.10k
  }
267
268
2.69k
  return 0;
269
3.10k
}
270
271
272
static size_t ieee802_11_fragments_length(struct ieee802_11_elems *elems,
273
            const u8 *start, size_t len)
274
961
{
275
961
  const struct element *elem;
276
961
  size_t frags_len = 0;
277
278
32.1k
  for_each_element(elem, start, len) {
279
32.1k
    if (elem->id != WLAN_EID_FRAGMENT)
280
509
      break;
281
282
31.6k
    frags_len += elem->datalen + 2;
283
31.6k
    elems->num_frag_elems++;
284
31.6k
  }
285
286
961
  return frags_len;
287
961
}
288
289
290
static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
291
              struct ieee802_11_elems *elems,
292
              const u8 *start, size_t len,
293
              int show_errors)
294
28.6k
{
295
28.6k
  u8 ext_id;
296
28.6k
  size_t *total_len = NULL;
297
298
28.6k
  if (elen < 1) {
299
12.5k
    if (show_errors) {
300
0
      wpa_printf(MSG_MSGDUMP,
301
0
           "short information element (Ext)");
302
0
    }
303
12.5k
    return -1;
304
12.5k
  }
305
306
16.0k
  ext_id = *pos++;
307
16.0k
  elen--;
308
309
16.0k
  switch (ext_id) {
310
756
  case WLAN_EID_EXT_ASSOC_DELAY_INFO:
311
756
    if (elen != 1)
312
288
      break;
313
468
    elems->assoc_delay_info = pos;
314
468
    break;
315
611
  case WLAN_EID_EXT_FILS_REQ_PARAMS:
316
611
    if (elen < 3)
317
337
      break;
318
274
    elems->fils_req_params = pos;
319
274
    elems->fils_req_params_len = elen;
320
274
    break;
321
536
  case WLAN_EID_EXT_FILS_KEY_CONFIRM:
322
536
    elems->fils_key_confirm = pos;
323
536
    elems->fils_key_confirm_len = elen;
324
536
    break;
325
849
  case WLAN_EID_EXT_FILS_SESSION:
326
849
    if (elen != FILS_SESSION_LEN)
327
651
      break;
328
198
    elems->fils_session = pos;
329
198
    break;
330
925
  case WLAN_EID_EXT_FILS_HLP_CONTAINER:
331
925
    if (elen < 2 * ETH_ALEN)
332
289
      break;
333
636
    elems->fils_hlp = pos;
334
636
    elems->fils_hlp_len = elen;
335
636
    total_len = &elems->fils_hlp_len;
336
636
    break;
337
621
  case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
338
621
    if (elen < 1)
339
406
      break;
340
215
    elems->fils_ip_addr_assign = pos;
341
215
    elems->fils_ip_addr_assign_len = elen;
342
215
    break;
343
551
  case WLAN_EID_EXT_KEY_DELIVERY:
344
551
    if (elen < WPA_KEY_RSC_LEN)
345
285
      break;
346
266
    elems->key_delivery = pos;
347
266
    elems->key_delivery_len = elen;
348
266
    break;
349
235
  case WLAN_EID_EXT_WRAPPED_DATA:
350
235
    elems->wrapped_data = pos;
351
235
    elems->wrapped_data_len = elen;
352
235
    total_len = &elems->wrapped_data_len;
353
235
    break;
354
935
  case WLAN_EID_EXT_FILS_PUBLIC_KEY:
355
935
    if (elen < 1)
356
582
      break;
357
353
    elems->fils_pk = pos;
358
353
    elems->fils_pk_len = elen;
359
353
    break;
360
556
  case WLAN_EID_EXT_FILS_NONCE:
361
556
    if (elen != FILS_NONCE_LEN)
362
357
      break;
363
199
    elems->fils_nonce = pos;
364
199
    break;
365
627
  case WLAN_EID_EXT_OWE_DH_PARAM:
366
627
    if (elen < 2)
367
288
      break;
368
339
    elems->owe_dh = pos;
369
339
    elems->owe_dh_len = elen;
370
339
    break;
371
437
  case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
372
437
    elems->password_id = pos;
373
437
    elems->password_id_len = elen;
374
437
    break;
375
224
  case WLAN_EID_EXT_HE_CAPABILITIES:
376
224
    elems->he_capabilities = pos;
377
224
    elems->he_capabilities_len = elen;
378
224
    break;
379
228
  case WLAN_EID_EXT_HE_OPERATION:
380
228
    elems->he_operation = pos;
381
228
    elems->he_operation_len = elen;
382
228
    break;
383
718
  case WLAN_EID_EXT_OCV_OCI:
384
718
    elems->oci = pos;
385
718
    elems->oci_len = elen;
386
718
    break;
387
250
  case WLAN_EID_EXT_SHORT_SSID_LIST:
388
250
    elems->short_ssid_list = pos;
389
250
    elems->short_ssid_list_len = elen;
390
250
    break;
391
474
  case WLAN_EID_EXT_HE_6GHZ_BAND_CAP:
392
474
    if (elen < sizeof(struct ieee80211_he_6ghz_band_cap))
393
248
      break;
394
226
    elems->he_6ghz_band_cap = pos;
395
226
    break;
396
307
  case WLAN_EID_EXT_PASN_PARAMS:
397
307
    elems->pasn_params = pos;
398
307
    elems->pasn_params_len = elen;
399
307
    break;
400
343
  case WLAN_EID_EXT_EHT_CAPABILITIES:
401
343
    elems->eht_capabilities = pos;
402
343
    elems->eht_capabilities_len = elen;
403
343
    break;
404
209
  case WLAN_EID_EXT_EHT_OPERATION:
405
209
    elems->eht_operation = pos;
406
209
    elems->eht_operation_len = elen;
407
209
    break;
408
3.41k
  case WLAN_EID_EXT_MULTI_LINK:
409
3.41k
    if (elen < 2)
410
316
      break;
411
3.10k
    if (ieee802_11_parse_mle(pos, elen, &total_len, elems,
412
3.10k
           show_errors))
413
405
      return -1;
414
2.69k
    break;
415
2.69k
  case WLAN_EID_EXT_KNOWN_BSSID:
416
431
    elems->mbssid_known_bss = pos;
417
431
    elems->mbssid_known_bss_len = elen;
418
431
    break;
419
194
  case WLAN_EID_EXT_PASN_ENCRYPTED_DATA:
420
194
    elems->pasn_encrypted_data = pos;
421
194
    elems->pasn_encrypted_data_len = elen;
422
194
    break;
423
1.64k
  default:
424
1.64k
    if (show_errors) {
425
0
      wpa_printf(MSG_MSGDUMP,
426
0
           "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
427
0
           ext_id, (unsigned int) elen);
428
0
    }
429
1.64k
    return -1;
430
16.0k
  }
431
432
14.0k
  if (elen == 254 && total_len)
433
465
    *total_len += ieee802_11_fragments_length(
434
465
      elems, pos + elen, (start + len) - (pos + elen));
435
436
14.0k
  return 0;
437
16.0k
}
438
439
440
static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len,
441
           struct ieee802_11_elems *elems,
442
           int show_errors)
443
12.3k
{
444
12.3k
  const struct element *elem;
445
12.3k
  int unknown = 0;
446
447
12.3k
  if (!start)
448
0
    return ParseOK;
449
450
177k
  for_each_element(elem, start, len) {
451
177k
    u8 id = elem->id, elen = elem->datalen;
452
177k
    const u8 *pos = elem->data;
453
177k
    size_t *total_len = NULL;
454
455
177k
    if (id == WLAN_EID_FRAGMENT && elems->num_frag_elems > 0) {
456
31.6k
      elems->num_frag_elems--;
457
31.6k
      continue;
458
31.6k
    }
459
145k
    elems->num_frag_elems = 0;
460
461
145k
    switch (id) {
462
51.9k
    case WLAN_EID_SSID:
463
51.9k
      if (elen > SSID_MAX_LEN) {
464
3.32k
        wpa_printf(MSG_DEBUG,
465
3.32k
             "Ignored too long SSID element (elen=%u)",
466
3.32k
             elen);
467
3.32k
        break;
468
3.32k
      }
469
48.6k
      if (elems->ssid) {
470
47.0k
        wpa_printf(MSG_MSGDUMP,
471
47.0k
             "Ignored duplicated SSID element");
472
47.0k
        break;
473
47.0k
      }
474
1.59k
      elems->ssid = pos;
475
1.59k
      elems->ssid_len = elen;
476
1.59k
      break;
477
4.21k
    case WLAN_EID_SUPP_RATES:
478
4.21k
      elems->supp_rates = pos;
479
4.21k
      elems->supp_rates_len = elen;
480
4.21k
      break;
481
2.57k
    case WLAN_EID_DS_PARAMS:
482
2.57k
      if (elen < 1)
483
473
        break;
484
2.09k
      elems->ds_params = pos;
485
2.09k
      break;
486
1.12k
    case WLAN_EID_CF_PARAMS:
487
1.69k
    case WLAN_EID_TIM:
488
1.69k
      break;
489
571
    case WLAN_EID_CHALLENGE:
490
571
      elems->challenge = pos;
491
571
      elems->challenge_len = elen;
492
571
      break;
493
1.79k
    case WLAN_EID_ERP_INFO:
494
1.79k
      if (elen < 1)
495
846
        break;
496
945
      elems->erp_info = pos;
497
945
      break;
498
1.18k
    case WLAN_EID_EXT_SUPP_RATES:
499
1.18k
      elems->ext_supp_rates = pos;
500
1.18k
      elems->ext_supp_rates_len = elen;
501
1.18k
      break;
502
19.9k
    case WLAN_EID_VENDOR_SPECIFIC:
503
19.9k
      if (ieee802_11_parse_vendor_specific(pos, elen,
504
19.9k
                   elems,
505
19.9k
                   show_errors))
506
13.5k
        unknown++;
507
19.9k
      break;
508
491
    case WLAN_EID_RSN:
509
491
      elems->rsn_ie = pos;
510
491
      elems->rsn_ie_len = elen;
511
491
      break;
512
277
    case WLAN_EID_RSNX:
513
277
      elems->rsnxe = pos;
514
277
      elems->rsnxe_len = elen;
515
277
      break;
516
686
    case WLAN_EID_PWR_CAPABILITY:
517
686
      if (elen < 2)
518
378
        break;
519
308
      elems->power_capab = pos;
520
308
      elems->power_capab_len = elen;
521
308
      break;
522
435
    case WLAN_EID_SUPPORTED_CHANNELS:
523
435
      elems->supp_channels = pos;
524
435
      elems->supp_channels_len = elen;
525
435
      break;
526
1.05k
    case WLAN_EID_MOBILITY_DOMAIN:
527
1.05k
      if (elen < sizeof(struct rsn_mdie))
528
581
        break;
529
469
      elems->mdie = pos;
530
469
      elems->mdie_len = elen;
531
469
      break;
532
1.34k
    case WLAN_EID_FAST_BSS_TRANSITION:
533
1.34k
      if (elen < sizeof(struct rsn_ftie))
534
655
        break;
535
694
      elems->ftie = pos;
536
694
      elems->ftie_len = elen;
537
694
      elems->fte_defrag_len = elen;
538
694
      total_len = &elems->fte_defrag_len;
539
694
      break;
540
617
    case WLAN_EID_TIMEOUT_INTERVAL:
541
617
      if (elen != 5)
542
346
        break;
543
271
      elems->timeout_int = pos;
544
271
      break;
545
2.56k
    case WLAN_EID_HT_CAP:
546
2.56k
      if (elen < sizeof(struct ieee80211_ht_capabilities))
547
2.05k
        break;
548
518
      elems->ht_capabilities = pos;
549
518
      break;
550
854
    case WLAN_EID_HT_OPERATION:
551
854
      if (elen < sizeof(struct ieee80211_ht_operation))
552
357
        break;
553
497
      elems->ht_operation = pos;
554
497
      break;
555
313
    case WLAN_EID_MESH_CONFIG:
556
313
      elems->mesh_config = pos;
557
313
      elems->mesh_config_len = elen;
558
313
      break;
559
770
    case WLAN_EID_MESH_ID:
560
770
      elems->mesh_id = pos;
561
770
      elems->mesh_id_len = elen;
562
770
      break;
563
646
    case WLAN_EID_PEER_MGMT:
564
646
      elems->peer_mgmt = pos;
565
646
      elems->peer_mgmt_len = elen;
566
646
      break;
567
1.09k
    case WLAN_EID_VHT_CAP:
568
1.09k
      if (elen < sizeof(struct ieee80211_vht_capabilities))
569
879
        break;
570
216
      elems->vht_capabilities = pos;
571
216
      break;
572
601
    case WLAN_EID_VHT_OPERATION:
573
601
      if (elen < sizeof(struct ieee80211_vht_operation))
574
332
        break;
575
269
      elems->vht_operation = pos;
576
269
      break;
577
612
    case WLAN_EID_OPERATING_MODE_NOTIFICATION:
578
612
      if (elen != 1)
579
349
        break;
580
263
      elems->opmode_notif = pos;
581
263
      break;
582
617
    case WLAN_EID_LINK_ID:
583
617
      if (elen < 18)
584
352
        break;
585
265
      elems->link_id = pos;
586
265
      break;
587
588
    case WLAN_EID_INTERWORKING:
588
588
      elems->interworking = pos;
589
588
      elems->interworking_len = elen;
590
588
      break;
591
488
    case WLAN_EID_QOS_MAP_SET:
592
488
      if (elen < 16)
593
253
        break;
594
235
      elems->qos_map_set = pos;
595
235
      elems->qos_map_set_len = elen;
596
235
      break;
597
535
    case WLAN_EID_EXT_CAPAB:
598
535
      elems->ext_capab = pos;
599
535
      elems->ext_capab_len = elen;
600
535
      break;
601
640
    case WLAN_EID_BSS_MAX_IDLE_PERIOD:
602
640
      if (elen < 3)
603
379
        break;
604
261
      elems->bss_max_idle_period = pos;
605
261
      break;
606
414
    case WLAN_EID_SSID_LIST:
607
414
      elems->ssid_list = pos;
608
414
      elems->ssid_list_len = elen;
609
414
      break;
610
394
    case WLAN_EID_AMPE:
611
394
      elems->ampe = pos;
612
394
      elems->ampe_len = elen;
613
394
      break;
614
296
    case WLAN_EID_MIC:
615
296
      elems->mic = pos;
616
296
      elems->mic_len = elen;
617
      /* after mic everything is encrypted, so stop. */
618
296
      goto done;
619
508
    case WLAN_EID_MULTI_BAND:
620
508
      if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
621
234
        wpa_printf(MSG_MSGDUMP,
622
234
             "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
623
234
             id, elen);
624
234
        break;
625
234
      }
626
627
274
      elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
628
274
      elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
629
274
      elems->mb_ies.nof_ies++;
630
274
      break;
631
505
    case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
632
505
      elems->supp_op_classes = pos;
633
505
      elems->supp_op_classes_len = elen;
634
505
      break;
635
297
    case WLAN_EID_RRM_ENABLED_CAPABILITIES:
636
297
      elems->rrm_enabled = pos;
637
297
      elems->rrm_enabled_len = elen;
638
297
      break;
639
733
    case WLAN_EID_MULTIPLE_BSSID:
640
733
      if (elen < 1)
641
353
        break;
642
380
      elems->mbssid = pos;
643
380
      elems->mbssid_len = elen;
644
380
      break;
645
323
    case WLAN_EID_CAG_NUMBER:
646
323
      elems->cag_number = pos;
647
323
      elems->cag_number_len = elen;
648
323
      break;
649
708
    case WLAN_EID_AP_CSN:
650
708
      if (elen < 1)
651
368
        break;
652
340
      elems->ap_csn = pos;
653
340
      break;
654
443
    case WLAN_EID_FILS_INDICATION:
655
443
      if (elen < 2)
656
203
        break;
657
240
      elems->fils_indic = pos;
658
240
      elems->fils_indic_len = elen;
659
240
      break;
660
523
    case WLAN_EID_DILS:
661
523
      if (elen < 2)
662
271
        break;
663
252
      elems->dils = pos;
664
252
      elems->dils_len = elen;
665
252
      break;
666
471
    case WLAN_EID_S1G_CAPABILITIES:
667
471
      if (elen < 15)
668
266
        break;
669
205
      elems->s1g_capab = pos;
670
205
      break;
671
2.36k
    case WLAN_EID_FRAGMENT:
672
2.36k
      wpa_printf(MSG_MSGDUMP,
673
2.36k
           "Fragment without a valid last element - skip");
674
675
2.36k
      break;
676
28.6k
    case WLAN_EID_EXTENSION:
677
28.6k
      if (ieee802_11_parse_extension(pos, elen, elems, start,
678
28.6k
                   len, show_errors))
679
14.6k
        unknown++;
680
28.6k
      break;
681
9.93k
    default:
682
9.93k
      unknown++;
683
9.93k
      if (!show_errors)
684
9.93k
        break;
685
0
      wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
686
0
           "ignored unknown element (id=%d elen=%d)",
687
0
           id, elen);
688
0
      break;
689
145k
    }
690
691
145k
    if (elen == 255 && total_len)
692
496
      *total_len += ieee802_11_fragments_length(
693
496
        elems, pos + elen,
694
496
        (start + len) - (pos + elen));
695
696
145k
  }
697
698
12.0k
  if (!for_each_element_completed(elem, start, len)) {
699
1.14k
    if (show_errors) {
700
0
      wpa_printf(MSG_DEBUG,
701
0
           "IEEE 802.11 element parse failed @%d",
702
0
           (int) (start + len - (const u8 *) elem));
703
0
      wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
704
0
    }
705
1.14k
    return ParseFailed;
706
1.14k
  }
707
708
11.2k
done:
709
11.2k
  return unknown ? ParseUnknown : ParseOK;
710
12.0k
}
711
712
713
/**
714
 * ieee802_11_parse_elems - Parse information elements in management frames
715
 * @start: Pointer to the start of IEs
716
 * @len: Length of IE buffer in octets
717
 * @elems: Data structure for parsed elements
718
 * @show_errors: Whether to show parsing errors in debug log
719
 * Returns: Parsing result
720
 */
721
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
722
        struct ieee802_11_elems *elems,
723
        int show_errors)
724
12.3k
{
725
12.3k
  os_memset(elems, 0, sizeof(*elems));
726
727
12.3k
  return __ieee802_11_parse_elems(start, len, elems, show_errors);
728
12.3k
}
729
730
731
/**
732
 * ieee802_11_elems_clear_ids - Clear the data for the given element IDs
733
 * @ids: Array of element IDs for which data should be cleared.
734
 * @num: The number of entries in the array
735
 */
736
void ieee802_11_elems_clear_ids(struct ieee802_11_elems *elems,
737
        const u8 *ids, size_t num)
738
0
{
739
0
  size_t i;
740
741
0
  for (i = 0; i < num; i++) {
742
0
    switch (ids[i]) {
743
0
    case WLAN_EID_SSID:
744
0
      elems->ssid = NULL;
745
0
      elems->ssid_len = 0;
746
0
      break;
747
0
    case WLAN_EID_SUPP_RATES:
748
0
      elems->supp_rates = NULL;
749
0
      elems->supp_rates_len = 0;
750
0
      break;
751
0
    case WLAN_EID_DS_PARAMS:
752
0
      elems->ds_params = NULL;
753
0
      break;
754
0
    case WLAN_EID_CHALLENGE:
755
0
      elems->challenge = NULL;
756
0
      elems->challenge_len = 0;
757
0
      break;
758
0
    case WLAN_EID_ERP_INFO:
759
0
      elems->erp_info = NULL;
760
0
      break;
761
0
    case WLAN_EID_EXT_SUPP_RATES:
762
0
      elems->ext_supp_rates = NULL;
763
0
      elems->ext_supp_rates_len = 0;
764
0
      break;
765
0
    case WLAN_EID_RSN:
766
0
      elems->rsn_ie = NULL;
767
0
      elems->rsn_ie_len = 0;
768
0
      break;
769
0
    case WLAN_EID_RSNX:
770
0
      elems->rsnxe = NULL;
771
0
      elems->rsnxe_len = 0;
772
0
      break;
773
0
    case WLAN_EID_PWR_CAPABILITY:
774
0
      elems->power_capab = NULL;
775
0
      elems->power_capab_len = 0;
776
0
      break;
777
0
    case WLAN_EID_SUPPORTED_CHANNELS:
778
0
      elems->supp_channels = NULL;
779
0
      elems->supp_channels_len = 0;
780
0
      break;
781
0
    case WLAN_EID_MOBILITY_DOMAIN:
782
0
      elems->mdie = NULL;
783
0
      elems->mdie_len = 0;
784
0
      break;
785
0
    case WLAN_EID_FAST_BSS_TRANSITION:
786
0
      elems->ftie = NULL;
787
0
      elems->ftie_len = 0;
788
0
      break;
789
0
    case WLAN_EID_TIMEOUT_INTERVAL:
790
0
      elems->timeout_int = NULL;
791
0
      break;
792
0
    case WLAN_EID_HT_CAP:
793
0
      elems->ht_capabilities = NULL;
794
0
      break;
795
0
    case WLAN_EID_HT_OPERATION:
796
0
      elems->ht_operation = NULL;
797
0
      break;
798
0
    case WLAN_EID_MESH_CONFIG:
799
0
      elems->mesh_config = NULL;
800
0
      elems->mesh_config_len = 0;
801
0
      break;
802
0
    case WLAN_EID_MESH_ID:
803
0
      elems->mesh_id = NULL;
804
0
      elems->mesh_id_len = 0;
805
0
      break;
806
0
    case WLAN_EID_PEER_MGMT:
807
0
      elems->peer_mgmt = NULL;
808
0
      elems->peer_mgmt_len = 0;
809
0
      break;
810
0
    case WLAN_EID_VHT_CAP:
811
0
      elems->vht_capabilities = NULL;
812
0
      break;
813
0
    case WLAN_EID_VHT_OPERATION:
814
0
      elems->vht_operation = NULL;
815
0
      break;
816
0
    case WLAN_EID_OPERATING_MODE_NOTIFICATION:
817
0
      elems->opmode_notif = NULL;
818
0
      break;
819
0
    case WLAN_EID_LINK_ID:
820
0
      elems->link_id = NULL;
821
0
      break;
822
0
    case WLAN_EID_INTERWORKING:
823
0
      elems->interworking = NULL;
824
0
      elems->interworking_len = 0;
825
0
      break;
826
0
    case WLAN_EID_QOS_MAP_SET:
827
0
      elems->qos_map_set = NULL;
828
0
      elems->qos_map_set_len = 0;
829
0
      break;
830
0
    case WLAN_EID_EXT_CAPAB:
831
0
      elems->ext_capab = NULL;
832
0
      elems->ext_capab_len = 0;
833
0
      break;
834
0
    case WLAN_EID_BSS_MAX_IDLE_PERIOD:
835
0
      elems->bss_max_idle_period = NULL;
836
0
      break;
837
0
    case WLAN_EID_SSID_LIST:
838
0
      elems->ssid_list = NULL;
839
0
      elems->ssid_list_len = 0;
840
0
      break;
841
0
    case WLAN_EID_AMPE:
842
0
      elems->ampe = NULL;
843
0
      elems->ampe_len = 0;
844
0
      break;
845
0
    case WLAN_EID_MIC:
846
0
      elems->mic = NULL;
847
0
      elems->mic_len = 0;
848
0
      break;
849
0
    case WLAN_EID_MULTI_BAND:
850
0
      os_memset(&elems->mb_ies, 0, sizeof(elems->mb_ies));
851
0
      elems->mb_ies.nof_ies = 0;
852
0
      break;
853
0
    case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
854
0
      elems->supp_op_classes = NULL;
855
0
      elems->supp_op_classes_len = 0;
856
0
      break;
857
0
    case WLAN_EID_RRM_ENABLED_CAPABILITIES:
858
0
      elems->rrm_enabled = NULL;
859
0
      elems->rrm_enabled_len = 0;
860
0
      break;
861
0
    case WLAN_EID_CAG_NUMBER:
862
0
      elems->cag_number = NULL;
863
0
      elems->cag_number_len = 0;
864
0
      break;
865
0
    case WLAN_EID_AP_CSN:
866
0
      elems->ap_csn = NULL;
867
0
      break;
868
0
    case WLAN_EID_FILS_INDICATION:
869
0
      elems->fils_indic = NULL;
870
0
      elems->fils_indic_len = 0;
871
0
      break;
872
0
    case WLAN_EID_DILS:
873
0
      elems->dils = NULL;
874
0
      elems->dils_len = 0;
875
0
      break;
876
0
    case WLAN_EID_S1G_CAPABILITIES:
877
0
      elems->s1g_capab = NULL;
878
0
      break;
879
0
    }
880
0
  }
881
0
}
882
883
884
/**
885
 * ieee802_11_elems_clear_ext_ids - Clear the data for the given element
886
 * extension IDs
887
 * @ids: Array of element extension IDs for which data should be cleared.
888
 * @num: The number of entries in the array
889
 */
890
void ieee802_11_elems_clear_ext_ids(struct ieee802_11_elems *elems,
891
            const u8 *ids, size_t num)
892
0
{
893
0
  size_t i;
894
895
0
  for (i = 0; i < num; i++) {
896
0
    switch (ids[i]) {
897
0
    case WLAN_EID_EXT_ASSOC_DELAY_INFO:
898
0
      elems->assoc_delay_info = NULL;
899
0
      break;
900
0
    case WLAN_EID_EXT_FILS_REQ_PARAMS:
901
0
      elems->fils_req_params = NULL;
902
0
      elems->fils_req_params_len = 0;
903
0
      break;
904
0
    case WLAN_EID_EXT_FILS_KEY_CONFIRM:
905
0
      elems->fils_key_confirm = NULL;
906
0
      elems->fils_key_confirm_len = 0;
907
0
      break;
908
0
    case WLAN_EID_EXT_FILS_SESSION:
909
0
      elems->fils_session = NULL;
910
0
      break;
911
0
    case WLAN_EID_EXT_FILS_HLP_CONTAINER:
912
0
      elems->fils_hlp = NULL;
913
0
      elems->fils_hlp_len = 0;
914
0
      break;
915
0
    case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
916
0
      elems->fils_ip_addr_assign = NULL;
917
0
      elems->fils_ip_addr_assign_len = 0;
918
0
      break;
919
0
    case WLAN_EID_EXT_KEY_DELIVERY:
920
0
      elems->key_delivery = NULL;
921
0
      elems->key_delivery_len = 0;
922
0
      break;
923
0
    case WLAN_EID_EXT_WRAPPED_DATA:
924
0
      elems->wrapped_data = NULL;
925
0
      elems->wrapped_data_len = 0;
926
0
      break;
927
0
    case WLAN_EID_EXT_FILS_PUBLIC_KEY:
928
0
      elems->fils_pk = NULL;
929
0
      elems->fils_pk_len = 0;
930
0
      break;
931
0
    case WLAN_EID_EXT_FILS_NONCE:
932
0
      elems->fils_nonce = NULL;
933
0
      break;
934
0
    case WLAN_EID_EXT_OWE_DH_PARAM:
935
0
      elems->owe_dh = NULL;
936
0
      elems->owe_dh_len = 0;
937
0
      break;
938
0
    case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
939
0
      elems->password_id = NULL;
940
0
      elems->password_id_len = 0;
941
0
      break;
942
0
    case WLAN_EID_EXT_HE_CAPABILITIES:
943
0
      elems->he_capabilities = NULL;
944
0
      elems->he_capabilities_len = 0;
945
0
      break;
946
0
    case WLAN_EID_EXT_HE_OPERATION:
947
0
      elems->he_operation = NULL;
948
0
      elems->he_operation_len = 0;
949
0
      break;
950
0
    case WLAN_EID_EXT_OCV_OCI:
951
0
      elems->oci = NULL;
952
0
      elems->oci_len = 0;
953
0
      break;
954
0
    case WLAN_EID_EXT_SHORT_SSID_LIST:
955
0
      elems->short_ssid_list = NULL;
956
0
      elems->short_ssid_list_len = 0;
957
0
      break;
958
0
    case WLAN_EID_EXT_HE_6GHZ_BAND_CAP:
959
0
      elems->he_6ghz_band_cap = NULL;
960
0
      break;
961
0
    case WLAN_EID_EXT_PASN_PARAMS:
962
0
      elems->pasn_params = NULL;
963
0
      elems->pasn_params_len = 0;
964
0
      break;
965
0
    case WLAN_EID_EXT_MULTI_LINK:
966
0
      elems->basic_mle = NULL;
967
0
      elems->probe_req_mle = NULL;
968
0
      elems->reconf_mle = NULL;
969
0
      elems->tdls_mle = NULL;
970
0
      elems->prior_access_mle = NULL;
971
972
0
      elems->basic_mle_len = 0;
973
0
      elems->probe_req_mle_len = 0;
974
0
      elems->reconf_mle_len = 0;
975
0
      elems->tdls_mle_len = 0;
976
0
      elems->prior_access_mle_len = 0;
977
0
      break;
978
0
    case WLAN_EID_EXT_EHT_CAPABILITIES:
979
0
      elems->eht_capabilities = NULL;
980
0
      elems->eht_capabilities_len = 0;
981
0
      break;
982
0
    case WLAN_EID_EXT_EHT_OPERATION:
983
0
      elems->eht_operation = NULL;
984
0
      elems->eht_operation_len = 0;
985
0
      break;
986
0
    }
987
0
  }
988
0
}
989
990
991
ParseRes ieee802_11_parse_link_assoc_req(struct ieee802_11_elems *elems,
992
           struct wpabuf *mlbuf,
993
           u8 link_id, bool show_errors)
994
0
{
995
0
  const struct ieee80211_eht_ml *ml;
996
0
  const u8 *pos;
997
0
  ParseRes res = ParseFailed;
998
0
  size_t len;
999
1000
0
  pos = wpabuf_head(mlbuf);
1001
0
  len = wpabuf_len(mlbuf);
1002
1003
  /* Must have control and common info length */
1004
0
  if (len < sizeof(*ml) + 1 || len < sizeof(*ml) + pos[sizeof(*ml)])
1005
0
    goto out;
1006
1007
0
  ml = (const struct ieee80211_eht_ml *) pos;
1008
1009
  /* As we are interested with the Per-STA profile, ignore other types */
1010
0
  if ((le_to_host16(ml->ml_control) & MULTI_LINK_CONTROL_TYPE_MASK) !=
1011
0
       MULTI_LINK_CONTROL_TYPE_BASIC)
1012
0
    goto out;
1013
1014
  /* Skip the common info */
1015
0
  len -= sizeof(*ml) + pos[sizeof(*ml)];
1016
0
  pos += sizeof(*ml) + pos[sizeof(*ml)];
1017
1018
0
  while (len > 2) {
1019
0
    size_t sub_elem_len, sta_info_len;
1020
0
    u16 link_info_control;
1021
0
    const u8 *non_inherit;
1022
0
    int num_frag_subelems;
1023
1024
0
    num_frag_subelems =
1025
0
      ieee802_11_defrag_mle_subelem(mlbuf, pos,
1026
0
                  &sub_elem_len);
1027
0
    if (num_frag_subelems < 0) {
1028
0
      wpa_printf(MSG_DEBUG,
1029
0
           "MLD: Failed to parse MLE subelem");
1030
0
      goto out;
1031
0
    }
1032
1033
0
    len -= num_frag_subelems * 2;
1034
1035
0
    wpa_printf(MSG_DEBUG,
1036
0
         "MLD: sub element: len=%zu, sub_elem_len=%zu, Fragment subelems=%u",
1037
0
         len, sub_elem_len, num_frag_subelems);
1038
1039
0
    if (2 + sub_elem_len > len) {
1040
0
      if (show_errors)
1041
0
        wpa_printf(MSG_DEBUG,
1042
0
             "MLD: error: len=%zu, sub_elem_len=%zu",
1043
0
             len, sub_elem_len);
1044
0
      goto out;
1045
0
    }
1046
1047
0
    if (*pos != 0) {
1048
0
      pos += 2 + sub_elem_len;
1049
0
      len -= 2 + sub_elem_len;
1050
0
      continue;
1051
0
    }
1052
1053
0
    if (sub_elem_len < 5) {
1054
0
      if (show_errors)
1055
0
        wpa_printf(MSG_DEBUG,
1056
0
             "MLD: error: sub_elem_len=%zu < 5",
1057
0
             sub_elem_len);
1058
0
      goto out;
1059
0
    }
1060
1061
0
    link_info_control = WPA_GET_LE16(pos + 2);
1062
0
    if ((link_info_control & BASIC_MLE_STA_CTRL_LINK_ID_MASK) !=
1063
0
        link_id) {
1064
0
      pos += 2 + sub_elem_len;
1065
0
      len -= 2 + sub_elem_len;
1066
0
      continue;
1067
0
    }
1068
1069
0
    sta_info_len = *(pos + 4);
1070
0
    if (sub_elem_len < sta_info_len + 3 || sta_info_len < 1) {
1071
0
      if (show_errors)
1072
0
        wpa_printf(MSG_DEBUG,
1073
0
             "MLD: error: sub_elem_len=%zu, sta_info_len=%zu",
1074
0
             sub_elem_len, sta_info_len);
1075
0
      goto out;
1076
0
    }
1077
1078
0
    pos += sta_info_len + 4;
1079
0
    sub_elem_len -= sta_info_len + 2;
1080
1081
0
    if (sub_elem_len < 2) {
1082
0
      if (show_errors)
1083
0
        wpa_printf(MSG_DEBUG,
1084
0
             "MLD: missing capability info");
1085
0
      goto out;
1086
0
    }
1087
1088
0
    pos += 2;
1089
0
    sub_elem_len -= 2;
1090
1091
    /* Handle non-inheritance */
1092
0
    non_inherit = get_ie_ext(pos, sub_elem_len,
1093
0
           WLAN_EID_EXT_NON_INHERITANCE);
1094
0
    if (non_inherit && non_inherit[1] > 1) {
1095
0
      u8 non_inherit_len = non_inherit[1] - 1;
1096
1097
      /*
1098
       * Do not include the Non-Inheritance element when
1099
       * parsing below. It should be the last element in the
1100
       * subelement.
1101
       */
1102
0
      if (3U + non_inherit_len > sub_elem_len)
1103
0
        goto out;
1104
0
      sub_elem_len -= 3 + non_inherit_len;
1105
1106
      /* Skip the ID, length and extension ID */
1107
0
      non_inherit += 3;
1108
1109
0
      if (non_inherit_len < 1UL + non_inherit[0]) {
1110
0
        if (show_errors)
1111
0
          wpa_printf(MSG_DEBUG,
1112
0
               "MLD: Invalid inheritance");
1113
0
        goto out;
1114
0
      }
1115
1116
0
      ieee802_11_elems_clear_ids(elems, &non_inherit[1],
1117
0
               non_inherit[0]);
1118
1119
0
      non_inherit_len -= 1 + non_inherit[0];
1120
0
      non_inherit += 1 + non_inherit[0];
1121
1122
0
      if (non_inherit_len < 1UL ||
1123
0
          non_inherit_len < 1UL + non_inherit[0]) {
1124
0
        if (show_errors)
1125
0
          wpa_printf(MSG_DEBUG,
1126
0
               "MLD: Invalid inheritance");
1127
0
        goto out;
1128
0
      }
1129
1130
0
      ieee802_11_elems_clear_ext_ids(elems, &non_inherit[1],
1131
0
                   non_inherit[0]);
1132
0
    }
1133
1134
0
    wpa_printf(MSG_DEBUG, "MLD: link: sub_elem_len=%zu",
1135
0
         sub_elem_len);
1136
1137
0
    if (sub_elem_len)
1138
0
      res = __ieee802_11_parse_elems(pos, sub_elem_len,
1139
0
                   elems, show_errors);
1140
0
    else
1141
0
      res = ParseOK;
1142
0
    break;
1143
0
  }
1144
1145
0
out:
1146
0
  return res;
1147
0
}
1148
1149
1150
int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
1151
0
{
1152
0
  const struct element *elem;
1153
0
  int count = 0;
1154
1155
0
  if (ies == NULL)
1156
0
    return 0;
1157
1158
0
  for_each_element(elem, ies, ies_len)
1159
0
    count++;
1160
1161
0
  return count;
1162
0
}
1163
1164
1165
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
1166
              u32 oui_type)
1167
0
{
1168
0
  struct wpabuf *buf;
1169
0
  const struct element *elem, *found = NULL;
1170
1171
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
1172
0
    if (elem->datalen >= 4 &&
1173
0
        WPA_GET_BE32(elem->data) == oui_type) {
1174
0
      found = elem;
1175
0
      break;
1176
0
    }
1177
0
  }
1178
1179
0
  if (!found)
1180
0
    return NULL; /* No specified vendor IE found */
1181
1182
0
  buf = wpabuf_alloc(ies_len);
1183
0
  if (buf == NULL)
1184
0
    return NULL;
1185
1186
  /*
1187
   * There may be multiple vendor IEs in the message, so need to
1188
   * concatenate their data fields.
1189
   */
1190
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
1191
0
    if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type)
1192
0
      wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4);
1193
0
  }
1194
1195
0
  return buf;
1196
0
}
1197
1198
1199
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
1200
0
{
1201
0
  u16 fc, type, stype;
1202
1203
  /*
1204
   * PS-Poll frames are 16 bytes. All other frames are
1205
   * 24 bytes or longer.
1206
   */
1207
0
  if (len < 16)
1208
0
    return NULL;
1209
1210
0
  fc = le_to_host16(hdr->frame_control);
1211
0
  type = WLAN_FC_GET_TYPE(fc);
1212
0
  stype = WLAN_FC_GET_STYPE(fc);
1213
1214
0
  switch (type) {
1215
0
  case WLAN_FC_TYPE_DATA:
1216
0
    if (len < 24)
1217
0
      return NULL;
1218
0
    switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
1219
0
    case WLAN_FC_FROMDS | WLAN_FC_TODS:
1220
0
    case WLAN_FC_TODS:
1221
0
      return hdr->addr1;
1222
0
    case WLAN_FC_FROMDS:
1223
0
      return hdr->addr2;
1224
0
    default:
1225
0
      return NULL;
1226
0
    }
1227
0
  case WLAN_FC_TYPE_CTRL:
1228
0
    if (stype != WLAN_FC_STYPE_PSPOLL)
1229
0
      return NULL;
1230
0
    return hdr->addr1;
1231
0
  case WLAN_FC_TYPE_MGMT:
1232
0
    return hdr->addr3;
1233
0
  default:
1234
0
    return NULL;
1235
0
  }
1236
0
}
1237
1238
1239
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
1240
        const char *name, const char *val)
1241
0
{
1242
0
  int num, v;
1243
0
  const char *pos;
1244
0
  struct hostapd_wmm_ac_params *ac;
1245
1246
  /* skip 'wme_ac_' or 'wmm_ac_' prefix */
1247
0
  pos = name + 7;
1248
0
  if (os_strncmp(pos, "be_", 3) == 0) {
1249
0
    num = 0;
1250
0
    pos += 3;
1251
0
  } else if (os_strncmp(pos, "bk_", 3) == 0) {
1252
0
    num = 1;
1253
0
    pos += 3;
1254
0
  } else if (os_strncmp(pos, "vi_", 3) == 0) {
1255
0
    num = 2;
1256
0
    pos += 3;
1257
0
  } else if (os_strncmp(pos, "vo_", 3) == 0) {
1258
0
    num = 3;
1259
0
    pos += 3;
1260
0
  } else {
1261
0
    wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
1262
0
    return -1;
1263
0
  }
1264
1265
0
  ac = &wmm_ac_params[num];
1266
1267
0
  if (os_strcmp(pos, "aifs") == 0) {
1268
0
    v = atoi(val);
1269
0
    if (v < 1 || v > 255) {
1270
0
      wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
1271
0
      return -1;
1272
0
    }
1273
0
    ac->aifs = v;
1274
0
  } else if (os_strcmp(pos, "cwmin") == 0) {
1275
0
    v = atoi(val);
1276
0
    if (v < 0 || v > 15) {
1277
0
      wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
1278
0
      return -1;
1279
0
    }
1280
0
    ac->cwmin = v;
1281
0
  } else if (os_strcmp(pos, "cwmax") == 0) {
1282
0
    v = atoi(val);
1283
0
    if (v < 0 || v > 15) {
1284
0
      wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
1285
0
      return -1;
1286
0
    }
1287
0
    ac->cwmax = v;
1288
0
  } else if (os_strcmp(pos, "txop_limit") == 0) {
1289
0
    v = atoi(val);
1290
0
    if (v < 0 || v > 0xffff) {
1291
0
      wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
1292
0
      return -1;
1293
0
    }
1294
0
    ac->txop_limit = v;
1295
0
  } else if (os_strcmp(pos, "acm") == 0) {
1296
0
    v = atoi(val);
1297
0
    if (v < 0 || v > 1) {
1298
0
      wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
1299
0
      return -1;
1300
0
    }
1301
0
    ac->admission_control_mandatory = v;
1302
0
  } else {
1303
0
    wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
1304
0
    return -1;
1305
0
  }
1306
1307
0
  return 0;
1308
0
}
1309
1310
1311
/* convert floats with one decimal place to value*10 int, i.e.,
1312
 * "1.5" will return 15
1313
 */
1314
static int hostapd_config_read_int10(const char *value)
1315
0
{
1316
0
  int i, d;
1317
0
  char *pos;
1318
1319
0
  i = atoi(value);
1320
0
  pos = os_strchr(value, '.');
1321
0
  d = 0;
1322
0
  if (pos) {
1323
0
    pos++;
1324
0
    if (*pos >= '0' && *pos <= '9')
1325
0
      d = *pos - '0';
1326
0
  }
1327
1328
0
  return i * 10 + d;
1329
0
}
1330
1331
1332
static int valid_cw(int cw)
1333
0
{
1334
0
  return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
1335
0
    cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
1336
0
    cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
1337
0
    cw == 32767);
1338
0
}
1339
1340
1341
int hostapd_config_tx_queue(struct hostapd_tx_queue_params tx_queue[],
1342
          const char *name, const char *val)
1343
0
{
1344
0
  int num;
1345
0
  const char *pos;
1346
0
  struct hostapd_tx_queue_params *queue;
1347
1348
  /* skip 'tx_queue_' prefix */
1349
0
  pos = name + 9;
1350
0
  if (os_strncmp(pos, "data", 4) == 0 &&
1351
0
      pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
1352
0
    num = pos[4] - '0';
1353
0
    pos += 6;
1354
0
  } else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
1355
0
       os_strncmp(pos, "beacon_", 7) == 0) {
1356
0
    wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
1357
0
    return 0;
1358
0
  } else {
1359
0
    wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
1360
0
    return -1;
1361
0
  }
1362
1363
0
  if (num >= NUM_TX_QUEUES) {
1364
    /* for backwards compatibility, do not trigger failure */
1365
0
    wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
1366
0
    return 0;
1367
0
  }
1368
1369
0
  queue = &tx_queue[num];
1370
1371
0
  if (os_strcmp(pos, "aifs") == 0) {
1372
0
    queue->aifs = atoi(val);
1373
0
    if (queue->aifs < 0 || queue->aifs > 255) {
1374
0
      wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
1375
0
           queue->aifs);
1376
0
      return -1;
1377
0
    }
1378
0
  } else if (os_strcmp(pos, "cwmin") == 0) {
1379
0
    queue->cwmin = atoi(val);
1380
0
    if (!valid_cw(queue->cwmin)) {
1381
0
      wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
1382
0
           queue->cwmin);
1383
0
      return -1;
1384
0
    }
1385
0
  } else if (os_strcmp(pos, "cwmax") == 0) {
1386
0
    queue->cwmax = atoi(val);
1387
0
    if (!valid_cw(queue->cwmax)) {
1388
0
      wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
1389
0
           queue->cwmax);
1390
0
      return -1;
1391
0
    }
1392
0
  } else if (os_strcmp(pos, "burst") == 0) {
1393
0
    queue->burst = hostapd_config_read_int10(val);
1394
0
  } else {
1395
0
    wpa_printf(MSG_ERROR, "Unknown queue field '%s'", pos);
1396
0
    return -1;
1397
0
  }
1398
1399
0
  return 0;
1400
0
}
1401
1402
1403
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
1404
0
{
1405
0
  u8 op_class;
1406
1407
0
  return ieee80211_freq_to_channel_ext(freq, 0, CONF_OPER_CHWIDTH_USE_HT,
1408
0
               &op_class, channel);
1409
0
}
1410
1411
1412
/**
1413
 * ieee80211_freq_to_channel_ext - Convert frequency into channel info
1414
 * for HT40, VHT, and HE. DFS channels are not covered.
1415
 * @freq: Frequency (MHz) to convert
1416
 * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
1417
 * @chanwidth: VHT/EDMG/etc. channel width
1418
 * @op_class: Buffer for returning operating class
1419
 * @channel: Buffer for returning channel number
1420
 * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
1421
 */
1422
enum hostapd_hw_mode
1423
ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
1424
            enum oper_chan_width chanwidth,
1425
            u8 *op_class, u8 *channel)
1426
0
{
1427
0
  u8 vht_opclass;
1428
1429
  /* TODO: more operating classes */
1430
1431
0
  if (sec_channel > 1 || sec_channel < -1)
1432
0
    return NUM_HOSTAPD_MODES;
1433
1434
0
  if (freq >= 2412 && freq <= 2472) {
1435
0
    if ((freq - 2407) % 5)
1436
0
      return NUM_HOSTAPD_MODES;
1437
1438
0
    if (chanwidth)
1439
0
      return NUM_HOSTAPD_MODES;
1440
1441
    /* 2.407 GHz, channels 1..13 */
1442
0
    if (sec_channel == 1)
1443
0
      *op_class = 83;
1444
0
    else if (sec_channel == -1)
1445
0
      *op_class = 84;
1446
0
    else
1447
0
      *op_class = 81;
1448
1449
0
    *channel = (freq - 2407) / 5;
1450
1451
0
    return HOSTAPD_MODE_IEEE80211G;
1452
0
  }
1453
1454
0
  if (freq == 2484) {
1455
0
    if (sec_channel || chanwidth)
1456
0
      return NUM_HOSTAPD_MODES;
1457
1458
0
    *op_class = 82; /* channel 14 */
1459
0
    *channel = 14;
1460
1461
0
    return HOSTAPD_MODE_IEEE80211B;
1462
0
  }
1463
1464
0
  if (freq >= 4900 && freq < 5000) {
1465
0
    if ((freq - 4000) % 5)
1466
0
      return NUM_HOSTAPD_MODES;
1467
0
    *channel = (freq - 4000) / 5;
1468
0
    *op_class = 0; /* TODO */
1469
0
    return HOSTAPD_MODE_IEEE80211A;
1470
0
  }
1471
1472
0
  switch (chanwidth) {
1473
0
  case CONF_OPER_CHWIDTH_80MHZ:
1474
0
    vht_opclass = 128;
1475
0
    break;
1476
0
  case CONF_OPER_CHWIDTH_160MHZ:
1477
0
    vht_opclass = 129;
1478
0
    break;
1479
0
  case CONF_OPER_CHWIDTH_80P80MHZ:
1480
0
    vht_opclass = 130;
1481
0
    break;
1482
0
  default:
1483
0
    vht_opclass = 0;
1484
0
    break;
1485
0
  }
1486
1487
  /* 5 GHz, channels 36..48 */
1488
0
  if (freq >= 5180 && freq <= 5240) {
1489
0
    if ((freq - 5000) % 5)
1490
0
      return NUM_HOSTAPD_MODES;
1491
1492
0
    if (vht_opclass)
1493
0
      *op_class = vht_opclass;
1494
0
    else if (sec_channel == 1)
1495
0
      *op_class = 116;
1496
0
    else if (sec_channel == -1)
1497
0
      *op_class = 117;
1498
0
    else
1499
0
      *op_class = 115;
1500
1501
0
    *channel = (freq - 5000) / 5;
1502
1503
0
    return HOSTAPD_MODE_IEEE80211A;
1504
0
  }
1505
1506
  /* 5 GHz, channels 52..64 */
1507
0
  if (freq >= 5260 && freq <= 5320) {
1508
0
    if ((freq - 5000) % 5)
1509
0
      return NUM_HOSTAPD_MODES;
1510
1511
0
    if (vht_opclass)
1512
0
      *op_class = vht_opclass;
1513
0
    else if (sec_channel == 1)
1514
0
      *op_class = 119;
1515
0
    else if (sec_channel == -1)
1516
0
      *op_class = 120;
1517
0
    else
1518
0
      *op_class = 118;
1519
1520
0
    *channel = (freq - 5000) / 5;
1521
1522
0
    return HOSTAPD_MODE_IEEE80211A;
1523
0
  }
1524
1525
  /* 5 GHz, channels 149..177 */
1526
0
  if (freq >= 5745 && freq <= 5885) {
1527
0
    if ((freq - 5000) % 5)
1528
0
      return NUM_HOSTAPD_MODES;
1529
1530
0
    if (vht_opclass)
1531
0
      *op_class = vht_opclass;
1532
0
    else if (sec_channel == 1)
1533
0
      *op_class = 126;
1534
0
    else if (sec_channel == -1)
1535
0
      *op_class = 127;
1536
0
    else
1537
0
      *op_class = 125;
1538
1539
0
    *channel = (freq - 5000) / 5;
1540
1541
0
    return HOSTAPD_MODE_IEEE80211A;
1542
0
  }
1543
1544
  /* 5 GHz, channels 100..144 */
1545
0
  if (freq >= 5500 && freq <= 5720) {
1546
0
    if ((freq - 5000) % 5)
1547
0
      return NUM_HOSTAPD_MODES;
1548
1549
0
    if (vht_opclass)
1550
0
      *op_class = vht_opclass;
1551
0
    else if (sec_channel == 1)
1552
0
      *op_class = 122;
1553
0
    else if (sec_channel == -1)
1554
0
      *op_class = 123;
1555
0
    else
1556
0
      *op_class = 121;
1557
1558
0
    *channel = (freq - 5000) / 5;
1559
1560
0
    return HOSTAPD_MODE_IEEE80211A;
1561
0
  }
1562
1563
0
  if (freq >= 5000 && freq < 5900) {
1564
0
    if ((freq - 5000) % 5)
1565
0
      return NUM_HOSTAPD_MODES;
1566
0
    *channel = (freq - 5000) / 5;
1567
0
    *op_class = 0; /* TODO */
1568
0
    return HOSTAPD_MODE_IEEE80211A;
1569
0
  }
1570
1571
0
  if (freq > 5950 && freq <= 7115) {
1572
0
    if ((freq - 5950) % 5)
1573
0
      return NUM_HOSTAPD_MODES;
1574
1575
0
    switch (chanwidth) {
1576
0
    case CONF_OPER_CHWIDTH_80MHZ:
1577
0
      *op_class = 133;
1578
0
      break;
1579
0
    case CONF_OPER_CHWIDTH_160MHZ:
1580
0
      *op_class = 134;
1581
0
      break;
1582
0
    case CONF_OPER_CHWIDTH_80P80MHZ:
1583
0
      *op_class = 135;
1584
0
      break;
1585
0
    case CONF_OPER_CHWIDTH_320MHZ:
1586
0
      *op_class = 137;
1587
0
      break;
1588
0
    default:
1589
0
      if (sec_channel)
1590
0
        *op_class = 132;
1591
0
      else
1592
0
        *op_class = 131;
1593
0
      break;
1594
0
    }
1595
1596
0
    *channel = (freq - 5950) / 5;
1597
0
    return HOSTAPD_MODE_IEEE80211A;
1598
0
  }
1599
1600
0
  if (freq == 5935) {
1601
0
    *op_class = 136;
1602
0
    *channel = (freq - 5925) / 5;
1603
0
    return HOSTAPD_MODE_IEEE80211A;
1604
0
  }
1605
1606
  /* 56.16 GHz, channel 1..6 */
1607
0
  if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
1608
0
    if (sec_channel)
1609
0
      return NUM_HOSTAPD_MODES;
1610
1611
0
    switch (chanwidth) {
1612
0
    case CONF_OPER_CHWIDTH_USE_HT:
1613
0
    case CONF_OPER_CHWIDTH_2160MHZ:
1614
0
      *channel = (freq - 56160) / 2160;
1615
0
      *op_class = 180;
1616
0
      break;
1617
0
    case CONF_OPER_CHWIDTH_4320MHZ:
1618
      /* EDMG channels 9 - 13 */
1619
0
      if (freq > 56160 + 2160 * 5)
1620
0
        return NUM_HOSTAPD_MODES;
1621
1622
0
      *channel = (freq - 56160) / 2160 + 8;
1623
0
      *op_class = 181;
1624
0
      break;
1625
0
    case CONF_OPER_CHWIDTH_6480MHZ:
1626
      /* EDMG channels 17 - 20 */
1627
0
      if (freq > 56160 + 2160 * 4)
1628
0
        return NUM_HOSTAPD_MODES;
1629
1630
0
      *channel = (freq - 56160) / 2160 + 16;
1631
0
      *op_class = 182;
1632
0
      break;
1633
0
    case CONF_OPER_CHWIDTH_8640MHZ:
1634
      /* EDMG channels 25 - 27 */
1635
0
      if (freq > 56160 + 2160 * 3)
1636
0
        return NUM_HOSTAPD_MODES;
1637
1638
0
      *channel = (freq - 56160) / 2160 + 24;
1639
0
      *op_class = 183;
1640
0
      break;
1641
0
    default:
1642
0
      return NUM_HOSTAPD_MODES;
1643
0
    }
1644
1645
0
    return HOSTAPD_MODE_IEEE80211AD;
1646
0
  }
1647
1648
0
  return NUM_HOSTAPD_MODES;
1649
0
}
1650
1651
1652
int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
1653
          int sec_channel, u8 *op_class, u8 *channel)
1654
0
{
1655
0
  int cw = CHAN_WIDTH_UNKNOWN;
1656
1657
0
  switch (chanwidth) {
1658
0
  case CHAN_WIDTH_UNKNOWN:
1659
0
  case CHAN_WIDTH_20_NOHT:
1660
0
  case CHAN_WIDTH_20:
1661
0
  case CHAN_WIDTH_40:
1662
0
    cw = CONF_OPER_CHWIDTH_USE_HT;
1663
0
    break;
1664
0
  case CHAN_WIDTH_80:
1665
0
    cw = CONF_OPER_CHWIDTH_80MHZ;
1666
0
    break;
1667
0
  case CHAN_WIDTH_80P80:
1668
0
    cw = CONF_OPER_CHWIDTH_80P80MHZ;
1669
0
    break;
1670
0
  case CHAN_WIDTH_160:
1671
0
    cw = CONF_OPER_CHWIDTH_160MHZ;
1672
0
    break;
1673
0
  case CHAN_WIDTH_2160:
1674
0
    cw = CONF_OPER_CHWIDTH_2160MHZ;
1675
0
    break;
1676
0
  case CHAN_WIDTH_4320:
1677
0
    cw = CONF_OPER_CHWIDTH_4320MHZ;
1678
0
    break;
1679
0
  case CHAN_WIDTH_6480:
1680
0
    cw = CONF_OPER_CHWIDTH_6480MHZ;
1681
0
    break;
1682
0
  case CHAN_WIDTH_8640:
1683
0
    cw = CONF_OPER_CHWIDTH_8640MHZ;
1684
0
    break;
1685
0
  case CHAN_WIDTH_320:
1686
0
    cw = CONF_OPER_CHWIDTH_320MHZ;
1687
0
    break;
1688
0
  }
1689
1690
0
  if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class,
1691
0
            channel) == NUM_HOSTAPD_MODES) {
1692
0
    wpa_printf(MSG_WARNING,
1693
0
         "Cannot determine operating class and channel (freq=%u chanwidth=%d sec_channel=%d)",
1694
0
         freq, chanwidth, sec_channel);
1695
0
    return -1;
1696
0
  }
1697
1698
0
  return 0;
1699
0
}
1700
1701
1702
static const char *const us_op_class_cc[] = {
1703
  "US", "CA", NULL
1704
};
1705
1706
static const char *const eu_op_class_cc[] = {
1707
  "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
1708
  "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
1709
  "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
1710
  "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
1711
};
1712
1713
static const char *const jp_op_class_cc[] = {
1714
  "JP", NULL
1715
};
1716
1717
static const char *const cn_op_class_cc[] = {
1718
  "CN", NULL
1719
};
1720
1721
1722
static int country_match(const char *const cc[], const char *const country)
1723
0
{
1724
0
  int i;
1725
1726
0
  if (country == NULL)
1727
0
    return 0;
1728
0
  for (i = 0; cc[i]; i++) {
1729
0
    if (cc[i][0] == country[0] && cc[i][1] == country[1])
1730
0
      return 1;
1731
0
  }
1732
1733
0
  return 0;
1734
0
}
1735
1736
1737
static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
1738
0
{
1739
0
  switch (op_class) {
1740
0
  case 12: /* channels 1..11 */
1741
0
  case 32: /* channels 1..7; 40 MHz */
1742
0
  case 33: /* channels 5..11; 40 MHz */
1743
0
    if (chan < 1 || chan > 11)
1744
0
      return -1;
1745
0
    return 2407 + 5 * chan;
1746
0
  case 1: /* channels 36,40,44,48 */
1747
0
  case 2: /* channels 52,56,60,64; dfs */
1748
0
  case 22: /* channels 36,44; 40 MHz */
1749
0
  case 23: /* channels 52,60; 40 MHz */
1750
0
  case 27: /* channels 40,48; 40 MHz */
1751
0
  case 28: /* channels 56,64; 40 MHz */
1752
0
    if (chan < 36 || chan > 64)
1753
0
      return -1;
1754
0
    return 5000 + 5 * chan;
1755
0
  case 4: /* channels 100-144 */
1756
0
  case 24: /* channels 100-140; 40 MHz */
1757
0
    if (chan < 100 || chan > 144)
1758
0
      return -1;
1759
0
    return 5000 + 5 * chan;
1760
0
  case 3: /* channels 149,153,157,161 */
1761
0
  case 25: /* channels 149,157; 40 MHz */
1762
0
  case 26: /* channels 149,157; 40 MHz */
1763
0
  case 30: /* channels 153,161; 40 MHz */
1764
0
  case 31: /* channels 153,161; 40 MHz */
1765
0
    if (chan < 149 || chan > 161)
1766
0
      return -1;
1767
0
    return 5000 + 5 * chan;
1768
0
  case 5: /* channels 149,153,157,161,165 */
1769
0
    if (chan < 149 || chan > 165)
1770
0
      return -1;
1771
0
    return 5000 + 5 * chan;
1772
0
  case 34: /* 60 GHz band, channels 1..8 */
1773
0
    if (chan < 1 || chan > 8)
1774
0
      return -1;
1775
0
    return 56160 + 2160 * chan;
1776
0
  case 37: /* 60 GHz band, EDMG CB2, channels 9..15 */
1777
0
    if (chan < 9 || chan > 15)
1778
0
      return -1;
1779
0
    return 56160 + 2160 * (chan - 8);
1780
0
  case 38: /* 60 GHz band, EDMG CB3, channels 17..22 */
1781
0
    if (chan < 17 || chan > 22)
1782
0
      return -1;
1783
0
    return 56160 + 2160 * (chan - 16);
1784
0
  case 39: /* 60 GHz band, EDMG CB4, channels 25..29 */
1785
0
    if (chan < 25 || chan > 29)
1786
0
      return -1;
1787
0
    return 56160 + 2160 * (chan - 24);
1788
0
  default:
1789
0
    return -1;
1790
0
  }
1791
0
}
1792
1793
1794
static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
1795
0
{
1796
0
  switch (op_class) {
1797
0
  case 4: /* channels 1..13 */
1798
0
  case 11: /* channels 1..9; 40 MHz */
1799
0
  case 12: /* channels 5..13; 40 MHz */
1800
0
    if (chan < 1 || chan > 13)
1801
0
      return -1;
1802
0
    return 2407 + 5 * chan;
1803
0
  case 1: /* channels 36,40,44,48 */
1804
0
  case 2: /* channels 52,56,60,64; dfs */
1805
0
  case 5: /* channels 36,44; 40 MHz */
1806
0
  case 6: /* channels 52,60; 40 MHz */
1807
0
  case 8: /* channels 40,48; 40 MHz */
1808
0
  case 9: /* channels 56,64; 40 MHz */
1809
0
    if (chan < 36 || chan > 64)
1810
0
      return -1;
1811
0
    return 5000 + 5 * chan;
1812
0
  case 3: /* channels 100-140 */
1813
0
  case 7: /* channels 100-132; 40 MHz */
1814
0
  case 10: /* channels 104-136; 40 MHz */
1815
0
  case 16: /* channels 100-140 */
1816
0
    if (chan < 100 || chan > 140)
1817
0
      return -1;
1818
0
    return 5000 + 5 * chan;
1819
0
  case 17: /* channels 149,153,157,161,165,169 */
1820
0
    if (chan < 149 || chan > 169)
1821
0
      return -1;
1822
0
    return 5000 + 5 * chan;
1823
0
  case 18: /* 60 GHz band, channels 1..6 */
1824
0
    if (chan < 1 || chan > 6)
1825
0
      return -1;
1826
0
    return 56160 + 2160 * chan;
1827
0
  case 21: /* 60 GHz band, EDMG CB2, channels 9..11 */
1828
0
    if (chan < 9 || chan > 11)
1829
0
      return -1;
1830
0
    return 56160 + 2160 * (chan - 8);
1831
0
  case 22: /* 60 GHz band, EDMG CB3, channels 17..18 */
1832
0
    if (chan < 17 || chan > 18)
1833
0
      return -1;
1834
0
    return 56160 + 2160 * (chan - 16);
1835
0
  case 23: /* 60 GHz band, EDMG CB4, channels 25 */
1836
0
    if (chan != 25)
1837
0
      return -1;
1838
0
    return 56160 + 2160 * (chan - 24);
1839
0
  default:
1840
0
    return -1;
1841
0
  }
1842
0
}
1843
1844
1845
static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
1846
0
{
1847
  /* Table E-3 in IEEE Std 802.11-2020 - Operating classes in Japan */
1848
0
  switch (op_class) {
1849
0
  case 30: /* channels 1..13 */
1850
0
  case 56: /* channels 1..9; 40 MHz */
1851
0
  case 57: /* channels 5..13; 40 MHz */
1852
0
    if (chan < 1 || chan > 13)
1853
0
      return -1;
1854
0
    return 2407 + 5 * chan;
1855
0
  case 31: /* channel 14 */
1856
0
    if (chan != 14)
1857
0
      return -1;
1858
0
    return 2414 + 5 * chan;
1859
0
  case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
1860
0
  case 32: /* channels 52,56,60,64 */
1861
0
  case 33: /* channels 52,56,60,64 */
1862
0
  case 36: /* channels 36,44; 40 MHz */
1863
0
  case 37: /* channels 52,60; 40 MHz */
1864
0
  case 38: /* channels 52,60; 40 MHz */
1865
0
  case 41: /* channels 40,48; 40 MHz */
1866
0
  case 42: /* channels 56,64; 40 MHz */
1867
0
  case 43: /* channels 56,64; 40 MHz */
1868
0
    if (chan < 34 || chan > 64)
1869
0
      return -1;
1870
0
    return 5000 + 5 * chan;
1871
0
  case 34: /* channels 100-144 */
1872
0
  case 35: /* reserved */
1873
0
  case 39: /* channels 100-140; 40 MHz */
1874
0
  case 40: /* reserved */
1875
0
  case 44: /* channels 104-144; 40 MHz */
1876
0
  case 45: /* reserved */
1877
0
  case 58: /* channels 100-144 */
1878
0
    if (chan < 100 || chan > 144)
1879
0
      return -1;
1880
0
    return 5000 + 5 * chan;
1881
0
  case 59: /* 60 GHz band, channels 1..6 */
1882
0
    if (chan < 1 || chan > 6)
1883
0
      return -1;
1884
0
    return 56160 + 2160 * chan;
1885
0
  case 62: /* 60 GHz band, EDMG CB2, channels 9..11 */
1886
0
    if (chan < 9 || chan > 11)
1887
0
      return -1;
1888
0
    return 56160 + 2160 * (chan - 8);
1889
0
  case 63: /* 60 GHz band, EDMG CB3, channels 17..18 */
1890
0
    if (chan < 17 || chan > 18)
1891
0
      return -1;
1892
0
    return 56160 + 2160 * (chan - 16);
1893
0
  case 64: /* 60 GHz band, EDMG CB4, channel 25 */
1894
0
    if (chan != 25)
1895
0
      return -1;
1896
0
    return 56160 + 2160 * (chan - 24);
1897
0
  default:
1898
0
    return -1;
1899
0
  }
1900
0
}
1901
1902
1903
static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
1904
0
{
1905
0
  switch (op_class) {
1906
0
  case 7: /* channels 1..13 */
1907
0
  case 8: /* channels 1..9; 40 MHz */
1908
0
  case 9: /* channels 5..13; 40 MHz */
1909
0
    if (chan < 1 || chan > 13)
1910
0
      return -1;
1911
0
    return 2407 + 5 * chan;
1912
0
  case 1: /* channels 36,40,44,48 */
1913
0
  case 2: /* channels 52,56,60,64; dfs */
1914
0
  case 4: /* channels 36,44; 40 MHz */
1915
0
  case 5: /* channels 52,60; 40 MHz */
1916
0
    if (chan < 36 || chan > 64)
1917
0
      return -1;
1918
0
    return 5000 + 5 * chan;
1919
0
  case 3: /* channels 149,153,157,161,165 */
1920
0
  case 6: /* channels 149,157; 40 MHz */
1921
0
    if (chan < 149 || chan > 165)
1922
0
      return -1;
1923
0
    return 5000 + 5 * chan;
1924
0
  default:
1925
0
    return -1;
1926
0
  }
1927
0
}
1928
1929
1930
static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
1931
0
{
1932
  /* Table E-4 in IEEE Std 802.11-2020 - Global operating classes */
1933
0
  switch (op_class) {
1934
0
  case 81:
1935
    /* channels 1..13 */
1936
0
    if (chan < 1 || chan > 13)
1937
0
      return -1;
1938
0
    return 2407 + 5 * chan;
1939
0
  case 82:
1940
    /* channel 14 */
1941
0
    if (chan != 14)
1942
0
      return -1;
1943
0
    return 2414 + 5 * chan;
1944
0
  case 83: /* channels 1..9; 40 MHz */
1945
0
  case 84: /* channels 5..13; 40 MHz */
1946
0
    if (chan < 1 || chan > 13)
1947
0
      return -1;
1948
0
    return 2407 + 5 * chan;
1949
0
  case 115: /* channels 36,40,44,48; indoor only */
1950
0
  case 116: /* channels 36,44; 40 MHz; indoor only */
1951
0
  case 117: /* channels 40,48; 40 MHz; indoor only */
1952
0
  case 118: /* channels 52,56,60,64; dfs */
1953
0
  case 119: /* channels 52,60; 40 MHz; dfs */
1954
0
  case 120: /* channels 56,64; 40 MHz; dfs */
1955
0
    if (chan < 36 || chan > 64)
1956
0
      return -1;
1957
0
    return 5000 + 5 * chan;
1958
0
  case 121: /* channels 100-144 */
1959
0
  case 122: /* channels 100-140; 40 MHz */
1960
0
  case 123: /* channels 104-144; 40 MHz */
1961
0
    if (chan < 100 || chan > 144)
1962
0
      return -1;
1963
0
    return 5000 + 5 * chan;
1964
0
  case 124: /* channels 149,153,157,161 */
1965
0
    if (chan < 149 || chan > 161)
1966
0
      return -1;
1967
0
    return 5000 + 5 * chan;
1968
0
  case 125: /* channels 149,153,157,161,165,169,173,177 */
1969
0
  case 126: /* channels 149,157,165,173; 40 MHz */
1970
0
  case 127: /* channels 153,161,169,177; 40 MHz */
1971
0
    if (chan < 149 || chan > 177)
1972
0
      return -1;
1973
0
    return 5000 + 5 * chan;
1974
0
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
1975
0
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
1976
0
    if (chan < 36 || chan > 177)
1977
0
      return -1;
1978
0
    return 5000 + 5 * chan;
1979
0
  case 129: /* center freqs 50, 114, 163; 160 MHz */
1980
0
    if (chan < 36 || chan > 177)
1981
0
      return -1;
1982
0
    return 5000 + 5 * chan;
1983
0
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
1984
0
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
1985
0
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
1986
0
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
1987
0
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
1988
0
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
1989
0
    if (chan < 1 || chan > 233)
1990
0
      return -1;
1991
0
    return 5950 + chan * 5;
1992
0
  case 136: /* UHB channels, 20 MHz: 2 */
1993
0
    if (chan == 2)
1994
0
      return 5935;
1995
0
    return -1;
1996
0
  case 180: /* 60 GHz band, channels 1..8 */
1997
0
    if (chan < 1 || chan > 8)
1998
0
      return -1;
1999
0
    return 56160 + 2160 * chan;
2000
0
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
2001
0
    if (chan < 9 || chan > 15)
2002
0
      return -1;
2003
0
    return 56160 + 2160 * (chan - 8);
2004
0
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
2005
0
    if (chan < 17 || chan > 22)
2006
0
      return -1;
2007
0
    return 56160 + 2160 * (chan - 16);
2008
0
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
2009
0
    if (chan < 25 || chan > 29)
2010
0
      return -1;
2011
0
    return 56160 + 2160 * (chan - 24);
2012
0
  default:
2013
0
    return -1;
2014
0
  }
2015
0
}
2016
2017
/**
2018
 * ieee80211_chan_to_freq - Convert channel info to frequency
2019
 * @country: Country code, if known; otherwise, global operating class is used
2020
 * @op_class: Operating class
2021
 * @chan: Channel number
2022
 * Returns: Frequency in MHz or -1 if the specified channel is unknown
2023
 */
2024
int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
2025
0
{
2026
0
  int freq;
2027
2028
0
  if (country_match(us_op_class_cc, country)) {
2029
0
    freq = ieee80211_chan_to_freq_us(op_class, chan);
2030
0
    if (freq > 0)
2031
0
      return freq;
2032
0
  }
2033
2034
0
  if (country_match(eu_op_class_cc, country)) {
2035
0
    freq = ieee80211_chan_to_freq_eu(op_class, chan);
2036
0
    if (freq > 0)
2037
0
      return freq;
2038
0
  }
2039
2040
0
  if (country_match(jp_op_class_cc, country)) {
2041
0
    freq = ieee80211_chan_to_freq_jp(op_class, chan);
2042
0
    if (freq > 0)
2043
0
      return freq;
2044
0
  }
2045
2046
0
  if (country_match(cn_op_class_cc, country)) {
2047
0
    freq = ieee80211_chan_to_freq_cn(op_class, chan);
2048
0
    if (freq > 0)
2049
0
      return freq;
2050
0
  }
2051
2052
0
  return ieee80211_chan_to_freq_global(op_class, chan);
2053
0
}
2054
2055
2056
int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
2057
         u16 num_modes)
2058
0
{
2059
0
  int i, j;
2060
2061
0
  if (!modes || !num_modes)
2062
0
    return (freq >= 5260 && freq <= 5320) ||
2063
0
      (freq >= 5500 && freq <= 5720);
2064
2065
0
  for (i = 0; i < num_modes; i++) {
2066
0
    for (j = 0; j < modes[i].num_channels; j++) {
2067
0
      if (modes[i].channels[j].freq == freq &&
2068
0
          (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR))
2069
0
        return 1;
2070
0
    }
2071
0
  }
2072
2073
0
  return 0;
2074
0
}
2075
2076
2077
/*
2078
 * 802.11-2020: Table E-4 - Global operating classes
2079
 * DFS_50_100_Behavior: 118, 119, 120, 121, 122, 123
2080
 */
2081
int is_dfs_global_op_class(u8 op_class)
2082
0
{
2083
0
    return (op_class >= 118) && (op_class <= 123);
2084
0
}
2085
2086
2087
bool is_80plus_op_class(u8 op_class)
2088
0
{
2089
  /* Operating classes with "80+" behavior indication in Table E-4 */
2090
0
  return op_class == 130 || op_class == 135;
2091
0
}
2092
2093
2094
static int is_11b(u8 rate)
2095
0
{
2096
0
  return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
2097
0
}
2098
2099
2100
int supp_rates_11b_only(struct ieee802_11_elems *elems)
2101
0
{
2102
0
  int num_11b = 0, num_others = 0;
2103
0
  int i;
2104
2105
0
  if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
2106
0
    return 0;
2107
2108
0
  for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
2109
0
    if (is_11b(elems->supp_rates[i]))
2110
0
      num_11b++;
2111
0
    else
2112
0
      num_others++;
2113
0
  }
2114
2115
0
  for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
2116
0
       i++) {
2117
0
    if (is_11b(elems->ext_supp_rates[i]))
2118
0
      num_11b++;
2119
0
    else
2120
0
      num_others++;
2121
0
  }
2122
2123
0
  return num_11b > 0 && num_others == 0;
2124
0
}
2125
2126
2127
const char * fc2str(u16 fc)
2128
0
{
2129
0
  u16 stype = WLAN_FC_GET_STYPE(fc);
2130
0
#define C2S(x) case x: return #x;
2131
2132
0
  switch (WLAN_FC_GET_TYPE(fc)) {
2133
0
  case WLAN_FC_TYPE_MGMT:
2134
0
    switch (stype) {
2135
0
    C2S(WLAN_FC_STYPE_ASSOC_REQ)
2136
0
    C2S(WLAN_FC_STYPE_ASSOC_RESP)
2137
0
    C2S(WLAN_FC_STYPE_REASSOC_REQ)
2138
0
    C2S(WLAN_FC_STYPE_REASSOC_RESP)
2139
0
    C2S(WLAN_FC_STYPE_PROBE_REQ)
2140
0
    C2S(WLAN_FC_STYPE_PROBE_RESP)
2141
0
    C2S(WLAN_FC_STYPE_BEACON)
2142
0
    C2S(WLAN_FC_STYPE_ATIM)
2143
0
    C2S(WLAN_FC_STYPE_DISASSOC)
2144
0
    C2S(WLAN_FC_STYPE_AUTH)
2145
0
    C2S(WLAN_FC_STYPE_DEAUTH)
2146
0
    C2S(WLAN_FC_STYPE_ACTION)
2147
0
    }
2148
0
    break;
2149
0
  case WLAN_FC_TYPE_CTRL:
2150
0
    switch (stype) {
2151
0
    C2S(WLAN_FC_STYPE_PSPOLL)
2152
0
    C2S(WLAN_FC_STYPE_RTS)
2153
0
    C2S(WLAN_FC_STYPE_CTS)
2154
0
    C2S(WLAN_FC_STYPE_ACK)
2155
0
    C2S(WLAN_FC_STYPE_CFEND)
2156
0
    C2S(WLAN_FC_STYPE_CFENDACK)
2157
0
    }
2158
0
    break;
2159
0
  case WLAN_FC_TYPE_DATA:
2160
0
    switch (stype) {
2161
0
    C2S(WLAN_FC_STYPE_DATA)
2162
0
    C2S(WLAN_FC_STYPE_DATA_CFACK)
2163
0
    C2S(WLAN_FC_STYPE_DATA_CFPOLL)
2164
0
    C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
2165
0
    C2S(WLAN_FC_STYPE_NULLFUNC)
2166
0
    C2S(WLAN_FC_STYPE_CFACK)
2167
0
    C2S(WLAN_FC_STYPE_CFPOLL)
2168
0
    C2S(WLAN_FC_STYPE_CFACKPOLL)
2169
0
    C2S(WLAN_FC_STYPE_QOS_DATA)
2170
0
    C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
2171
0
    C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
2172
0
    C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
2173
0
    C2S(WLAN_FC_STYPE_QOS_NULL)
2174
0
    C2S(WLAN_FC_STYPE_QOS_CFPOLL)
2175
0
    C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
2176
0
    }
2177
0
    break;
2178
0
  }
2179
0
  return "WLAN_FC_TYPE_UNKNOWN";
2180
0
#undef C2S
2181
0
}
2182
2183
2184
const char * reason2str(u16 reason)
2185
0
{
2186
0
#define R2S(r) case WLAN_REASON_ ## r: return #r;
2187
0
  switch (reason) {
2188
0
  R2S(UNSPECIFIED)
2189
0
  R2S(PREV_AUTH_NOT_VALID)
2190
0
  R2S(DEAUTH_LEAVING)
2191
0
  R2S(DISASSOC_DUE_TO_INACTIVITY)
2192
0
  R2S(DISASSOC_AP_BUSY)
2193
0
  R2S(CLASS2_FRAME_FROM_NONAUTH_STA)
2194
0
  R2S(CLASS3_FRAME_FROM_NONASSOC_STA)
2195
0
  R2S(DISASSOC_STA_HAS_LEFT)
2196
0
  R2S(STA_REQ_ASSOC_WITHOUT_AUTH)
2197
0
  R2S(PWR_CAPABILITY_NOT_VALID)
2198
0
  R2S(SUPPORTED_CHANNEL_NOT_VALID)
2199
0
  R2S(BSS_TRANSITION_DISASSOC)
2200
0
  R2S(INVALID_IE)
2201
0
  R2S(MICHAEL_MIC_FAILURE)
2202
0
  R2S(4WAY_HANDSHAKE_TIMEOUT)
2203
0
  R2S(GROUP_KEY_UPDATE_TIMEOUT)
2204
0
  R2S(IE_IN_4WAY_DIFFERS)
2205
0
  R2S(GROUP_CIPHER_NOT_VALID)
2206
0
  R2S(PAIRWISE_CIPHER_NOT_VALID)
2207
0
  R2S(AKMP_NOT_VALID)
2208
0
  R2S(UNSUPPORTED_RSN_IE_VERSION)
2209
0
  R2S(INVALID_RSN_IE_CAPAB)
2210
0
  R2S(IEEE_802_1X_AUTH_FAILED)
2211
0
  R2S(CIPHER_SUITE_REJECTED)
2212
0
  R2S(TDLS_TEARDOWN_UNREACHABLE)
2213
0
  R2S(TDLS_TEARDOWN_UNSPECIFIED)
2214
0
  R2S(SSP_REQUESTED_DISASSOC)
2215
0
  R2S(NO_SSP_ROAMING_AGREEMENT)
2216
0
  R2S(BAD_CIPHER_OR_AKM)
2217
0
  R2S(NOT_AUTHORIZED_THIS_LOCATION)
2218
0
  R2S(SERVICE_CHANGE_PRECLUDES_TS)
2219
0
  R2S(UNSPECIFIED_QOS_REASON)
2220
0
  R2S(NOT_ENOUGH_BANDWIDTH)
2221
0
  R2S(DISASSOC_LOW_ACK)
2222
0
  R2S(EXCEEDED_TXOP)
2223
0
  R2S(STA_LEAVING)
2224
0
  R2S(END_TS_BA_DLS)
2225
0
  R2S(UNKNOWN_TS_BA)
2226
0
  R2S(TIMEOUT)
2227
0
  R2S(PEERKEY_MISMATCH)
2228
0
  R2S(AUTHORIZED_ACCESS_LIMIT_REACHED)
2229
0
  R2S(EXTERNAL_SERVICE_REQUIREMENTS)
2230
0
  R2S(INVALID_FT_ACTION_FRAME_COUNT)
2231
0
  R2S(INVALID_PMKID)
2232
0
  R2S(INVALID_MDE)
2233
0
  R2S(INVALID_FTE)
2234
0
  R2S(MESH_PEERING_CANCELLED)
2235
0
  R2S(MESH_MAX_PEERS)
2236
0
  R2S(MESH_CONFIG_POLICY_VIOLATION)
2237
0
  R2S(MESH_CLOSE_RCVD)
2238
0
  R2S(MESH_MAX_RETRIES)
2239
0
  R2S(MESH_CONFIRM_TIMEOUT)
2240
0
  R2S(MESH_INVALID_GTK)
2241
0
  R2S(MESH_INCONSISTENT_PARAMS)
2242
0
  R2S(MESH_INVALID_SECURITY_CAP)
2243
0
  R2S(MESH_PATH_ERROR_NO_PROXY_INFO)
2244
0
  R2S(MESH_PATH_ERROR_NO_FORWARDING_INFO)
2245
0
  R2S(MESH_PATH_ERROR_DEST_UNREACHABLE)
2246
0
  R2S(MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS)
2247
0
  R2S(MESH_CHANNEL_SWITCH_REGULATORY_REQ)
2248
0
  R2S(MESH_CHANNEL_SWITCH_UNSPECIFIED)
2249
0
  }
2250
0
  return "UNKNOWN";
2251
0
#undef R2S
2252
0
}
2253
2254
2255
const char * status2str(u16 status)
2256
0
{
2257
0
#define S2S(s) case WLAN_STATUS_ ## s: return #s;
2258
0
  switch (status) {
2259
0
  S2S(SUCCESS)
2260
0
  S2S(UNSPECIFIED_FAILURE)
2261
0
  S2S(TDLS_WAKEUP_ALTERNATE)
2262
0
  S2S(TDLS_WAKEUP_REJECT)
2263
0
  S2S(SECURITY_DISABLED)
2264
0
  S2S(UNACCEPTABLE_LIFETIME)
2265
0
  S2S(NOT_IN_SAME_BSS)
2266
0
  S2S(CAPS_UNSUPPORTED)
2267
0
  S2S(REASSOC_NO_ASSOC)
2268
0
  S2S(ASSOC_DENIED_UNSPEC)
2269
0
  S2S(NOT_SUPPORTED_AUTH_ALG)
2270
0
  S2S(UNKNOWN_AUTH_TRANSACTION)
2271
0
  S2S(CHALLENGE_FAIL)
2272
0
  S2S(AUTH_TIMEOUT)
2273
0
  S2S(AP_UNABLE_TO_HANDLE_NEW_STA)
2274
0
  S2S(ASSOC_DENIED_RATES)
2275
0
  S2S(ASSOC_DENIED_NOSHORT)
2276
0
  S2S(SPEC_MGMT_REQUIRED)
2277
0
  S2S(PWR_CAPABILITY_NOT_VALID)
2278
0
  S2S(SUPPORTED_CHANNEL_NOT_VALID)
2279
0
  S2S(ASSOC_DENIED_NO_SHORT_SLOT_TIME)
2280
0
  S2S(ASSOC_DENIED_NO_HT)
2281
0
  S2S(R0KH_UNREACHABLE)
2282
0
  S2S(ASSOC_DENIED_NO_PCO)
2283
0
  S2S(ASSOC_REJECTED_TEMPORARILY)
2284
0
  S2S(ROBUST_MGMT_FRAME_POLICY_VIOLATION)
2285
0
  S2S(UNSPECIFIED_QOS_FAILURE)
2286
0
  S2S(DENIED_INSUFFICIENT_BANDWIDTH)
2287
0
  S2S(DENIED_POOR_CHANNEL_CONDITIONS)
2288
0
  S2S(DENIED_QOS_NOT_SUPPORTED)
2289
0
  S2S(REQUEST_DECLINED)
2290
0
  S2S(INVALID_PARAMETERS)
2291
0
  S2S(REJECTED_WITH_SUGGESTED_CHANGES)
2292
0
  S2S(INVALID_IE)
2293
0
  S2S(GROUP_CIPHER_NOT_VALID)
2294
0
  S2S(PAIRWISE_CIPHER_NOT_VALID)
2295
0
  S2S(AKMP_NOT_VALID)
2296
0
  S2S(UNSUPPORTED_RSN_IE_VERSION)
2297
0
  S2S(INVALID_RSN_IE_CAPAB)
2298
0
  S2S(CIPHER_REJECTED_PER_POLICY)
2299
0
  S2S(TS_NOT_CREATED)
2300
0
  S2S(DIRECT_LINK_NOT_ALLOWED)
2301
0
  S2S(DEST_STA_NOT_PRESENT)
2302
0
  S2S(DEST_STA_NOT_QOS_STA)
2303
0
  S2S(ASSOC_DENIED_LISTEN_INT_TOO_LARGE)
2304
0
  S2S(INVALID_FT_ACTION_FRAME_COUNT)
2305
0
  S2S(INVALID_PMKID)
2306
0
  S2S(INVALID_MDIE)
2307
0
  S2S(INVALID_FTIE)
2308
0
  S2S(REQUESTED_TCLAS_NOT_SUPPORTED)
2309
0
  S2S(INSUFFICIENT_TCLAS_PROCESSING_RESOURCES)
2310
0
  S2S(TRY_ANOTHER_BSS)
2311
0
  S2S(GAS_ADV_PROTO_NOT_SUPPORTED)
2312
0
  S2S(NO_OUTSTANDING_GAS_REQ)
2313
0
  S2S(GAS_RESP_NOT_RECEIVED)
2314
0
  S2S(STA_TIMED_OUT_WAITING_FOR_GAS_RESP)
2315
0
  S2S(GAS_RESP_LARGER_THAN_LIMIT)
2316
0
  S2S(REQ_REFUSED_HOME)
2317
0
  S2S(ADV_SRV_UNREACHABLE)
2318
0
  S2S(REQ_REFUSED_SSPN)
2319
0
  S2S(REQ_REFUSED_UNAUTH_ACCESS)
2320
0
  S2S(INVALID_RSNIE)
2321
0
  S2S(U_APSD_COEX_NOT_SUPPORTED)
2322
0
  S2S(U_APSD_COEX_MODE_NOT_SUPPORTED)
2323
0
  S2S(BAD_INTERVAL_WITH_U_APSD_COEX)
2324
0
  S2S(ANTI_CLOGGING_TOKEN_REQ)
2325
0
  S2S(FINITE_CYCLIC_GROUP_NOT_SUPPORTED)
2326
0
  S2S(CANNOT_FIND_ALT_TBTT)
2327
0
  S2S(TRANSMISSION_FAILURE)
2328
0
  S2S(REQ_TCLAS_NOT_SUPPORTED)
2329
0
  S2S(TCLAS_RESOURCES_EXCHAUSTED)
2330
0
  S2S(REJECTED_WITH_SUGGESTED_BSS_TRANSITION)
2331
0
  S2S(REJECT_WITH_SCHEDULE)
2332
0
  S2S(REJECT_NO_WAKEUP_SPECIFIED)
2333
0
  S2S(SUCCESS_POWER_SAVE_MODE)
2334
0
  S2S(PENDING_ADMITTING_FST_SESSION)
2335
0
  S2S(PERFORMING_FST_NOW)
2336
0
  S2S(PENDING_GAP_IN_BA_WINDOW)
2337
0
  S2S(REJECT_U_PID_SETTING)
2338
0
  S2S(REFUSED_EXTERNAL_REASON)
2339
0
  S2S(REFUSED_AP_OUT_OF_MEMORY)
2340
0
  S2S(REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED)
2341
0
  S2S(QUERY_RESP_OUTSTANDING)
2342
0
  S2S(REJECT_DSE_BAND)
2343
0
  S2S(TCLAS_PROCESSING_TERMINATED)
2344
0
  S2S(TS_SCHEDULE_CONFLICT)
2345
0
  S2S(DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL)
2346
0
  S2S(MCCAOP_RESERVATION_CONFLICT)
2347
0
  S2S(MAF_LIMIT_EXCEEDED)
2348
0
  S2S(MCCA_TRACK_LIMIT_EXCEEDED)
2349
0
  S2S(DENIED_DUE_TO_SPECTRUM_MANAGEMENT)
2350
0
  S2S(ASSOC_DENIED_NO_VHT)
2351
0
  S2S(ENABLEMENT_DENIED)
2352
0
  S2S(RESTRICTION_FROM_AUTHORIZED_GDB)
2353
0
  S2S(AUTHORIZATION_DEENABLED)
2354
0
  S2S(FILS_AUTHENTICATION_FAILURE)
2355
0
  S2S(UNKNOWN_AUTHENTICATION_SERVER)
2356
0
  S2S(UNKNOWN_PASSWORD_IDENTIFIER)
2357
0
  S2S(DENIED_HE_NOT_SUPPORTED)
2358
0
  S2S(SAE_HASH_TO_ELEMENT)
2359
0
  S2S(SAE_PK)
2360
0
  S2S(INVALID_PUBLIC_KEY)
2361
0
  S2S(PASN_BASE_AKMP_FAILED)
2362
0
  S2S(OCI_MISMATCH)
2363
0
  }
2364
0
  return "UNKNOWN";
2365
0
#undef S2S
2366
0
}
2367
2368
2369
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
2370
           size_t ies_len)
2371
0
{
2372
0
  const struct element *elem;
2373
2374
0
  os_memset(info, 0, sizeof(*info));
2375
2376
0
  if (!ies_buf)
2377
0
    return 0;
2378
2379
0
  for_each_element_id(elem, WLAN_EID_MULTI_BAND, ies_buf, ies_len) {
2380
0
    if (info->nof_ies >= MAX_NOF_MB_IES_SUPPORTED)
2381
0
      return 0;
2382
2383
0
    wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
2384
0
         elem->datalen + 2);
2385
0
    info->ies[info->nof_ies].ie = elem->data;
2386
0
    info->ies[info->nof_ies].ie_len = elem->datalen;
2387
0
    info->nof_ies++;
2388
0
  }
2389
2390
0
  if (!for_each_element_completed(elem, ies_buf, ies_len)) {
2391
0
    wpa_hexdump(MSG_DEBUG, "Truncated IEs", ies_buf, ies_len);
2392
0
    return -1;
2393
0
  }
2394
2395
0
  return 0;
2396
0
}
2397
2398
2399
struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
2400
0
{
2401
0
  struct wpabuf *mb_ies = NULL;
2402
2403
0
  WPA_ASSERT(info != NULL);
2404
2405
0
  if (info->nof_ies) {
2406
0
    u8 i;
2407
0
    size_t mb_ies_size = 0;
2408
2409
0
    for (i = 0; i < info->nof_ies; i++)
2410
0
      mb_ies_size += 2 + info->ies[i].ie_len;
2411
2412
0
    mb_ies = wpabuf_alloc(mb_ies_size);
2413
0
    if (mb_ies) {
2414
0
      for (i = 0; i < info->nof_ies; i++) {
2415
0
        wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
2416
0
        wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
2417
0
        wpabuf_put_data(mb_ies,
2418
0
            info->ies[i].ie,
2419
0
            info->ies[i].ie_len);
2420
0
      }
2421
0
    }
2422
0
  }
2423
2424
0
  return mb_ies;
2425
0
}
2426
2427
2428
const struct oper_class_map global_op_class[] = {
2429
  { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
2430
  { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
2431
2432
  /* Do not enable HT40 on 2.4 GHz for P2P use for now */
2433
  { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
2434
  { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
2435
2436
  { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
2437
  { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
2438
  { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
2439
  { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
2440
  { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
2441
  { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
2442
  { HOSTAPD_MODE_IEEE80211A, 121, 100, 144, 4, BW20, NO_P2P_SUPP },
2443
  { HOSTAPD_MODE_IEEE80211A, 122, 100, 140, 8, BW40PLUS, NO_P2P_SUPP },
2444
  { HOSTAPD_MODE_IEEE80211A, 123, 104, 144, 8, BW40MINUS, NO_P2P_SUPP },
2445
  { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
2446
  { HOSTAPD_MODE_IEEE80211A, 125, 149, 177, 4, BW20, P2P_SUPP },
2447
  { HOSTAPD_MODE_IEEE80211A, 126, 149, 173, 8, BW40PLUS, P2P_SUPP },
2448
  { HOSTAPD_MODE_IEEE80211A, 127, 153, 177, 8, BW40MINUS, P2P_SUPP },
2449
2450
  /*
2451
   * IEEE Std 802.11ax-2021, Table E-4 actually talks about channel center
2452
   * frequency index for operation classes 128, 129, 130, 132, 133, 134,
2453
   * and 135, but currently use the lowest 20 MHz channel for simplicity
2454
   * (these center frequencies are not actual channels, which makes
2455
   * wpas_p2p_verify_channel() fail).
2456
   * Specially for the operation class 136, it is also defined to use the
2457
   * channel center frequency index value, but it happens to be a 20 MHz
2458
   * channel and the channel number in the channel set would match the
2459
   * value in for the frequency center.
2460
   *
2461
   * Operating class value pair 128 and 130 is used to describe a 80+80
2462
   * MHz channel on the 5 GHz band. 130 is identified with "80+", so this
2463
   * is encoded with two octets 130 and 128. Similarly, operating class
2464
   * value pair 133 and 135 is used to describe a 80+80 MHz channel on
2465
   * the 6 GHz band (135 being the one with "80+" indication). All other
2466
   * operating classes listed here are used as 1-octet values.
2467
   */
2468
  { HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
2469
  { HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
2470
  { HOSTAPD_MODE_IEEE80211A, 130, 36, 177, 4, BW80P80, P2P_SUPP },
2471
  { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
2472
  { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
2473
  { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
2474
  { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, P2P_SUPP },
2475
  { HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
2476
  { HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
2477
2478
  /* IEEE P802.11be/D5.0, Table E-4 (Global operating classes) */
2479
  { HOSTAPD_MODE_IEEE80211A, 137, 31, 191, 32, BW320, NO_P2P_SUPP },
2480
2481
  /*
2482
   * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
2483
   * Class 180 has the legacy channels 1-6. Classes 181-183 include
2484
   * channels which implement channel bonding features.
2485
   */
2486
  { HOSTAPD_MODE_IEEE80211AD, 180, 1, 6, 1, BW2160, P2P_SUPP },
2487
  { HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP },
2488
  { HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
2489
  { HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
2490
2491
  { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
2492
};
2493
2494
2495
static enum phy_type ieee80211_phy_type_by_freq(int freq)
2496
0
{
2497
0
  enum hostapd_hw_mode hw_mode;
2498
0
  u8 channel;
2499
2500
0
  hw_mode = ieee80211_freq_to_chan(freq, &channel);
2501
2502
0
  switch (hw_mode) {
2503
0
  case HOSTAPD_MODE_IEEE80211A:
2504
0
    return PHY_TYPE_OFDM;
2505
0
  case HOSTAPD_MODE_IEEE80211B:
2506
0
    return PHY_TYPE_HRDSSS;
2507
0
  case HOSTAPD_MODE_IEEE80211G:
2508
0
    return PHY_TYPE_ERP;
2509
0
  case HOSTAPD_MODE_IEEE80211AD:
2510
0
    return PHY_TYPE_DMG;
2511
0
  default:
2512
0
    return PHY_TYPE_UNSPECIFIED;
2513
0
  };
2514
0
}
2515
2516
2517
/* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
2518
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
2519
0
{
2520
0
  if (vht)
2521
0
    return PHY_TYPE_VHT;
2522
0
  if (ht)
2523
0
    return PHY_TYPE_HT;
2524
2525
0
  return ieee80211_phy_type_by_freq(freq);
2526
0
}
2527
2528
2529
size_t global_op_class_size = ARRAY_SIZE(global_op_class);
2530
2531
2532
/**
2533
 * get_ie - Fetch a specified information element from IEs buffer
2534
 * @ies: Information elements buffer
2535
 * @len: Information elements buffer length
2536
 * @eid: Information element identifier (WLAN_EID_*)
2537
 * Returns: Pointer to the information element (id field) or %NULL if not found
2538
 *
2539
 * This function returns the first matching information element in the IEs
2540
 * buffer or %NULL in case the element is not found.
2541
 */
2542
const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
2543
0
{
2544
0
  const struct element *elem;
2545
2546
0
  if (!ies)
2547
0
    return NULL;
2548
2549
0
  for_each_element_id(elem, eid, ies, len)
2550
0
    return &elem->id;
2551
2552
0
  return NULL;
2553
0
}
2554
2555
2556
/**
2557
 * get_ie_ext - Fetch a specified extended information element from IEs buffer
2558
 * @ies: Information elements buffer
2559
 * @len: Information elements buffer length
2560
 * @ext: Information element extension identifier (WLAN_EID_EXT_*)
2561
 * Returns: Pointer to the information element (id field) or %NULL if not found
2562
 *
2563
 * This function returns the first matching information element in the IEs
2564
 * buffer or %NULL in case the element is not found.
2565
 */
2566
const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext)
2567
0
{
2568
0
  const struct element *elem;
2569
2570
0
  if (!ies)
2571
0
    return NULL;
2572
2573
0
  for_each_element_extid(elem, ext, ies, len)
2574
0
    return &elem->id;
2575
2576
0
  return NULL;
2577
0
}
2578
2579
2580
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type)
2581
0
{
2582
0
  const struct element *elem;
2583
2584
0
  if (!ies)
2585
0
    return NULL;
2586
2587
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, len) {
2588
0
    if (elem->datalen >= 4 &&
2589
0
        vendor_type == WPA_GET_BE32(elem->data))
2590
0
      return &elem->id;
2591
0
  }
2592
2593
0
  return NULL;
2594
0
}
2595
2596
2597
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
2598
0
{
2599
  /*
2600
   * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
2601
   * OUI (3), OUI type (1).
2602
   */
2603
0
  if (len < 6 + attr_len) {
2604
0
    wpa_printf(MSG_DEBUG,
2605
0
         "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
2606
0
         len, attr_len);
2607
0
    return 0;
2608
0
  }
2609
2610
0
  *buf++ = WLAN_EID_VENDOR_SPECIFIC;
2611
0
  *buf++ = attr_len + 4;
2612
0
  WPA_PUT_BE24(buf, OUI_WFA);
2613
0
  buf += 3;
2614
0
  *buf++ = MBO_OUI_TYPE;
2615
0
  os_memcpy(buf, attr, attr_len);
2616
2617
0
  return 6 + attr_len;
2618
0
}
2619
2620
2621
u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len,
2622
          struct multi_ap_params *multi_ap)
2623
0
{
2624
0
  const struct element *elem;
2625
0
  bool ext_present = false;
2626
0
  unsigned int vlan_id;
2627
2628
0
  os_memset(multi_ap, 0, sizeof(*multi_ap));
2629
2630
  /* Default profile is 1, when Multi-AP profile subelement is not
2631
   * present in the element. */
2632
0
  multi_ap->profile = 1;
2633
2634
0
  for_each_element(elem, multi_ap_ie, multi_ap_len) {
2635
0
    u8 id = elem->id, elen = elem->datalen;
2636
0
    const u8 *pos = elem->data;
2637
2638
0
    switch (id) {
2639
0
    case MULTI_AP_SUB_ELEM_TYPE:
2640
0
      if (elen >= 1) {
2641
0
        multi_ap->capability = *pos;
2642
0
        ext_present = true;
2643
0
      } else {
2644
0
        wpa_printf(MSG_DEBUG,
2645
0
             "Multi-AP invalid Multi-AP subelement");
2646
0
        return WLAN_STATUS_INVALID_IE;
2647
0
      }
2648
0
      break;
2649
0
    case MULTI_AP_PROFILE_SUB_ELEM_TYPE:
2650
0
      if (elen < 1) {
2651
0
        wpa_printf(MSG_DEBUG,
2652
0
             "Multi-AP IE invalid Multi-AP profile subelement");
2653
0
        return WLAN_STATUS_INVALID_IE;
2654
0
      }
2655
2656
0
      multi_ap->profile = *pos;
2657
0
      if (multi_ap->profile > MULTI_AP_PROFILE_MAX) {
2658
0
        wpa_printf(MSG_DEBUG,
2659
0
             "Multi-AP IE with invalid profile 0x%02x",
2660
0
             multi_ap->profile);
2661
0
        return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
2662
0
      }
2663
0
      break;
2664
0
    case MULTI_AP_VLAN_SUB_ELEM_TYPE:
2665
0
      if (multi_ap->profile < MULTI_AP_PROFILE_2) {
2666
0
        wpa_printf(MSG_DEBUG,
2667
0
             "Multi-AP IE invalid profile to read VLAN IE");
2668
0
        return WLAN_STATUS_INVALID_IE;
2669
0
      }
2670
0
      if (elen < 2) {
2671
0
        wpa_printf(MSG_DEBUG,
2672
0
             "Multi-AP IE invalid Multi-AP VLAN subelement");
2673
0
        return WLAN_STATUS_INVALID_IE;
2674
0
      }
2675
2676
0
      vlan_id = WPA_GET_LE16(pos);
2677
0
      if (vlan_id < 1 || vlan_id > 4094) {
2678
0
        wpa_printf(MSG_INFO,
2679
0
             "Multi-AP IE invalid Multi-AP VLAN ID %d",
2680
0
             vlan_id);
2681
0
        return WLAN_STATUS_INVALID_IE;
2682
0
      }
2683
0
      multi_ap->vlanid = vlan_id;
2684
0
      break;
2685
0
    default:
2686
0
      wpa_printf(MSG_DEBUG,
2687
0
           "Ignore unknown subelement %u in Multi-AP IE",
2688
0
           id);
2689
0
      break;
2690
0
    }
2691
0
  }
2692
2693
0
  if (!for_each_element_completed(elem, multi_ap_ie, multi_ap_len)) {
2694
0
    wpa_printf(MSG_DEBUG, "Multi AP IE parse failed @%d",
2695
0
         (int) (multi_ap_ie + multi_ap_len -
2696
0
          (const u8 *) elem));
2697
0
    wpa_hexdump(MSG_MSGDUMP, "IEs", multi_ap_ie, multi_ap_len);
2698
0
  }
2699
2700
0
  if (!ext_present) {
2701
0
    wpa_printf(MSG_DEBUG,
2702
0
         "Multi-AP element without Multi-AP Extension subelement");
2703
0
    return WLAN_STATUS_INVALID_IE;
2704
0
  }
2705
2706
0
  return WLAN_STATUS_SUCCESS;
2707
0
}
2708
2709
2710
size_t add_multi_ap_ie(u8 *buf, size_t len,
2711
           const struct multi_ap_params *multi_ap)
2712
0
{
2713
0
  u8 *pos = buf;
2714
0
  u8 *len_ptr;
2715
2716
0
  if (len < 6)
2717
0
    return 0;
2718
2719
0
  *pos++ = WLAN_EID_VENDOR_SPECIFIC;
2720
0
  len_ptr = pos; /* Length field to be set at the end */
2721
0
  pos++;
2722
0
  WPA_PUT_BE24(pos, OUI_WFA);
2723
0
  pos += 3;
2724
0
  *pos++ = MULTI_AP_OUI_TYPE;
2725
2726
  /* Multi-AP Extension subelement */
2727
0
  if (buf + len - pos < 3)
2728
0
    return 0;
2729
0
  *pos++ = MULTI_AP_SUB_ELEM_TYPE;
2730
0
  *pos++ = 1; /* len */
2731
0
  *pos++ = multi_ap->capability;
2732
2733
  /* Add Multi-AP Profile subelement only for R2 or newer configuration */
2734
0
  if (multi_ap->profile >= MULTI_AP_PROFILE_2) {
2735
0
    if (buf + len - pos < 3)
2736
0
      return 0;
2737
0
    *pos++ = MULTI_AP_PROFILE_SUB_ELEM_TYPE;
2738
0
    *pos++ = 1;
2739
0
    *pos++ = multi_ap->profile;
2740
0
  }
2741
2742
  /* Add Multi-AP Default 802.1Q Setting subelement only for backhaul BSS
2743
   */
2744
0
  if (multi_ap->vlanid &&
2745
0
      multi_ap->profile >= MULTI_AP_PROFILE_2 &&
2746
0
      (multi_ap->capability & MULTI_AP_BACKHAUL_BSS)) {
2747
0
    if (buf + len - pos < 4)
2748
0
      return 0;
2749
0
    *pos++ = MULTI_AP_VLAN_SUB_ELEM_TYPE;
2750
0
    *pos++ = 2;
2751
0
    WPA_PUT_LE16(pos, multi_ap->vlanid);
2752
0
    pos += 2;
2753
0
  }
2754
2755
0
  *len_ptr = pos - len_ptr - 1;
2756
2757
0
  return pos - buf;
2758
0
}
2759
2760
2761
static const struct country_op_class us_op_class[] = {
2762
  { 1, 115 },
2763
  { 2, 118 },
2764
  { 3, 124 },
2765
  { 4, 121 },
2766
  { 5, 125 },
2767
  { 12, 81 },
2768
  { 22, 116 },
2769
  { 23, 119 },
2770
  { 24, 122 },
2771
  { 25, 126 },
2772
  { 26, 126 },
2773
  { 27, 117 },
2774
  { 28, 120 },
2775
  { 29, 123 },
2776
  { 30, 127 },
2777
  { 31, 127 },
2778
  { 32, 83 },
2779
  { 33, 84 },
2780
  { 34, 180 },
2781
};
2782
2783
static const struct country_op_class eu_op_class[] = {
2784
  { 1, 115 },
2785
  { 2, 118 },
2786
  { 3, 121 },
2787
  { 4, 81 },
2788
  { 5, 116 },
2789
  { 6, 119 },
2790
  { 7, 122 },
2791
  { 8, 117 },
2792
  { 9, 120 },
2793
  { 10, 123 },
2794
  { 11, 83 },
2795
  { 12, 84 },
2796
  { 17, 125 },
2797
  { 18, 180 },
2798
};
2799
2800
static const struct country_op_class jp_op_class[] = {
2801
  { 1, 115 },
2802
  { 30, 81 },
2803
  { 31, 82 },
2804
  { 32, 118 },
2805
  { 33, 118 },
2806
  { 34, 121 },
2807
  { 35, 121 },
2808
  { 36, 116 },
2809
  { 37, 119 },
2810
  { 38, 119 },
2811
  { 39, 122 },
2812
  { 40, 122 },
2813
  { 41, 117 },
2814
  { 42, 120 },
2815
  { 43, 120 },
2816
  { 44, 123 },
2817
  { 45, 123 },
2818
  { 56, 83 },
2819
  { 57, 84 },
2820
  { 58, 121 },
2821
  { 59, 180 },
2822
};
2823
2824
static const struct country_op_class cn_op_class[] = {
2825
  { 1, 115 },
2826
  { 2, 118 },
2827
  { 3, 125 },
2828
  { 4, 116 },
2829
  { 5, 119 },
2830
  { 6, 126 },
2831
  { 7, 81 },
2832
  { 8, 83 },
2833
  { 9, 84 },
2834
};
2835
2836
static u8
2837
global_op_class_from_country_array(u8 op_class, size_t array_size,
2838
           const struct country_op_class *country_array)
2839
0
{
2840
0
  size_t i;
2841
2842
0
  for (i = 0; i < array_size; i++) {
2843
0
    if (country_array[i].country_op_class == op_class)
2844
0
      return country_array[i].global_op_class;
2845
0
  }
2846
2847
0
  return 0;
2848
0
}
2849
2850
2851
u8 country_to_global_op_class(const char *country, u8 op_class)
2852
0
{
2853
0
  const struct country_op_class *country_array;
2854
0
  size_t size;
2855
0
  u8 g_op_class;
2856
2857
0
  if (country_match(us_op_class_cc, country)) {
2858
0
    country_array = us_op_class;
2859
0
    size = ARRAY_SIZE(us_op_class);
2860
0
  } else if (country_match(eu_op_class_cc, country)) {
2861
0
    country_array = eu_op_class;
2862
0
    size = ARRAY_SIZE(eu_op_class);
2863
0
  } else if (country_match(jp_op_class_cc, country)) {
2864
0
    country_array = jp_op_class;
2865
0
    size = ARRAY_SIZE(jp_op_class);
2866
0
  } else if (country_match(cn_op_class_cc, country)) {
2867
0
    country_array = cn_op_class;
2868
0
    size = ARRAY_SIZE(cn_op_class);
2869
0
  } else {
2870
    /*
2871
     * Countries that do not match any of the above countries use
2872
     * global operating classes
2873
     */
2874
0
    return op_class;
2875
0
  }
2876
2877
0
  g_op_class = global_op_class_from_country_array(op_class, size,
2878
0
              country_array);
2879
2880
  /*
2881
   * If the given operating class did not match any of the country's
2882
   * operating classes, assume that global operating class is used.
2883
   */
2884
0
  return g_op_class ? g_op_class : op_class;
2885
0
}
2886
2887
2888
const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
2889
0
{
2890
0
  const struct oper_class_map *op;
2891
2892
0
  if (country)
2893
0
    op_class = country_to_global_op_class(country, op_class);
2894
2895
0
  op = &global_op_class[0];
2896
0
  while (op->op_class && op->op_class != op_class)
2897
0
    op++;
2898
2899
0
  if (!op->op_class)
2900
0
    return NULL;
2901
2902
0
  return op;
2903
0
}
2904
2905
2906
int oper_class_bw_to_int(const struct oper_class_map *map)
2907
0
{
2908
0
  switch (map->bw) {
2909
0
  case BW20:
2910
0
    return 20;
2911
0
  case BW40:
2912
0
  case BW40PLUS:
2913
0
  case BW40MINUS:
2914
0
    return 40;
2915
0
  case BW80:
2916
0
    return 80;
2917
0
  case BW80P80:
2918
0
  case BW160:
2919
0
    return 160;
2920
0
  case BW320:
2921
0
    return 320;
2922
0
  case BW2160:
2923
0
    return 2160;
2924
0
  default:
2925
0
    return 0;
2926
0
  }
2927
0
}
2928
2929
2930
int center_idx_to_bw_6ghz(u8 idx)
2931
0
{
2932
  /* Channel: 2 */
2933
0
  if (idx == 2)
2934
0
    return 0; /* 20 MHz */
2935
  /* channels: 1, 5, 9, 13... */
2936
0
  if ((idx & 0x3) == 0x1)
2937
0
    return 0; /* 20 MHz */
2938
  /* channels 3, 11, 19... */
2939
0
  if ((idx & 0x7) == 0x3)
2940
0
    return 1; /* 40 MHz */
2941
  /* channels 7, 23, 39.. */
2942
0
  if ((idx & 0xf) == 0x7)
2943
0
    return 2; /* 80 MHz */
2944
  /* channels 15, 47, 79...*/
2945
0
  if ((idx & 0x1f) == 0xf)
2946
0
    return 3; /* 160 MHz */
2947
  /* channels 31, 63, 95, 127, 159, 191 */
2948
0
  if ((idx & 0x1f) == 0x1f && idx < 192)
2949
0
    return 4; /* 320 MHz */
2950
2951
0
  return -1;
2952
0
}
2953
2954
2955
bool is_6ghz_freq(int freq)
2956
0
{
2957
0
  if (freq < 5935 || freq > 7115)
2958
0
    return false;
2959
2960
0
  if (freq == 5935)
2961
0
    return true;
2962
2963
0
  if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0)
2964
0
    return false;
2965
2966
0
  return true;
2967
0
}
2968
2969
2970
bool is_6ghz_op_class(u8 op_class)
2971
0
{
2972
0
  return op_class >= 131 && op_class <= 137;
2973
0
}
2974
2975
2976
bool is_6ghz_psc_frequency(int freq)
2977
0
{
2978
0
  int i;
2979
2980
0
  if (!is_6ghz_freq(freq) || freq == 5935)
2981
0
    return false;
2982
0
  if ((((freq - 5950) / 5) & 0x3) != 0x1)
2983
0
    return false;
2984
2985
0
  i = (freq - 5950 + 55) % 80;
2986
0
  if (i == 0)
2987
0
    i = (freq - 5950 + 55) / 80;
2988
2989
0
  if (i >= 1 && i <= 15)
2990
0
    return true;
2991
2992
0
  return false;
2993
0
}
2994
2995
2996
/**
2997
 * get_6ghz_sec_channel - Get the relative position of the secondary channel
2998
 * to the primary channel in 6 GHz
2999
 * @channel: Primary channel to be checked for (in global op class 131)
3000
 * Returns: 1 = secondary channel above, -1 = secondary channel below
3001
 */
3002
3003
int get_6ghz_sec_channel(int channel)
3004
0
{
3005
  /*
3006
   * In the 6 GHz band, primary channels are numbered as 1, 5, 9, 13.., so
3007
   * the 40 MHz channels are formed with the channel pairs as (1,5),
3008
   * (9,13), (17,21)..
3009
   * The secondary channel for a given primary channel is below the
3010
   * primary channel for the channels 5, 13, 21.. and it is above the
3011
   * primary channel for the channels 1, 9, 17..
3012
   */
3013
3014
0
  if (((channel - 1) / 4) % 2)
3015
0
    return -1;
3016
0
  return 1;
3017
0
}
3018
3019
3020
bool is_same_band(int freq1, int freq2)
3021
0
{
3022
0
  if (IS_2P4GHZ(freq1) && IS_2P4GHZ(freq2))
3023
0
    return true;
3024
3025
0
  if (IS_5GHZ(freq1) && IS_5GHZ(freq2))
3026
0
    return true;
3027
3028
0
  if (is_6ghz_freq(freq1) && is_6ghz_freq(freq2))
3029
0
    return true;
3030
3031
0
  return false;
3032
0
}
3033
3034
3035
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
3036
            size_t nei_rep_len)
3037
0
{
3038
0
  u8 *nei_pos = nei_rep;
3039
0
  const char *end;
3040
3041
  /*
3042
   * BSS Transition Candidate List Entries - Neighbor Report elements
3043
   * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
3044
   * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
3045
   */
3046
0
  while (pos) {
3047
0
    u8 *nei_start;
3048
0
    long int val;
3049
0
    char *endptr, *tmp;
3050
3051
0
    pos = os_strstr(pos, " neighbor=");
3052
0
    if (!pos)
3053
0
      break;
3054
0
    if (nei_pos + 15 > nei_rep + nei_rep_len) {
3055
0
      wpa_printf(MSG_DEBUG,
3056
0
           "Not enough room for additional neighbor");
3057
0
      return -1;
3058
0
    }
3059
0
    pos += 10;
3060
3061
0
    nei_start = nei_pos;
3062
0
    *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
3063
0
    nei_pos++; /* length to be filled in */
3064
3065
0
    if (hwaddr_aton(pos, nei_pos)) {
3066
0
      wpa_printf(MSG_DEBUG, "Invalid BSSID");
3067
0
      return -1;
3068
0
    }
3069
0
    nei_pos += ETH_ALEN;
3070
0
    pos += 17;
3071
0
    if (*pos != ',') {
3072
0
      wpa_printf(MSG_DEBUG, "Missing BSSID Information");
3073
0
      return -1;
3074
0
    }
3075
0
    pos++;
3076
3077
0
    val = strtol(pos, &endptr, 0);
3078
0
    WPA_PUT_LE32(nei_pos, val);
3079
0
    nei_pos += 4;
3080
0
    if (*endptr != ',') {
3081
0
      wpa_printf(MSG_DEBUG, "Missing Operating Class");
3082
0
      return -1;
3083
0
    }
3084
0
    pos = endptr + 1;
3085
3086
0
    *nei_pos++ = atoi(pos); /* Operating Class */
3087
0
    pos = os_strchr(pos, ',');
3088
0
    if (pos == NULL) {
3089
0
      wpa_printf(MSG_DEBUG, "Missing Channel Number");
3090
0
      return -1;
3091
0
    }
3092
0
    pos++;
3093
3094
0
    *nei_pos++ = atoi(pos); /* Channel Number */
3095
0
    pos = os_strchr(pos, ',');
3096
0
    if (pos == NULL) {
3097
0
      wpa_printf(MSG_DEBUG, "Missing PHY Type");
3098
0
      return -1;
3099
0
    }
3100
0
    pos++;
3101
3102
0
    *nei_pos++ = atoi(pos); /* PHY Type */
3103
0
    end = os_strchr(pos, ' ');
3104
0
    tmp = os_strchr(pos, ',');
3105
0
    if (tmp && (!end || tmp < end)) {
3106
      /* Optional Subelements (hexdump) */
3107
0
      size_t len;
3108
3109
0
      pos = tmp + 1;
3110
0
      end = os_strchr(pos, ' ');
3111
0
      if (end)
3112
0
        len = end - pos;
3113
0
      else
3114
0
        len = os_strlen(pos);
3115
0
      if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
3116
0
        wpa_printf(MSG_DEBUG,
3117
0
             "Not enough room for neighbor subelements");
3118
0
        return -1;
3119
0
      }
3120
0
      if (len & 0x01 ||
3121
0
          hexstr2bin(pos, nei_pos, len / 2) < 0) {
3122
0
        wpa_printf(MSG_DEBUG,
3123
0
             "Invalid neighbor subelement info");
3124
0
        return -1;
3125
0
      }
3126
0
      nei_pos += len / 2;
3127
0
      pos = end;
3128
0
    }
3129
3130
0
    nei_start[1] = nei_pos - nei_start - 2;
3131
0
  }
3132
3133
0
  return nei_pos - nei_rep;
3134
0
}
3135
3136
3137
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
3138
0
{
3139
0
  if (!ie || ie[1] <= capab / 8)
3140
0
    return 0;
3141
0
  return !!(ie[2 + capab / 8] & BIT(capab % 8));
3142
0
}
3143
3144
3145
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
3146
             unsigned int capab)
3147
0
{
3148
0
  const u8 *end;
3149
0
  size_t flen, i;
3150
0
  u32 capabs = 0;
3151
3152
0
  if (!rsnxe || rsnxe_len == 0)
3153
0
    return false;
3154
0
  end = rsnxe + rsnxe_len;
3155
0
  flen = (rsnxe[0] & 0x0f) + 1;
3156
0
  if (rsnxe + flen > end)
3157
0
    return false;
3158
0
  if (flen > 4)
3159
0
    flen = 4;
3160
0
  for (i = 0; i < flen; i++)
3161
0
    capabs |= (u32) rsnxe[i] << (8 * i);
3162
3163
0
  return !!(capabs & BIT(capab));
3164
0
}
3165
3166
3167
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
3168
0
{
3169
0
  if (!rsnxe)
3170
0
    return false;
3171
0
  if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
3172
0
    return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
3173
0
             capab);
3174
0
  return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
3175
0
}
3176
3177
3178
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
3179
            int primary_channel,
3180
            struct ieee80211_edmg_config *edmg)
3181
0
{
3182
0
  if (!edmg_enable) {
3183
0
    edmg->channels = 0;
3184
0
    edmg->bw_config = 0;
3185
0
    return;
3186
0
  }
3187
3188
  /* Only EDMG CB1 and EDMG CB2 contiguous channels supported for now */
3189
0
  switch (edmg_channel) {
3190
0
  case EDMG_CHANNEL_9:
3191
0
    edmg->channels = EDMG_CHANNEL_9_SUBCHANNELS;
3192
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3193
0
    return;
3194
0
  case EDMG_CHANNEL_10:
3195
0
    edmg->channels = EDMG_CHANNEL_10_SUBCHANNELS;
3196
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3197
0
    return;
3198
0
  case EDMG_CHANNEL_11:
3199
0
    edmg->channels = EDMG_CHANNEL_11_SUBCHANNELS;
3200
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3201
0
    return;
3202
0
  case EDMG_CHANNEL_12:
3203
0
    edmg->channels = EDMG_CHANNEL_12_SUBCHANNELS;
3204
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3205
0
    return;
3206
0
  case EDMG_CHANNEL_13:
3207
0
    edmg->channels = EDMG_CHANNEL_13_SUBCHANNELS;
3208
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3209
0
    return;
3210
0
  default:
3211
0
    if (primary_channel > 0 && primary_channel < 7) {
3212
0
      edmg->channels = BIT(primary_channel - 1);
3213
0
      edmg->bw_config = EDMG_BW_CONFIG_4;
3214
0
    } else {
3215
0
      edmg->channels = 0;
3216
0
      edmg->bw_config = 0;
3217
0
    }
3218
0
    break;
3219
0
  }
3220
0
}
3221
3222
3223
/* Check if the requested EDMG configuration is a subset of the allowed
3224
 * EDMG configuration. */
3225
int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
3226
          struct ieee80211_edmg_config requested)
3227
0
{
3228
  /*
3229
   * The validation check if the requested EDMG configuration
3230
   * is a subset of the allowed EDMG configuration:
3231
   * 1. Check that the requested channels are part (set) of the allowed
3232
   * channels.
3233
   * 2. P802.11ay defines the values of bw_config between 4 and 15.
3234
   * (bw config % 4) will give us 4 groups inside bw_config definition,
3235
   * inside each group we can check the subset just by comparing the
3236
   * bw_config value.
3237
   * Between this 4 groups, there is no subset relation - as a result of
3238
   * the P802.11ay definition.
3239
   * bw_config defined by IEEE P802.11ay/D4.0, 9.4.2.251, Table 13.
3240
   */
3241
0
  if (((requested.channels & allowed.channels) != requested.channels) ||
3242
0
      ((requested.bw_config % 4) > (allowed.bw_config % 4)) ||
3243
0
      requested.bw_config > allowed.bw_config)
3244
0
    return 0;
3245
3246
0
  return 1;
3247
0
}
3248
3249
3250
int op_class_to_bandwidth(u8 op_class)
3251
0
{
3252
0
  switch (op_class) {
3253
0
  case 81:
3254
0
  case 82:
3255
0
    return 20;
3256
0
  case 83: /* channels 1..9; 40 MHz */
3257
0
  case 84: /* channels 5..13; 40 MHz */
3258
0
    return 40;
3259
0
  case 115: /* channels 36,40,44,48; indoor only */
3260
0
    return 20;
3261
0
  case 116: /* channels 36,44; 40 MHz; indoor only */
3262
0
  case 117: /* channels 40,48; 40 MHz; indoor only */
3263
0
    return 40;
3264
0
  case 118: /* channels 52,56,60,64; dfs */
3265
0
    return 20;
3266
0
  case 119: /* channels 52,60; 40 MHz; dfs */
3267
0
  case 120: /* channels 56,64; 40 MHz; dfs */
3268
0
    return 40;
3269
0
  case 121: /* channels 100-144 */
3270
0
    return 20;
3271
0
  case 122: /* channels 100-140; 40 MHz */
3272
0
  case 123: /* channels 104-144; 40 MHz */
3273
0
    return 40;
3274
0
  case 124: /* channels 149,153,157,161 */
3275
0
  case 125: /* channels 149,153,157,161,165,169,173,177 */
3276
0
    return 20;
3277
0
  case 126: /* channels 149,157,161,165,169,173; 40 MHz */
3278
0
  case 127: /* channels 153..177; 40 MHz */
3279
0
    return 40;
3280
0
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
3281
0
    return 80;
3282
0
  case 129: /* center freqs 50, 114, 163; 160 MHz */
3283
0
    return 160;
3284
0
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80+80 MHz */
3285
0
    return 80;
3286
0
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
3287
0
    return 20;
3288
0
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
3289
0
    return 40;
3290
0
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
3291
0
    return 80;
3292
0
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
3293
0
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
3294
0
    return 160;
3295
0
  case 136: /* UHB channels, 20 MHz: 2 */
3296
0
    return 20;
3297
0
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
3298
0
    return 320;
3299
0
  case 180: /* 60 GHz band, channels 1..8 */
3300
0
    return 2160;
3301
0
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
3302
0
    return 4320;
3303
0
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
3304
0
    return 6480;
3305
0
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
3306
0
    return 8640;
3307
0
  default:
3308
0
    return 20;
3309
0
  }
3310
0
}
3311
3312
3313
enum oper_chan_width op_class_to_ch_width(u8 op_class)
3314
0
{
3315
0
  switch (op_class) {
3316
0
  case 81:
3317
0
  case 82:
3318
0
    return CONF_OPER_CHWIDTH_USE_HT;
3319
0
  case 83: /* channels 1..9; 40 MHz */
3320
0
  case 84: /* channels 5..13; 40 MHz */
3321
0
    return CONF_OPER_CHWIDTH_USE_HT;
3322
0
  case 115: /* channels 36,40,44,48; indoor only */
3323
0
    return CONF_OPER_CHWIDTH_USE_HT;
3324
0
  case 116: /* channels 36,44; 40 MHz; indoor only */
3325
0
  case 117: /* channels 40,48; 40 MHz; indoor only */
3326
0
    return CONF_OPER_CHWIDTH_USE_HT;
3327
0
  case 118: /* channels 52,56,60,64; dfs */
3328
0
    return CONF_OPER_CHWIDTH_USE_HT;
3329
0
  case 119: /* channels 52,60; 40 MHz; dfs */
3330
0
  case 120: /* channels 56,64; 40 MHz; dfs */
3331
0
    return CONF_OPER_CHWIDTH_USE_HT;
3332
0
  case 121: /* channels 100-144 */
3333
0
    return CONF_OPER_CHWIDTH_USE_HT;
3334
0
  case 122: /* channels 100-140; 40 MHz */
3335
0
  case 123: /* channels 104-144; 40 MHz */
3336
0
    return CONF_OPER_CHWIDTH_USE_HT;
3337
0
  case 124: /* channels 149,153,157,161 */
3338
0
  case 125: /* channels 149,153,157,161,165,169,171 */
3339
0
    return CONF_OPER_CHWIDTH_USE_HT;
3340
0
  case 126: /* channels 149,157,165, 173; 40 MHz */
3341
0
  case 127: /* channels 153,161,169,177; 40 MHz */
3342
0
    return CONF_OPER_CHWIDTH_USE_HT;
3343
0
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
3344
0
    return CONF_OPER_CHWIDTH_80MHZ;
3345
0
  case 129: /* center freqs 50, 114, 163; 160 MHz */
3346
0
    return CONF_OPER_CHWIDTH_160MHZ;
3347
0
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80+80 MHz */
3348
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3349
0
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
3350
0
    return CONF_OPER_CHWIDTH_USE_HT;
3351
0
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
3352
0
    return CONF_OPER_CHWIDTH_USE_HT;
3353
0
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
3354
0
    return CONF_OPER_CHWIDTH_80MHZ;
3355
0
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
3356
0
    return CONF_OPER_CHWIDTH_160MHZ;
3357
0
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
3358
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3359
0
  case 136: /* UHB channels, 20 MHz: 2 */
3360
0
    return CONF_OPER_CHWIDTH_USE_HT;
3361
0
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
3362
0
    return CONF_OPER_CHWIDTH_320MHZ;
3363
0
  case 180: /* 60 GHz band, channels 1..8 */
3364
0
    return CONF_OPER_CHWIDTH_2160MHZ;
3365
0
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
3366
0
    return CONF_OPER_CHWIDTH_4320MHZ;
3367
0
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
3368
0
    return CONF_OPER_CHWIDTH_6480MHZ;
3369
0
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
3370
0
    return CONF_OPER_CHWIDTH_8640MHZ;
3371
0
  default:
3372
0
    return CONF_OPER_CHWIDTH_USE_HT;
3373
0
  }
3374
0
}
3375
3376
3377
/**
3378
 * chwidth_freq2_to_ch_width - Determine channel width as enum oper_chan_width
3379
 * @chwidth: Channel width integer
3380
 * @freq2: Value for frequency 2. 0 is not used
3381
 * Returns: enum oper_chan_width, -1 on failure
3382
 */
3383
int chwidth_freq2_to_ch_width(int chwidth, int freq2)
3384
0
{
3385
0
  if (freq2 < 0)
3386
0
    return -1;
3387
0
  if (freq2)
3388
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3389
3390
0
  switch (chwidth) {
3391
0
  case 0:
3392
0
  case 20:
3393
0
  case 40:
3394
0
    return CONF_OPER_CHWIDTH_USE_HT;
3395
0
  case 80:
3396
0
    return CONF_OPER_CHWIDTH_80MHZ;
3397
0
  case 160:
3398
0
    return CONF_OPER_CHWIDTH_160MHZ;
3399
0
  case 320:
3400
0
    return CONF_OPER_CHWIDTH_320MHZ;
3401
0
  default:
3402
0
    wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
3403
0
         chwidth);
3404
0
    return -1;
3405
0
  }
3406
0
}
3407
3408
3409
struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem)
3410
0
{
3411
0
  struct wpabuf *buf;
3412
0
  const u8 *pos, *end;
3413
0
  size_t min_defrag_len = ext_elem ? 255 : 256;
3414
3415
0
  if (!data || !len)
3416
0
    return NULL;
3417
3418
0
  if (len < min_defrag_len)
3419
0
    return wpabuf_alloc_copy(data, len);
3420
3421
0
  buf = wpabuf_alloc_copy(data, min_defrag_len - 1);
3422
0
  if (!buf)
3423
0
    return NULL;
3424
3425
0
  pos = &data[min_defrag_len - 1];
3426
0
  end = data + len;
3427
0
  len -= min_defrag_len - 1;
3428
0
  while (len > 2 && pos[0] == WLAN_EID_FRAGMENT && pos[1]) {
3429
0
    int ret;
3430
0
    size_t elen = 2 + pos[1];
3431
3432
0
    if (elen > (size_t) (end - pos) || elen > len)
3433
0
      break;
3434
0
    ret = wpabuf_resize(&buf, pos[1]);
3435
0
    if (ret < 0) {
3436
0
      wpabuf_free(buf);
3437
0
      return NULL;
3438
0
    }
3439
3440
    /* Copy only the fragment data (without the EID and length) */
3441
0
    wpabuf_put_data(buf, &pos[2], pos[1]);
3442
0
    pos += elen;
3443
0
    len -= elen;
3444
0
  }
3445
3446
0
  return buf;
3447
0
}
3448
3449
3450
/**
3451
 * ieee802_11_defrag_mle_subelem - Defragment Multi-Link element subelements
3452
 * @mlbuf: Defragmented mlbuf (defragmented using ieee802_11_defrag())
3453
 * @parent_subelem: Pointer to the subelement which may be fragmented
3454
 * @defrag_len: Defragmented length of the subelement
3455
 * Returns: Number of Fragment subelements parsed on success, -1 otherwise
3456
 *
3457
 * This function defragments a subelement present inside an Multi-Link element.
3458
 * It should be called individually for each subelement.
3459
 *
3460
 * Subelements can use the Fragment subelement if they pack more than 255 bytes
3461
 * of data, see IEEE P802.11be/D7.0 Figure 35-4 - Per-STA Profile subelement
3462
 * fragmentation within a fragmented Multi-Link element.
3463
 */
3464
size_t ieee802_11_defrag_mle_subelem(struct wpabuf *mlbuf,
3465
             const u8 *parent_subelem,
3466
             size_t *defrag_len)
3467
0
{
3468
0
  u8 *buf, *pos, *end;
3469
0
  size_t len, subelem_len;
3470
0
  const size_t min_defrag_len = 255;
3471
0
  int num_frag_subelems = 0;
3472
3473
0
  if (!mlbuf || !parent_subelem)
3474
0
    return -1;
3475
3476
0
  buf = wpabuf_mhead_u8(mlbuf);
3477
0
  len = wpabuf_len(mlbuf);
3478
0
  end = buf + len;
3479
3480
0
  *defrag_len = parent_subelem[1];
3481
0
  if (parent_subelem[1] < min_defrag_len)
3482
0
    return 0;
3483
3484
0
  pos = (u8 *) parent_subelem;
3485
0
  if (2 + parent_subelem[1] > end - pos)
3486
0
    return -1;
3487
0
  pos += 2 + parent_subelem[1];
3488
0
  subelem_len = parent_subelem[1];
3489
3490
0
  while (end - pos > 2 &&
3491
0
         pos[0] == MULTI_LINK_SUB_ELEM_ID_FRAGMENT && pos[1]) {
3492
0
    size_t elen = 2 + pos[1];
3493
3494
    /* This Multi-Link parent subelement has more data and is
3495
     * fragmented. */
3496
0
    num_frag_subelems++;
3497
3498
0
    if (elen > (size_t) (end - pos))
3499
0
      return -1;
3500
3501
0
    os_memmove(pos, pos + 2, end - (pos + 2));
3502
0
    pos += elen - 2;
3503
0
    subelem_len += elen - 2;
3504
3505
    /* Deduct Fragment subelement header */
3506
0
    len -= 2;
3507
0
  }
3508
3509
0
  *defrag_len = subelem_len;
3510
0
  return num_frag_subelems;
3511
0
}
3512
3513
3514
const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
3515
0
{
3516
0
  const struct element *elem;
3517
3518
0
  if (!ies)
3519
0
    return NULL;
3520
3521
0
  for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
3522
0
    if (elem->datalen >= 2 &&
3523
0
        (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
3524
0
      return &elem->id;
3525
0
  }
3526
3527
0
  return NULL;
3528
0
}
3529
3530
3531
const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
3532
0
{
3533
0
  const size_t mld_addr_pos =
3534
0
    2 /* Control field */ +
3535
0
    1 /* Common Info Length field */;
3536
0
  const size_t fixed_len = mld_addr_pos +
3537
0
    ETH_ALEN /* MLD MAC Address field */;
3538
3539
0
  if (len < fixed_len)
3540
0
    return NULL;
3541
3542
0
  if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
3543
0
      MULTI_LINK_CONTROL_TYPE_BASIC)
3544
0
    return NULL;
3545
3546
0
  return &buf[mld_addr_pos];
3547
0
}