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