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