Coverage Report

Created: 2025-08-26 06:04

/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
1.05M
{
24
1.05M
  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
1.05M
  if (elen < 4) {
30
523k
    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
523k
    return -1;
36
523k
  }
37
38
528k
  oui = WPA_GET_BE24(pos);
39
528k
  switch (oui) {
40
192k
  case OUI_MICROSOFT:
41
    /* Microsoft/Wi-Fi information elements are further typed and
42
     * subtyped */
43
192k
    switch (pos[3]) {
44
1.15k
    case 1:
45
      /* Microsoft OUI (00:50:F2) with OUI Type 1:
46
       * real WPA information element */
47
1.15k
      elems->wpa_ie = pos;
48
1.15k
      elems->wpa_ie_len = elen;
49
1.15k
      break;
50
2.01k
    case WMM_OUI_TYPE:
51
      /* WMM information element */
52
2.01k
      if (elen < 5) {
53
1.04k
        wpa_printf(MSG_MSGDUMP, "short WMM "
54
1.04k
             "information element ignored "
55
1.04k
             "(len=%lu)",
56
1.04k
             (unsigned long) elen);
57
1.04k
        return -1;
58
1.04k
      }
59
972
      switch (pos[4]) {
60
239
      case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
61
478
      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
478
        elems->wmm = pos;
69
478
        elems->wmm_len = elen;
70
478
        break;
71
209
      case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
72
209
        elems->wmm_tspec = pos;
73
209
        elems->wmm_tspec_len = elen;
74
209
        break;
75
285
      default:
76
285
        wpa_printf(MSG_EXCESSIVE, "unknown WMM "
77
285
             "information element ignored "
78
285
             "(subtype=%d len=%lu)",
79
285
             pos[4], (unsigned long) elen);
80
285
        return -1;
81
972
      }
82
687
      break;
83
188k
    case 4:
84
      /* Wi-Fi Protected Setup (WPS) IE */
85
188k
      elems->wps_ie = pos;
86
188k
      elems->wps_ie_len = elen;
87
188k
      break;
88
503
    default:
89
503
      wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
90
503
           "information element ignored "
91
503
           "(type=%d len=%lu)",
92
503
           pos[3], (unsigned long) elen);
93
503
      return -1;
94
192k
    }
95
190k
    break;
96
97
266k
  case OUI_WFA:
98
266k
    switch (pos[3]) {
99
187k
    case P2P_OUI_TYPE:
100
      /* Wi-Fi Alliance - P2P IE */
101
187k
      elems->p2p = pos;
102
187k
      elems->p2p_len = elen;
103
187k
      break;
104
74.1k
    case WFD_OUI_TYPE:
105
      /* Wi-Fi Alliance - WFD IE */
106
74.1k
      elems->wfd = pos;
107
74.1k
      elems->wfd_len = elen;
108
74.1k
      break;
109
205
    case HS20_INDICATION_OUI_TYPE:
110
      /* Hotspot 2.0 */
111
205
      elems->hs20 = pos;
112
205
      elems->hs20_len = elen;
113
205
      break;
114
216
    case MBO_OUI_TYPE:
115
      /* MBO-OCE */
116
216
      elems->mbo = pos;
117
216
      elems->mbo_len = elen;
118
216
      break;
119
284
    case HS20_ROAMING_CONS_SEL_OUI_TYPE:
120
      /* Hotspot 2.0 Roaming Consortium Selection */
121
284
      elems->roaming_cons_sel = pos;
122
284
      elems->roaming_cons_sel_len = elen;
123
284
      break;
124
206
    case MULTI_AP_OUI_TYPE:
125
206
      elems->multi_ap = pos;
126
206
      elems->multi_ap_len = elen;
127
206
      break;
128
253
    case OWE_OUI_TYPE:
129
      /* OWE Transition Mode element */
130
253
      break;
131
222
    case DPP_CC_OUI_TYPE:
132
      /* DPP Configurator Connectivity element */
133
222
      break;
134
205
    case SAE_PK_OUI_TYPE:
135
205
      elems->sae_pk = pos + 4;
136
205
      elems->sae_pk_len = elen - 4;
137
205
      break;
138
332
    case WFA_CAPA_OUI_TYPE:
139
332
      elems->wfa_capab = pos + 4;
140
332
      elems->wfa_capab_len = elen - 4;
141
332
      break;
142
305
    case WFA_RSNE_OVERRIDE_OUI_TYPE:
143
305
      elems->rsne_override = pos;
144
305
      elems->rsne_override_len = elen;
145
305
      break;
146
216
    case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
147
216
      elems->rsne_override_2 = pos;
148
216
      elems->rsne_override_2_len = elen;
149
216
      break;
150
226
    case WFA_RSNXE_OVERRIDE_OUI_TYPE:
151
226
      elems->rsnxe_override = pos;
152
226
      elems->rsnxe_override_len = elen;
153
226
      break;
154
537
    case WFA_RSN_SELECTION_OUI_TYPE:
155
537
      if (elen < 4 + 1) {
156
327
        wpa_printf(MSG_DEBUG,
157
327
             "Too short RSN Selection element ignored");
158
327
        return -1;
159
327
      }
160
210
      elems->rsn_selection = pos + 4;
161
210
      elems->rsn_selection_len = elen - 4;
162
210
      break;
163
1.64k
    case P2P2_OUI_TYPE:
164
      /* Wi-Fi Alliance - P2P2 IE */
165
1.64k
      elems->p2p2_ie = pos;
166
1.64k
      elems->p2p2_ie_len = elen;
167
1.64k
      break;
168
805
    default:
169
805
      wpa_printf(MSG_MSGDUMP, "Unknown WFA "
170
805
           "information element ignored "
171
805
           "(type=%d len=%lu)",
172
805
           pos[3], (unsigned long) elen);
173
805
      return -1;
174
266k
    }
175
265k
    break;
176
177
265k
  case OUI_BROADCOM:
178
2.36k
    switch (pos[3]) {
179
200
    case VENDOR_HT_CAPAB_OUI_TYPE:
180
200
      elems->vendor_ht_cap = pos;
181
200
      elems->vendor_ht_cap_len = elen;
182
200
      break;
183
1.38k
    case VENDOR_VHT_TYPE:
184
1.38k
      if (elen > 4 &&
185
1.38k
          (pos[4] == VENDOR_VHT_SUBTYPE ||
186
1.18k
           pos[4] == VENDOR_VHT_SUBTYPE2)) {
187
934
        elems->vendor_vht = pos;
188
934
        elems->vendor_vht_len = elen;
189
934
      } else
190
455
        return -1;
191
934
      break;
192
934
    default:
193
772
      wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
194
772
           "information element ignored "
195
772
           "(type=%d len=%lu)",
196
772
           pos[3], (unsigned long) elen);
197
772
      return -1;
198
2.36k
    }
199
1.13k
    break;
200
201
1.13k
  case OUI_QCA:
202
925
    switch (pos[3]) {
203
403
    case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
204
403
      elems->pref_freq_list = pos;
205
403
      elems->pref_freq_list_len = elen;
206
403
      break;
207
522
    default:
208
522
      wpa_printf(MSG_EXCESSIVE,
209
522
           "Unknown QCA information element ignored (type=%d len=%lu)",
210
522
           pos[3], (unsigned long) elen);
211
522
      return -1;
212
925
    }
