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