Coverage Report

Created: 2025-04-24 06:18

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