213
403
    break;
214
215
65.4k
  default:
216
65.4k
    wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
217
65.4k
         "information element ignored (vendor OUI "
218
65.4k
         "%02x:%02x:%02x len=%lu)",
219
65.4k
         pos[0], pos[1], pos[2], (unsigned long) elen);
220
65.4k
    return -1;
221
528k
  }
222
223
458k
  return 0;
224
528k
}
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
1.95k
{
231
1.95k
  u8 mle_type = pos[0] & MULTI_LINK_CONTROL_TYPE_MASK;
232
233
1.95k
  switch (mle_type) {
234
267
  case MULTI_LINK_CONTROL_TYPE_BASIC:
235
267
    elems->basic_mle = pos;
236
267
    elems->basic_mle_len = elen;
237
267
    *total_len = &elems->basic_mle_len;
238
267
    break;
239
700
  case MULTI_LINK_CONTROL_TYPE_PROBE_REQ:
240
700
    elems->probe_req_mle = pos;
241
700
    elems->probe_req_mle_len = elen;
242
700
    *total_len = &elems->probe_req_mle_len;
243
700
    break;
244
254
  case MULTI_LINK_CONTROL_TYPE_RECONF:
245
254
    elems->reconf_mle = pos;
246
254
    elems->reconf_mle_len = elen;
247
254
    *total_len = &elems->reconf_mle_len;
248
254
    break;
249
236
  case MULTI_LINK_CONTROL_TYPE_TDLS:
250
236
    elems->tdls_mle = pos;
251
236
    elems->tdls_mle_len = elen;
252
236
    *total_len = &elems->tdls_mle_len;
253
236
    break;
254
290
  case MULTI_LINK_CONTROL_TYPE_PRIOR_ACCESS:
255
290
    elems->prior_access_mle = pos;
256
290
    elems->prior_access_mle_len = elen;
257
290
    *total_len = &elems->prior_access_mle_len;
258
290
    break;
259
207
  default:
260
207
    if (show_errors) {
261
0
      wpa_printf(MSG_MSGDUMP,
262
0
           "Unknown Multi-Link element type %u",
263
0
           mle_type);
264
0
    }
265
207
    return -1;
266
1.95k
  }
267
268
1.74k
  return 0;
269
1.95k
}
270
271
272
static size_t ieee802_11_fragments_length(struct ieee802_11_elems *elems,
273
            const u8 *start, size_t len)
