Coverage Report

Created: 2023-11-19 06:30

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