Coverage Report

Created: 2026-06-09 06:10

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