274
1.68k
{
275
1.68k
  const struct element *elem;
276
1.68k
  size_t frags_len = 0;
277
278
1.33M
  for_each_element(elem, start, len) {
279
1.33M
    if (elem->id != WLAN_EID_FRAGMENT)
280
1.52k
      break;
281
282
1.32M
    frags_len += elem->datalen + 2;
283
1.32M
    elems->num_frag_elems++;
284
1.32M
  }
285
286
1.68k
  return frags_len;
287
1.68k
}
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
37.5k
{
295
37.5k
  u8 ext_id;
296
37.5k
  size_t *total_len = NULL;
297
298
37.5k
  if (elen < 1) {
299
2.87k
    if (show_errors) {
300
0
      wpa_printf(MSG_MSGDUMP,
301
0
           "short information element (Ext)");
302
0
    }
303
2.87k
    return -1;
304
2.87k
  }
305
306
34.6k
  ext_id = *pos++;
307
34.6k
  elen--;
308
309
34.6k
  switch (ext_id) {
310
1.03k
  case WLAN_EID_EXT_ASSOC_DELAY_INFO:
311
1.03k
    if (elen != 1)
312
814
      break;
313
217
    elems->assoc_delay_info = pos;
314
217
    break;
315
1.12k
  case WLAN_EID_EXT_FILS_REQ_PARAMS:
316
1.12k
    if (elen < 3)
317
693
      break;
318
429
    elems->fils_req_params = pos;
319
429
    elems->fils_req_params_len = elen;
320
429
    break;
321
1.29k
  case WLAN_EID_EXT_FILS_KEY_CONFIRM:
322
1.29k
    elems->fils_key_confirm = pos;
323
1.29k
    elems->fils_key_confirm_len = elen;
324
1.29k
    break;
325
1.02k
  case WLAN_EID_EXT_FILS_SESSION:
326
1.02k
    if (elen != FILS_SESSION_LEN)
327
792
      break;
328
235
    elems->fils_session = pos;
329
235
    break;
330
1.16k
  case WLAN_EID_EXT_FILS_HLP_CONTAINER:
331
1.16k
    if (elen < 2 * ETH_ALEN)
332
259
      break;
333
905
    elems->fils_hlp = pos;
334
905
    elems->fils_hlp_len = elen;
335
905
    total_len = &elems->fils_hlp_len;
336
905
    break;
337
970
  case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
338
970
    if (elen < 1)
339
200
      break;
340
770
    elems->fils_ip_addr_assign = pos;
341
770
    elems->fils_ip_addr_assign_len = elen;
342
770
    break;
343
1.49k
  case WLAN_EID_EXT_KEY_DELIVERY:
344
1.49k
    if (elen < WPA_KEY_RSC_LEN)
345
472
      break;
346
1.02k
    elems->key_delivery = pos;
347
1.02k
    elems->key_delivery_len = elen;
348
1.02k
    break;
349
706
  case WLAN_EID_EXT_WRAPPED_DATA:
350
706
    elems->wrapped_data = pos;
351
706
    elems->wrapped_data_len = elen;
352
706
    total_len = &elems->wrapped_data_len;
353
706
    break;
354
631
  case WLAN_EID_EXT_FILS_PUBLIC_KEY:
355
631
    if (elen < 1)
356
236
      break;
357
395
    elems->fils_pk = pos;
358
395
    elems->fils_pk_len = elen;
359
395
    break;
360
519
  case WLAN_EID_EXT_FILS_NONCE:
361
519
    if (elen != FILS_NONCE_LEN)
362
319
      break;
363
200
    elems->fils_nonce = pos;
364
200
    break;
365
594
  case WLAN_EID_EXT_OWE_DH_PARAM:
366
594
    if (elen < 2)
367
334
      break;
368
260
    elems->owe_dh = pos;
369
260
    elems->owe_dh_len = elen;
370
260
    break;
371
260
  case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
372
260
    elems->password_id = pos;
373
260
    elems->password_id_len = elen;
374
260
    break;
375
307
  case WLAN_EID_EXT_HE_CAPABILITIES:
376
307
    elems->he_capabilities = pos;
377
307
    elems->he_capabilities_len = elen;
378
307
    break;
379
211
  case WLAN_EID_EXT_HE_OPERATION:
380
211
    elems->he_operation = pos;
381
211
    elems->he_operation_len = elen;
382
211
    break;
383
201
  case WLAN_EID_EXT_OCV_OCI:
384
201
    elems->oci = pos;
385
201
    elems->oci_len = elen;
386
201
    break;
387
236
  case WLAN_EID_EXT_SHORT_SSID_LIST:
388
236
    elems->short_ssid_list = pos;
389
236
    elems->short_ssid_list_len = elen;
390
236
    break;
391
436
  case WLAN_EID_EXT_HE_6GHZ_BAND_CAP:
392
436
    if (elen < sizeof(struct ieee80211_he_6ghz_band_cap))
393
202
      break;
394
234
    elems->he_6ghz_band_cap = pos;
395
234
    break;
396
209
  case WLAN_EID_EXT_PASN_PARAMS:
397
209
    elems->pasn_params = pos;
398
209
    elems->pasn_params_len = elen;
399
209
    break;
400
1.62k
  case WLAN_EID_EXT_EHT_CAPABILITIES:
401
1.62k
    elems->eht_capabilities = pos;
402
1.62k
    elems->eht_capabilities_len = elen;
403
1.62k
    break;
404
267
  case WLAN_EID_EXT_EHT_OPERATION:
405
267
    elems->eht_operation = pos;
406
267
    elems->eht_operation_len = elen;
407
267
    break;
408
2.19k
  case WLAN_EID_EXT_MULTI_LINK:
409
2.19k
    if (elen < 2)
410
240
      break;
411
1.95k
    if (ieee802_11_parse_mle(pos, elen, &total_len, elems,
412
1.95k
           show_errors))
413
207
      return -1;
414
1.74k
    break;
415
1.74k
  case WLAN_EID_EXT_KNOWN_BSSID:
416
228
    elems->mbssid_known_bss = pos;
417
228
    elems->mbssid_known_bss_len = elen;
418
228
    break;
419
545
  case WLAN_EID_EXT_PASN_ENCRYPTED_DATA:
420
545
    elems->pasn_encrypted_data = pos;
421
545
    elems->pasn_encrypted_data_len = elen;
422
545
    break;
423
17.3k
  default:
424
17.3k
    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
17.3k
    return -1;
430
34.6k
  }
431
432
17.0k
  if (elen == 254 && total_len)
433
1.16k
    *total_len += ieee802_11_fragments_length(
434
1.16k
      elems, pos + elen, (start + len) - (pos + elen));
435
436
17.0k
  return 0;
437
34.6k
}
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
23.4k
{
444
23.4k
  const struct element *elem;
445
23.4k
  int unknown = 0;
446
447
23.4k
  if (!start)
448
0
    return ParseOK;
449
450
37.7M
  for_each_element(elem, start, len) {
451
37.7M
    u8 id = elem->id, elen = elem->datalen;
452
37.7M
    const u8 *pos = elem->data;
453
37.7M
    size_t *total_len = NULL;
454
455
37.7M
    if (id == WLAN_EID_FRAGMENT && elems->num_frag_elems > 0) {
456
1.32M
      elems->num_frag_elems--;
457
1.32M
      continue;
458
1.32M
    }
459
36.4M
    elems->num_frag_elems = 0;
460
461
36.4M
    switch (id) {
462
32.6M
    case WLAN_EID_SSID:
463
32.6M
      if (elen > SSID_MAX_LEN) {
464
78.0k
        wpa_printf(MSG_DEBUG,
465
78.0k
             "Ignored too long SSID element (elen=%u)",
466
78.0k
             elen);
467
78.0k
        break;
468
78.0k
      }
469
32.5M
      if (elems->ssid) {
470
32.5M
        wpa_printf(MSG_MSGDUMP,
471
32.5M
             "Ignored duplicated SSID element");
472
32.5M
        break;
473
32.5M
      }
474
8.09k
      elems->ssid = pos;
475
8.09k
      elems->ssid_len = elen;
476
8.09k
      break;
477
90.3k
    case WLAN_EID_SUPP_RATES:
478
90.3k
      elems->supp_rates = pos;
479
90.3k
      elems->supp_rates_len = elen;
480
90.3k
      break;
481
177k
    case WLAN_EID_DS_PARAMS:
482
177k
      if (elen < 1)
483
3.95k
        break;
484
173k
      elems->ds_params = pos;
485
173k
      break;
486
18.1k
    case WLAN_EID_CF_PARAMS:
487
23.1k
    case WLAN_EID_TIM:
488
23.1k
      break;
489
26.8k
    case WLAN_EID_CHALLENGE:
490
26.8k
      elems->challenge = pos;
491
26.8k
      elems->challenge_len = elen;
492
26.8k
      break;
493
4.36k
    case WLAN_EID_ERP_INFO:
494
4.36k
      if (elen < 1)
495
3.83k
        break;
496
538
      elems->erp_info = pos;
497
538
      break;
498
29.4k
    case WLAN_EID_EXT_SUPP_RATES:
499
29.4k
      elems->ext_supp_rates = pos;
500
29.4k
      elems->ext_supp_rates_len = elen;
501
29.4k
      break;
502
1.05M
    case WLAN_EID_VENDOR_SPECIFIC:
503
1.05M
      if (ieee802_11_parse_vendor_specific(pos, elen,
504
1.05M
                   elems,
505
1.05M
                   show_errors))
506
593k
        unknown++;
507
1.05M
      break;
508
2.98k
    case WLAN_EID_RSN:
509
2.98k
      elems->rsn_ie = pos;
510
2.98k
      elems->rsn_ie_len = elen;
511
2.98k
      break;
512
446
    case WLAN_EID_RSNX:
513
446
      elems->rsnxe = pos;
514
446
      elems->rsnxe_len = elen;
515
446
      break;
516
2.08k
    case WLAN_EID_PWR_CAPABILITY:
517
2.08k
      if (elen < 2)
518
1.10k
        break;
519
986
      elems->power_capab = pos;
520
986
      elems->power_capab_len = elen;
521
986
      break;
522
1.07k
    case WLAN_EID_SUPPORTED_CHANNELS:
523
1.07k
      elems->supp_channels = pos;
524
1.07k
      elems->supp_channels_len = elen;
525
1.07k
      break;
526
1.11k
    case WLAN_EID_MOBILITY_DOMAIN:
527
1.11k
      if (elen < sizeof(struct rsn_mdie))
528
467
        break;
529
646
      elems->mdie = pos;
530
646
      elems->mdie_len = elen;
531
646
      break;
532
1.99k
    case WLAN_EID_FAST_BSS_TRANSITION:
533
1.99k
      if (elen < sizeof(struct rsn_ftie))
534
1.23k
        break;
535
762
      elems->ftie = pos;
536
762
      elems->ftie_len = elen;
537
762
      elems->fte_defrag_len = elen;
538
762
      total_len = &elems->fte_defrag_len;
539
762
      break;
540
4.00k
    case WLAN_EID_TIMEOUT_INTERVAL:
541
4.00k
      if (elen != 5)
542
3.62k
        break;
543
377
      elems->timeout_int = pos;
544
377
      break;
545
4.41k
    case WLAN_EID_HT_CAP:
546
4.41k
      if (elen < sizeof(struct ieee80211_ht_capabilities))
547
1.06k
        break;
548
3.34k
      elems->ht_capabilities = pos;
549
3.34k
      break;
550
2.39k
    case WLAN_EID_HT_OPERATION:
551
2.39k
      if (elen < sizeof(struct ieee80211_ht_operation))
552
1.20k
        break;
553
1.19k
      elems->ht_operation = pos;
554
1.19k
      break;
555
306
    case WLAN_EID_MESH_CONFIG:
556
306
      elems->mesh_config = pos;
557
306
      elems->mesh_config_len = elen;
558
306
      break;
559
1.00k
    case WLAN_EID_MESH_ID:
560
1.00k
      elems->mesh_id = pos;
561
1.00k
      elems->mesh_id_len = elen;
562
1.00k
      break;
563
2.83k
    case WLAN_EID_PEER_MGMT:
564
2.83k
      elems->peer_mgmt = pos;
565
2.83k
      elems->peer_mgmt_len = elen;
566
2.83k
      break;
567
1.22k
    case WLAN_EID_VHT_CAP:
568
1.22k
      if (elen < sizeof(struct ieee80211_vht_capabilities))
569
487
        break;
570
738
      elems->vht_capabilities = pos;
571
738
      break;
572
931
    case WLAN_EID_VHT_OPERATION:
573
931
      if (elen < sizeof(struct ieee80211_vht_operation))
574
600
        break;
575
331
      elems->vht_operation = pos;
576
331
      break;
577
1.18k
    case WLAN_EID_OPERATING_MODE_NOTIFICATION:
578
1.18k
      if (elen != 1)
579
981
        break;
580
203
      elems->opmode_notif = pos;
581
203
      break;
582
2.58k
    case WLAN_EID_LINK_ID:
583
2.58k
      if (elen < 18)
584
478
        break;
585
2.10k
      elems->link_id = pos;
586
2.10k
      break;
587
819
    case WLAN_EID_INTERWORKING:
588
819
      elems->interworking = pos;
589
819
      elems->interworking_len = elen;
590
819
      break;
591
1.70k
    case WLAN_EID_QOS_MAP_SET:
592
1.70k
      if (elen < 16)
593
672
        break;
594
1.03k
      elems->qos_map_set = pos;
595
1.03k
      elems->qos_map_set_len = elen;
596
1.03k
      break;
597
2.59k
    case WLAN_EID_EXT_CAPAB:
598
2.59k
      elems->ext_capab = pos;
599
2.59k
      elems->ext_capab_len = elen;
600
2.59k
      break;
601
1.18k
    case WLAN_EID_BSS_MAX_IDLE_PERIOD:
602
1.18k
      if (elen < 3)
603
382
        break;
604
800
      elems->bss_max_idle_period = pos;
605
800
      break;
606
1.93k
    case WLAN_EID_SSID_LIST:
607
1.93k
      elems->ssid_list = pos;
608
1.93k
      elems->ssid_list_len = elen;
609
1.93k
      break;
610
340
    case WLAN_EID_AMPE:
611
340
      elems->ampe = pos;
612
340
      elems->ampe_len = elen;
613
340
      break;
614
1.92k
    case WLAN_EID_MIC:
615
1.92k
      elems->mic = pos;
616
1.92k
      elems->mic_len = elen;
617
      /* after mic everything is encrypted, so stop. */
618
1.92k
      goto done;
619
528
    case WLAN_EID_MULTI_BAND:
620
528
      if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
621
204
        wpa_printf(MSG_MSGDUMP,
622
204
             "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
623
204
             id, elen);
624
204
        break;
625
204
      }
626
627
324
      elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
628
324
      elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
629
324
      elems->mb_ies.nof_ies++;
630
324
      break;
631
3.24k
    case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
632
3.24k
      elems->supp_op_classes = pos;
633
3.24k
      elems->supp_op_classes_len = elen;
634
3.24k
      break;
635
805
    case WLAN_EID_RRM_ENABLED_CAPABILITIES:
636
805
      elems->rrm_enabled = pos;
637
805
      elems->rrm_enabled_len = elen;
638
805
      break;
639
2.59k
    case WLAN_EID_MULTIPLE_BSSID:
640
2.59k
      if (elen < 1)
641
375
        break;
642
2.22k
      elems->mbssid = pos;
643
2.22k
      elems->mbssid_len = elen;
644
2.22k
      break;
645
281
    case WLAN_EID_CAG_NUMBER:
646
281
      elems->cag_number = pos;
647
281
      elems->cag_number_len = elen;
648
281
      break;
649
1.50k
    case WLAN_EID_AP_CSN:
650
1.50k
      if (elen < 1)
651
329
        break;
652
1.17k
      elems->ap_csn = pos;
653
1.17k
      break;
654
11.0k
    case WLAN_EID_FILS_INDICATION:
655
11.0k
      if (elen < 2)
656
10.2k
        break;
657
788
      elems->fils_indic = pos;
658
788
      elems->fils_indic_len = elen;
659
788
      break;
660
2.04k
    case WLAN_EID_DILS:
661
2.04k
      if (elen < 2)
662
374
        break;
663
1.67k
      elems->dils = pos;
664
1.67k
      elems->dils_len = elen;
665
1.67k
      break;
666
726
    case WLAN_EID_S1G_CAPABILITIES:
667
726
      if (elen < 15)
668
375
        break;
669
351
      elems->s1g_capab = pos;
670
351
      break;
671
6.64k
    case WLAN_EID_FRAGMENT:
672
6.64k
      wpa_printf(MSG_MSGDUMP,
673
6.64k
           "Fragment without a valid last element - skip");
674
675
6.64k
      break;
676
37.5k
    case WLAN_EID_EXTENSION:
677
37.5k
      if (ieee802_11_parse_extension(pos, elen, elems, start,
678
37.5k
                   len, show_errors))
679
20.4k
        unknown++;
680
37.5k
      break;
681
2.25M
    default:
682
2.25M
      unknown++;
683
2.25M
      if (!show_errors)
684
2.25M
        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
36.4M
    }
690
691
36.4M
    if (elen == 255 && total_len)
692
523
      *total_len += ieee802_11_fragments_length(
693
523
        elems, pos + elen,
694
523
        (start + len) - (pos + elen));
695
696
36.4M
  }
