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