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