697
698
21.5k
  if (!for_each_element_completed(elem, start, len)) {
699
2.87k
    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
2.87k
    return ParseFailed;
706
2.87k
  }
707
708
20.6k
done:
709
20.6k
  return unknown ? ParseUnknown : ParseOK;
710
21.5k
}
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
23.4k
{
725
23.4k
  os_memset(elems, 0, sizeof(*elems));
726
727
23.4k
  return __ieee802_11_parse_elems(start, len, elems, show_errors);
728
23.4k
}
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
40.7k
{
1168
40.7k
  struct wpabuf *buf;
1169
40.7k
  const struct element *elem, *found = NULL;
1170
1171
67.5M
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
1172
862k
    if (elem->datalen >= 4 &&
1173
862k
        WPA_GET_BE32(elem->data) == oui_type) {
1174
13.3k
      found = elem;
1175
13.3k
      break;
1176
13.3k
    }
1177
862k
  }
1178
1179
40.7k
  if (!found)
1180
27.4k
    return NULL; /* No specified vendor IE found */
1181
1182
13.3k
  buf = wpabuf_alloc(ies_len);
1183
13.3k
  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
49.8M
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
1191
2.08M
    if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type)
1192
488k
      wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4);
1193
2.08M
  }
1194
1195
13.3k
  return buf;
