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