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