1196
13.3k
}
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
2.33k
{
1724
2.33k
  int i;
1725
1726
2.33k
  if (country == NULL)
1727
2.33k
    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
584
{
1932
  /* Table E-4 in IEEE Std 802.11-2020 - Global operating classes */
1933
584
  switch (op_class) {
1934
42
  case 81:
1935
    /* channels 1..13 */
1936
42
    if (chan < 1 || chan > 13)
1937
9
      return -1;
1938
33
    return 2407 + 5 * chan;
1939
15
  case 82:
1940
    /* channel 14 */
1941
15
    if (chan != 14)
1942
12
      return -1;
1943
3
    return 2414 + 5 * chan;
1944
13
  case 83: /* channels 1..9; 40 MHz */
1945
28
  case 84: /* channels 5..13; 40 MHz */
1946
28
    if (chan < 1 || chan > 13)
1947
15
      return -1;
1948
13
    return 2407 + 5 * chan;
1949
4
  case 115: /* channels 36,40,44,48; indoor only */
1950
7
  case 116: /* channels 36,44; 40 MHz; indoor only */
1951
18
  case 117: /* channels 40,48; 40 MHz; indoor only */
1952
24
  case 118: /* channels 52,56,60,64; dfs */
1953
35
  case 119: /* channels 52,60; 40 MHz; dfs */
1954
39
  case 120: /* channels 56,64; 40 MHz; dfs */
1955
39
    if (chan < 36 || chan > 64)
1956
29
      return -1;
1957
10
    return 5000 + 5 * chan;
1958
8
  case 121: /* channels 100-144 */
1959
17
  case 122: /* channels 100-140; 40 MHz */
1960
25
  case 123: /* channels 104-144; 40 MHz */
1961
25
    if (chan < 100 || chan > 144)
1962
17
      return -1;
1963
8
    return 5000 + 5 * chan;
1964
24
  case 124: /* channels 149,153,157,161 */
1965
24
    if (chan < 149 || chan > 161)
1966
17
      return -1;
1967
7
    return 5000 + 5 * chan;
1968
7
  case 125: /* channels 149,153,157,161,165,169,173,177 */
1969
17
  case 126: /* channels 149,157,165,173; 40 MHz */
1970
26
  case 127: /* channels 153,161,169,177; 40 MHz */
1971
26
    if (chan < 149 || chan > 177)
1972
16
      return -1;
1973
10
    return 5000 + 5 * chan;
1974
27
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
1975
41
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
1976
41
    if (chan < 36 || chan > 177)
1977
14
      return -1;
1978
27
    return 5000 + 5 * chan;
1979
30
  case 129: /* center freqs 50, 114, 163; 160 MHz */
1980
30
    if (chan < 36 || chan > 177)
1981
15
      return -1;
1982
15
    return 5000 + 5 * chan;
1983
11
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
1984
30
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
1985
40
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
1986
48
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
1987
58
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
1988
65
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
1989
65
    if (chan < 1 || chan > 233)
1990
12
      return -1;
1991
53
    return 5950 + chan * 5;
1992
17
  case 136: /* UHB channels, 20 MHz: 2 */
1993
17
    if (chan == 2)
1994
3
      return 5935;
1995
14
    return -1;
1996
20
  case 180: /* 60 GHz band, channels 1..8 */
1997
20
    if (chan < 1 || chan > 8)
1998
13
      return -1;
1999
7
    return 56160 + 2160 * chan;
2000
25
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
2001
25
    if (chan < 9 || chan > 15)
2002
17
      return -1;
2003
8
    return 56160 + 2160 * (chan - 8);
2004
20
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
2005
20
    if (chan < 17 || chan > 22)
2006
13
      return -1;
2007
7
    return 56160 + 2160 * (chan - 16);
2008
23
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
2009
23
    if (chan < 25 || chan > 29)
2010
19
      return -1;
2011
4
    return 56160 + 2160 * (chan - 24);
2012
144
  default:
2013
144
    return -1;
2014
584
  }
2015
584
}
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
584
{
2026
584
  int freq;
2027
2028
584
  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
584
  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
584
  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
584
  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
584
  return ieee80211_chan_to_freq_global(op_class, chan);
2053
584
}
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
bool is_24ghz_freq(int freq)
2931
0
{
2932
0
  return freq >= 2400 && freq <= 2484;
2933
0
}
2934
2935
2936
bool is_5ghz_freq(int freq)
2937
0
{
2938
0
  return freq >= 5150 && freq <= 5885;
2939
0
}
2940
2941
2942
int center_idx_to_bw_6ghz(u8 idx)
2943
0
{
2944
  /* Channel: 2 */
2945
0
  if (idx == 2)
2946
0
    return 0; /* 20 MHz */
2947
  /* channels: 1, 5, 9, 13... */
2948
0
  if ((idx & 0x3) == 0x1)
2949
0
    return 0; /* 20 MHz */
2950
  /* channels 3, 11, 19... */
2951
0
  if ((idx & 0x7) == 0x3)
2952
0
    return 1; /* 40 MHz */
2953
  /* channels 7, 23, 39.. */
2954
0
  if ((idx & 0xf) == 0x7)
2955
0
    return 2; /* 80 MHz */
2956
  /* channels 15, 47, 79...*/
2957
0
  if ((idx & 0x1f) == 0xf)
2958
0
    return 3; /* 160 MHz */
2959
  /* channels 31, 63, 95, 127, 159, 191 */
2960
0
  if ((idx & 0x1f) == 0x1f && idx < 192)
2961
0
    return 4; /* 320 MHz */
2962
2963
0
  return -1;
2964
0
}
2965
2966
2967
bool is_6ghz_freq(int freq)
2968
0
{
2969
0
  if (freq < 5935 || freq > 7115)
2970
0
    return false;
2971
2972
0
  if (freq == 5935)
2973
0
    return true;
2974
2975
0
  if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0)
2976
0
    return false;
2977
2978
0
  return true;
2979
0
}
2980
2981
2982
bool is_6ghz_op_class(u8 op_class)
2983
0
{
2984
0
  return op_class >= 131 && op_class <= 137;
2985
0
}
2986
2987
2988
bool is_6ghz_psc_frequency(int freq)
2989
0
{
2990
0
  int i;
2991
2992
0
  if (!is_6ghz_freq(freq) || freq == 5935)
2993
0
    return false;
2994
0
  if ((((freq - 5950) / 5) & 0x3) != 0x1)
2995
0
    return false;
2996
2997
0
  i = (freq - 5950 + 55) % 80;
2998
0
  if (i == 0)
2999
0
    i = (freq - 5950 + 55) / 80;
3000
3001
0
  if (i >= 1 && i <= 15)
3002
0
    return true;
3003
3004
0
  return false;
3005
0
}
3006
3007
3008
/**
3009
 * get_6ghz_sec_channel - Get the relative position of the secondary channel
3010
 * to the primary channel in 6 GHz
3011
 * @channel: Primary channel to be checked for (in global op class 131)
3012
 * Returns: 1 = secondary channel above, -1 = secondary channel below
3013
 */
3014
3015
int get_6ghz_sec_channel(int channel)
3016
0
{
3017
  /*
3018
   * In the 6 GHz band, primary channels are numbered as 1, 5, 9, 13.., so
3019
   * the 40 MHz channels are formed with the channel pairs as (1,5),
3020
   * (9,13), (17,21)..
3021
   * The secondary channel for a given primary channel is below the
3022
   * primary channel for the channels 5, 13, 21.. and it is above the
3023
   * primary channel for the channels 1, 9, 17..
3024
   */
3025
3026
0
  if (((channel - 1) / 4) % 2)
3027
0
    return -1;
3028
0
  return 1;
3029
0
}
3030
3031
3032
bool is_same_band(int freq1, int freq2)
3033
0
{
3034
0
  if (IS_2P4GHZ(freq1) && IS_2P4GHZ(freq2))
3035
0
    return true;
3036
3037
0
  if (IS_5GHZ(freq1) && IS_5GHZ(freq2))
3038
0
    return true;
3039
3040
0
  if (is_6ghz_freq(freq1) && is_6ghz_freq(freq2))
3041
0
    return true;
3042
3043
0
  return false;
3044
0
}
3045
3046
3047
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
3048
            size_t nei_rep_len)
3049
0
{
3050
0
  u8 *nei_pos = nei_rep;
3051
0
  const char *end;
3052
3053
  /*
3054
   * BSS Transition Candidate List Entries - Neighbor Report elements
3055
   * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
3056
   * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
3057
   */
3058
0
  while (pos) {
3059
0
    u8 *nei_start;
3060
0
    long int val;
3061
0
    char *endptr, *tmp;
3062
3063
0
    pos = os_strstr(pos, " neighbor=");
3064
0
    if (!pos)
3065
0
      break;
3066
0
    if (nei_pos + 15 > nei_rep + nei_rep_len) {
3067
0
      wpa_printf(MSG_DEBUG,
3068
0
           "Not enough room for additional neighbor");
3069
0
      return -1;
3070
0
    }
3071
0
    pos += 10;
3072
3073
0
    nei_start = nei_pos;
3074
0
    *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
3075
0
    nei_pos++; /* length to be filled in */
3076
3077
0
    if (hwaddr_aton(pos, nei_pos)) {
3078
0
      wpa_printf(MSG_DEBUG, "Invalid BSSID");
3079
0
      return -1;
3080
0
    }
3081
0
    nei_pos += ETH_ALEN;
3082
0
    pos += 17;
3083
0
    if (*pos != ',') {
3084
0
      wpa_printf(MSG_DEBUG, "Missing BSSID Information");
3085
0
      return -1;
3086
0
    }
3087
0
    pos++;
3088
3089
0
    val = strtol(pos, &endptr, 0);
3090
0
    WPA_PUT_LE32(nei_pos, val);
3091
0
    nei_pos += 4;
3092
0
    if (*endptr != ',') {
3093
0
      wpa_printf(MSG_DEBUG, "Missing Operating Class");
3094
0
      return -1;
3095
0
    }
3096
0
    pos = endptr + 1;
3097
3098
0
    *nei_pos++ = atoi(pos); /* Operating Class */
3099
0
    pos = os_strchr(pos, ',');
3100
0
    if (pos == NULL) {
3101
0
      wpa_printf(MSG_DEBUG, "Missing Channel Number");
3102
0
      return -1;
3103
0
    }
3104
0
    pos++;
3105
3106
0
    *nei_pos++ = atoi(pos); /* Channel Number */
3107
0
    pos = os_strchr(pos, ',');
3108
0
    if (pos == NULL) {
3109
0
      wpa_printf(MSG_DEBUG, "Missing PHY Type");
3110
0
      return -1;
3111
0
    }
3112
0
    pos++;
3113
3114
0
    *nei_pos++ = atoi(pos); /* PHY Type */
3115
0
    end = os_strchr(pos, ' ');
3116
0
    tmp = os_strchr(pos, ',');
3117
0
    if (tmp && (!end || tmp < end)) {
3118
      /* Optional Subelements (hexdump) */
3119
0
      size_t len;
3120
3121
0
      pos = tmp + 1;
3122
0
      end = os_strchr(pos, ' ');
3123
0
      if (end)
3124
0
        len = end - pos;
3125
0
      else
3126
0
        len = os_strlen(pos);
3127
0
      if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
3128
0
        wpa_printf(MSG_DEBUG,
3129
0
             "Not enough room for neighbor subelements");
3130
0
        return -1;
3131
0
      }
3132
0
      if (len & 0x01 ||
3133
0
          hexstr2bin(pos, nei_pos, len / 2) < 0) {
3134
0
        wpa_printf(MSG_DEBUG,
3135
0
             "Invalid neighbor subelement info");
3136
0
        return -1;
3137
0
      }
3138
0
      nei_pos += len / 2;
3139
0
      pos = end;
3140
0
    }
3141
3142
0
    nei_start[1] = nei_pos - nei_start - 2;
3143
0
  }
3144
3145
0
  return nei_pos - nei_rep;
3146
0
}
3147
3148
3149
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
3150
0
{
3151
0
  if (!ie || ie[1] <= capab / 8)
3152
0
    return 0;
3153
0
  return !!(ie[2 + capab / 8] & BIT(capab % 8));
3154
0
}
3155
3156
3157
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
3158
             unsigned int capab)
3159
0
{
3160
0
  const u8 *end;
3161
0
  size_t flen, i;
3162
0
  u32 capabs = 0;
3163
3164
0
  if (!rsnxe || rsnxe_len == 0)
3165
0
    return false;
3166
0
  end = rsnxe + rsnxe_len;
3167
0
  flen = (rsnxe[0] & 0x0f) + 1;
3168
0
  if (rsnxe + flen > end)
3169
0
    return false;
3170
0
  if (flen > 4)
3171
0
    flen = 4;
3172
0
  for (i = 0; i < flen; i++)
3173
0
    capabs |= (u32) rsnxe[i] << (8 * i);
3174
3175
0
  return !!(capabs & BIT(capab));
3176
0
}
3177
3178
3179
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
3180
0
{
3181
0
  if (!rsnxe)
3182
0
    return false;
3183
0
  if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
3184
0
    return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
3185
0
             capab);
3186
0
  return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
3187
0
}
3188
3189
3190
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
3191
            int primary_channel,
3192
            struct ieee80211_edmg_config *edmg)
3193
0
{
3194
0
  if (!edmg_enable) {
3195
0
    edmg->channels = 0;
3196
0
    edmg->bw_config = 0;
3197
0
    return;
3198
0
  }
3199
3200
  /* Only EDMG CB1 and EDMG CB2 contiguous channels supported for now */
3201
0
  switch (edmg_channel) {
3202
0
  case EDMG_CHANNEL_9:
3203
0
    edmg->channels = EDMG_CHANNEL_9_SUBCHANNELS;
3204
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3205
0
    return;
3206
0
  case EDMG_CHANNEL_10:
3207
0
    edmg->channels = EDMG_CHANNEL_10_SUBCHANNELS;
3208
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3209
0
    return;
3210
0
  case EDMG_CHANNEL_11:
3211
0
    edmg->channels = EDMG_CHANNEL_11_SUBCHANNELS;
3212
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3213
0
    return;
3214
0
  case EDMG_CHANNEL_12:
3215
0
    edmg->channels = EDMG_CHANNEL_12_SUBCHANNELS;
3216
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3217
0
    return;
3218
0
  case EDMG_CHANNEL_13:
3219
0
    edmg->channels = EDMG_CHANNEL_13_SUBCHANNELS;
3220
0
    edmg->bw_config = EDMG_BW_CONFIG_5;
3221
0
    return;
3222
0
  default:
3223
0
    if (primary_channel > 0 && primary_channel < 7) {
3224
0
      edmg->channels = BIT(primary_channel - 1);
3225
0
      edmg->bw_config = EDMG_BW_CONFIG_4;
3226
0
    } else {
3227
0
      edmg->channels = 0;
3228
0
      edmg->bw_config = 0;
3229
0
    }
3230
0
    break;
3231
0
  }
3232
0
}
3233
3234
3235
/* Check if the requested EDMG configuration is a subset of the allowed
3236
 * EDMG configuration. */
3237
int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
3238
          struct ieee80211_edmg_config requested)
3239
0
{
3240
  /*
3241
   * The validation check if the requested EDMG configuration
3242
   * is a subset of the allowed EDMG configuration:
3243
   * 1. Check that the requested channels are part (set) of the allowed
3244
   * channels.
3245
   * 2. P802.11ay defines the values of bw_config between 4 and 15.
3246
   * (bw config % 4) will give us 4 groups inside bw_config definition,
3247
   * inside each group we can check the subset just by comparing the
3248
   * bw_config value.
3249
   * Between this 4 groups, there is no subset relation - as a result of
3250
   * the P802.11ay definition.
3251
   * bw_config defined by IEEE P802.11ay/D4.0, 9.4.2.251, Table 13.
3252
   */
3253
0
  if (((requested.channels & allowed.channels) != requested.channels) ||
3254
0
      ((requested.bw_config % 4) > (allowed.bw_config % 4)) ||
3255
0
      requested.bw_config > allowed.bw_config)
3256
0
    return 0;
3257
3258
0
  return 1;
3259
0
}
3260
3261
3262
int op_class_to_bandwidth(u8 op_class)
3263
0
{
3264
0
  switch (op_class) {
3265
0
  case 81:
3266
0
  case 82:
3267
0
    return 20;
3268
0
  case 83: /* channels 1..9; 40 MHz */
3269
0
  case 84: /* channels 5..13; 40 MHz */
3270
0
    return 40;
3271
0
  case 115: /* channels 36,40,44,48; indoor only */
3272
0
    return 20;
3273
0
  case 116: /* channels 36,44; 40 MHz; indoor only */
3274
0
  case 117: /* channels 40,48; 40 MHz; indoor only */
3275
0
    return 40;
3276
0
  case 118: /* channels 52,56,60,64; dfs */
3277
0
    return 20;
3278
0
  case 119: /* channels 52,60; 40 MHz; dfs */
3279
0
  case 120: /* channels 56,64; 40 MHz; dfs */
3280
0
    return 40;
3281
0
  case 121: /* channels 100-144 */
3282
0
    return 20;
3283
0
  case 122: /* channels 100-140; 40 MHz */
3284
0
  case 123: /* channels 104-144; 40 MHz */
3285
0
    return 40;
3286
0
  case 124: /* channels 149,153,157,161 */
3287
0
  case 125: /* channels 149,153,157,161,165,169,173,177 */
3288
0
    return 20;
3289
0
  case 126: /* channels 149,157,161,165,169,173; 40 MHz */
3290
0
  case 127: /* channels 153..177; 40 MHz */
3291
0
    return 40;
3292
0
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
3293
0
    return 80;
3294
0
  case 129: /* center freqs 50, 114, 163; 160 MHz */
3295
0
    return 160;
3296
0
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80+80 MHz */
3297
0
    return 80;
3298
0
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
3299
0
    return 20;
3300
0
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
3301
0
    return 40;
3302
0
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
3303
0
    return 80;
3304
0
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
3305
0
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
3306
0
    return 160;
3307
0
  case 136: /* UHB channels, 20 MHz: 2 */
3308
0
    return 20;
3309
0
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
3310
0
    return 320;
3311
0
  case 180: /* 60 GHz band, channels 1..8 */
3312
0
    return 2160;
3313
0
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
3314
0
    return 4320;
3315
0
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
3316
0
    return 6480;
3317
0
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
3318
0
    return 8640;
3319
0
  default:
3320
0
    return 20;
3321
0
  }
3322
0
}
3323
3324
3325
enum oper_chan_width op_class_to_ch_width(u8 op_class)
3326
0
{
3327
0
  switch (op_class) {
3328
0
  case 81:
3329
0
  case 82:
3330
0
    return CONF_OPER_CHWIDTH_USE_HT;
3331
0
  case 83: /* channels 1..9; 40 MHz */
3332
0
  case 84: /* channels 5..13; 40 MHz */
3333
0
    return CONF_OPER_CHWIDTH_USE_HT;
3334
0
  case 115: /* channels 36,40,44,48; indoor only */
3335
0
    return CONF_OPER_CHWIDTH_USE_HT;
3336
0
  case 116: /* channels 36,44; 40 MHz; indoor only */
3337
0
  case 117: /* channels 40,48; 40 MHz; indoor only */
3338
0
    return CONF_OPER_CHWIDTH_USE_HT;
3339
0
  case 118: /* channels 52,56,60,64; dfs */
3340
0
    return CONF_OPER_CHWIDTH_USE_HT;
3341
0
  case 119: /* channels 52,60; 40 MHz; dfs */
3342
0
  case 120: /* channels 56,64; 40 MHz; dfs */
3343
0
    return CONF_OPER_CHWIDTH_USE_HT;
3344
0
  case 121: /* channels 100-144 */
3345
0
    return CONF_OPER_CHWIDTH_USE_HT;
3346
0
  case 122: /* channels 100-140; 40 MHz */
3347
0
  case 123: /* channels 104-144; 40 MHz */
3348
0
    return CONF_OPER_CHWIDTH_USE_HT;
3349
0
  case 124: /* channels 149,153,157,161 */
3350
0
  case 125: /* channels 149,153,157,161,165,169,171 */
3351
0
    return CONF_OPER_CHWIDTH_USE_HT;
3352
0
  case 126: /* channels 149,157,165, 173; 40 MHz */
3353
0
  case 127: /* channels 153,161,169,177; 40 MHz */
3354
0
    return CONF_OPER_CHWIDTH_USE_HT;
3355
0
  case 128: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80 MHz */
3356
0
    return CONF_OPER_CHWIDTH_80MHZ;
3357
0
  case 129: /* center freqs 50, 114, 163; 160 MHz */
3358
0
    return CONF_OPER_CHWIDTH_160MHZ;
3359
0
  case 130: /* center freqs 42, 58, 106, 122, 138, 155, 171; 80+80 MHz */
3360
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3361
0
  case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
3362
0
    return CONF_OPER_CHWIDTH_USE_HT;
3363
0
  case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
3364
0
    return CONF_OPER_CHWIDTH_USE_HT;
3365
0
  case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
3366
0
    return CONF_OPER_CHWIDTH_80MHZ;
3367
0
  case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
3368
0
    return CONF_OPER_CHWIDTH_160MHZ;
3369
0
  case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
3370
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3371
0
  case 136: /* UHB channels, 20 MHz: 2 */
3372
0
    return CONF_OPER_CHWIDTH_USE_HT;
3373
0
  case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
3374
0
    return CONF_OPER_CHWIDTH_320MHZ;
3375
0
  case 180: /* 60 GHz band, channels 1..8 */
3376
0
    return CONF_OPER_CHWIDTH_2160MHZ;
3377
0
  case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
3378
0
    return CONF_OPER_CHWIDTH_4320MHZ;
3379
0
  case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
3380
0
    return CONF_OPER_CHWIDTH_6480MHZ;
3381
0
  case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
3382
0
    return CONF_OPER_CHWIDTH_8640MHZ;
3383
0
  default:
3384
0
    return CONF_OPER_CHWIDTH_USE_HT;
3385
0
  }
3386
0
}
3387
3388
3389
/**
3390
 * chwidth_freq2_to_ch_width - Determine channel width as enum oper_chan_width
3391
 * @chwidth: Channel width integer
3392
 * @freq2: Value for frequency 2. 0 is not used
3393
 * Returns: enum oper_chan_width, -1 on failure
3394
 */
3395
int chwidth_freq2_to_ch_width(int chwidth, int freq2)
3396
0
{
3397
0
  if (freq2 < 0)
3398
0
    return -1;
3399
0
  if (freq2)
3400
0
    return CONF_OPER_CHWIDTH_80P80MHZ;
3401
3402
0
  switch (chwidth) {
3403
0
  case 0:
3404
0
  case 20:
3405
0
  case 40:
3406
0
    return CONF_OPER_CHWIDTH_USE_HT;
3407
0
  case 80:
3408
0
    return CONF_OPER_CHWIDTH_80MHZ;
3409
0
  case 160:
3410
0
    return CONF_OPER_CHWIDTH_160MHZ;
3411
0
  case 320:
3412
0
    return CONF_OPER_CHWIDTH_320MHZ;
3413
0
  default:
3414
0
    wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
3415
0
         chwidth);
3416
0
    return -1;
3417
0
  }
3418
0
}
3419
3420
3421
struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem)
3422
0
{
3423
0
  struct wpabuf *buf;
3424
0
  const u8 *pos, *end;
3425
0
  size_t min_defrag_len = ext_elem ? 255 : 256;
3426
3427
0
  if (!data || !len)
3428
0
    return NULL;
3429
3430
0
  if (len < min_defrag_len)
3431
0
    return wpabuf_alloc_copy(data, len);
3432
3433
0
  buf = wpabuf_alloc_copy(data, min_defrag_len - 1);
3434
0
  if (!buf)
3435
0
    return NULL;
3436
3437
0
  pos = &data[min_defrag_len - 1];
3438
0
  end = data + len;
3439
0
  len -= min_defrag_len - 1;
3440
0
  while (len > 2 && pos[0] == WLAN_EID_FRAGMENT && pos[1]) {
3441
0
    int ret;
3442
0
    size_t elen = 2 + pos[1];
3443
3444
0
    if (elen > (size_t) (end - pos) || elen > len)
3445
0
      break;
3446
0
    ret = wpabuf_resize(&buf, pos[1]);
3447
0
    if (ret < 0) {
3448
0
      wpabuf_free(buf);
3449
0
      return NULL;
3450
0
    }
3451
3452
    /* Copy only the fragment data (without the EID and length) */
3453
0
    wpabuf_put_data(buf, &pos[2], pos[1]);
3454
0
    pos += elen;
3455
0
    len -= elen;
3456
0
  }
3457
3458
0
  return buf;
3459
0
}
3460
3461
3462
/**
3463
 * ieee802_11_defrag_mle_subelem - Defragment Multi-Link element subelements
3464
 * @mlbuf: Defragmented mlbuf (defragmented using ieee802_11_defrag())
3465
 * @parent_subelem: Pointer to the subelement which may be fragmented
3466
 * @defrag_len: Defragmented length of the subelement
3467
 * Returns: Number of Fragment subelements parsed on success, -1 otherwise
3468
 *
3469
 * This function defragments a subelement present inside an Multi-Link element.
3470
 * It should be called individually for each subelement.
3471
 *
3472
 * Subelements can use the Fragment subelement if they pack more than 255 bytes
3473
 * of data, see IEEE P802.11be/D7.0 Figure 35-4 - Per-STA Profile subelement
3474
 * fragmentation within a fragmented Multi-Link element.
3475
 */
3476
size_t ieee802_11_defrag_mle_subelem(struct wpabuf *mlbuf,
3477
             const u8 *parent_subelem,
3478
             size_t *defrag_len)
3479
0
{
3480
0
  u8 *buf, *pos, *end;
3481
0
  size_t len, subelem_len;
3482
0
  const size_t min_defrag_len = 255;
3483
0
  int num_frag_subelems = 0;
3484
3485
0
  if (!mlbuf || !parent_subelem)
3486
0
    return -1;
3487
3488
0
  buf = wpabuf_mhead_u8(mlbuf);
3489
0
  len = wpabuf_len(mlbuf);
3490
0
  end = buf + len;
3491
3492
0
  *defrag_len = parent_subelem[1];
3493
0
  if (parent_subelem[1] < min_defrag_len)
3494
0
    return 0;
3495
3496
0
  pos = (u8 *) parent_subelem;
3497
0
  if (2 + parent_subelem[1] > end - pos)
3498
0
    return -1;
3499
0
  pos += 2 + parent_subelem[1];
3500
0
  subelem_len = parent_subelem[1];
3501
3502
0
  while (end - pos > 2 &&
3503
0
         pos[0] == MULTI_LINK_SUB_ELEM_ID_FRAGMENT && pos[1]) {
3504
0
    size_t elen = 2 + pos[1];
3505
3506
    /* This Multi-Link parent subelement has more data and is
3507
     * fragmented. */
3508
0
    num_frag_subelems++;
3509
3510
0
    if (elen > (size_t) (end - pos))
3511
0
      return -1;
3512
3513
0
    os_memmove(pos, pos + 2, end - (pos + 2));
3514
0
    pos += elen - 2;
3515
0
    subelem_len += elen - 2;
3516
3517
    /* Deduct Fragment subelement header */
3518
0
    len -= 2;
3519
0
  }
3520
3521
0
  *defrag_len = subelem_len;
3522
0
  return num_frag_subelems;
3523
0
}
3524
3525
3526
const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type)
3527
0
{
3528
0
  const struct element *elem;
3529
3530
0
  if (!ies)
3531
0
    return NULL;
3532
3533
0
  for_each_element_extid(elem, WLAN_EID_EXT_MULTI_LINK, ies, len) {
3534
0
    if (elem->datalen >= 2 &&
3535
0
        (elem->data[1] & MULTI_LINK_CONTROL_TYPE_MASK) == type)
3536
0
      return &elem->id;
3537
0
  }
3538
3539
0
  return NULL;
3540
0
}
3541
3542
3543
const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len)
3544
0
{
3545
0
  const size_t mld_addr_pos =
3546
0
    2 /* Control field */ +
3547
0
    1 /* Common Info Length field */;
3548
0
  const size_t fixed_len = mld_addr_pos +
3549
0
    ETH_ALEN /* MLD MAC Address field */;
3550
3551
0
  if (len < fixed_len)
3552
0
    return NULL;
3553
3554
0
  if ((buf[0] & MULTI_LINK_CONTROL_TYPE_MASK) !=
3555
0
      MULTI_LINK_CONTROL_TYPE_BASIC)
3556
0
    return NULL;
3557
3558
0
  return &buf[mld_addr_pos];
3559
0
}