1 /*
2 * IEEE 802.11 Common routines
3 * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "defs.h"
13 #include "wpa_common.h"
14 #include "drivers/driver.h"
15 #include "qca-vendor.h"
16 #include "ieee802_11_defs.h"
17 #include "ieee802_11_common.h"
18
19
ieee802_11_parse_vendor_specific(const u8 * pos,size_t elen,struct ieee802_11_elems * elems,int show_errors)20 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
21 struct ieee802_11_elems *elems,
22 int show_errors)
23 {
24 unsigned int oui;
25
26 /* first 3 bytes in vendor specific information element are the IEEE
27 * OUI of the vendor. The following byte is used a vendor specific
28 * sub-type. */
29 if (elen < 4) {
30 if (show_errors) {
31 wpa_printf(MSG_MSGDUMP, "short vendor specific "
32 "information element ignored (len=%lu)",
33 (unsigned long) elen);
34 }
35 return -1;
36 }
37
38 oui = WPA_GET_BE24(pos);
39 switch (oui) {
40 case OUI_MICROSOFT:
41 /* Microsoft/Wi-Fi information elements are further typed and
42 * subtyped */
43 switch (pos[3]) {
44 case 1:
45 /* Microsoft OUI (00:50:F2) with OUI Type 1:
46 * real WPA information element */
47 elems->wpa_ie = pos;
48 elems->wpa_ie_len = elen;
49 break;
50 case WMM_OUI_TYPE:
51 /* WMM information element */
52 if (elen < 5) {
53 wpa_printf(MSG_MSGDUMP, "short WMM "
54 "information element ignored "
55 "(len=%lu)",
56 (unsigned long) elen);
57 return -1;
58 }
59 switch (pos[4]) {
60 case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
61 case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
62 /*
63 * Share same pointer since only one of these
64 * is used and they start with same data.
65 * Length field can be used to distinguish the
66 * IEs.
67 */
68 elems->wmm = pos;
69 elems->wmm_len = elen;
70 break;
71 case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
72 elems->wmm_tspec = pos;
73 elems->wmm_tspec_len = elen;
74 break;
75 default:
76 wpa_printf(MSG_EXCESSIVE, "unknown WMM "
77 "information element ignored "
78 "(subtype=%d len=%lu)",
79 pos[4], (unsigned long) elen);
80 return -1;
81 }
82 break;
83 case 4:
84 /* Wi-Fi Protected Setup (WPS) IE */
85 elems->wps_ie = pos;
86 elems->wps_ie_len = elen;
87 break;
88 default:
89 wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
90 "information element ignored "
91 "(type=%d len=%lu)",
92 pos[3], (unsigned long) elen);
93 return -1;
94 }
95 break;
96
97 case OUI_WFA:
98 switch (pos[3]) {
99 case P2P_OUI_TYPE:
100 /* Wi-Fi Alliance - P2P IE */
101 elems->p2p = pos;
102 elems->p2p_len = elen;
103 break;
104 case WFD_OUI_TYPE:
105 /* Wi-Fi Alliance - WFD IE */
106 elems->wfd = pos;
107 elems->wfd_len = elen;
108 break;
109 case HS20_INDICATION_OUI_TYPE:
110 /* Hotspot 2.0 */
111 elems->hs20 = pos;
112 elems->hs20_len = elen;
113 break;
114 case HS20_OSEN_OUI_TYPE:
115 /* Hotspot 2.0 OSEN */
116 elems->osen = pos;
117 elems->osen_len = elen;
118 break;
119 case MBO_OUI_TYPE:
120 /* MBO-OCE */
121 elems->mbo = pos;
122 elems->mbo_len = elen;
123 break;
124 case HS20_ROAMING_CONS_SEL_OUI_TYPE:
125 /* Hotspot 2.0 Roaming Consortium Selection */
126 elems->roaming_cons_sel = pos;
127 elems->roaming_cons_sel_len = elen;
128 break;
129 case MULTI_AP_OUI_TYPE:
130 elems->multi_ap = pos;
131 elems->multi_ap_len = elen;
132 break;
133 default:
134 wpa_printf(MSG_MSGDUMP, "Unknown WFA "
135 "information element ignored "
136 "(type=%d len=%lu)",
137 pos[3], (unsigned long) elen);
138 return -1;
139 }
140 break;
141
142 case OUI_BROADCOM:
143 switch (pos[3]) {
144 case VENDOR_HT_CAPAB_OUI_TYPE:
145 elems->vendor_ht_cap = pos;
146 elems->vendor_ht_cap_len = elen;
147 break;
148 case VENDOR_VHT_TYPE:
149 if (elen > 4 &&
150 (pos[4] == VENDOR_VHT_SUBTYPE ||
151 pos[4] == VENDOR_VHT_SUBTYPE2)) {
152 elems->vendor_vht = pos;
153 elems->vendor_vht_len = elen;
154 } else
155 return -1;
156 break;
157 default:
158 wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
159 "information element ignored "
160 "(type=%d len=%lu)",
161 pos[3], (unsigned long) elen);
162 return -1;
163 }
164 break;
165
166 case OUI_QCA:
167 switch (pos[3]) {
168 case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
169 elems->pref_freq_list = pos;
170 elems->pref_freq_list_len = elen;
171 break;
172 default:
173 wpa_printf(MSG_EXCESSIVE,
174 "Unknown QCA information element ignored (type=%d len=%lu)",
175 pos[3], (unsigned long) elen);
176 return -1;
177 }
178 break;
179
180 default:
181 wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
182 "information element ignored (vendor OUI "
183 "%02x:%02x:%02x len=%lu)",
184 pos[0], pos[1], pos[2], (unsigned long) elen);
185 return -1;
186 }
187
188 return 0;
189 }
190
191
ieee802_11_parse_extension(const u8 * pos,size_t elen,struct ieee802_11_elems * elems,int show_errors)192 static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
193 struct ieee802_11_elems *elems,
194 int show_errors)
195 {
196 u8 ext_id;
197
198 if (elen < 1) {
199 if (show_errors) {
200 wpa_printf(MSG_MSGDUMP,
201 "short information element (Ext)");
202 }
203 return -1;
204 }
205
206 ext_id = *pos++;
207 elen--;
208
209 switch (ext_id) {
210 case WLAN_EID_EXT_ASSOC_DELAY_INFO:
211 if (elen != 1)
212 break;
213 elems->assoc_delay_info = pos;
214 break;
215 case WLAN_EID_EXT_FILS_REQ_PARAMS:
216 if (elen < 3)
217 break;
218 elems->fils_req_params = pos;
219 elems->fils_req_params_len = elen;
220 break;
221 case WLAN_EID_EXT_FILS_KEY_CONFIRM:
222 elems->fils_key_confirm = pos;
223 elems->fils_key_confirm_len = elen;
224 break;
225 case WLAN_EID_EXT_FILS_SESSION:
226 if (elen != FILS_SESSION_LEN)
227 break;
228 elems->fils_session = pos;
229 break;
230 case WLAN_EID_EXT_FILS_HLP_CONTAINER:
231 if (elen < 2 * ETH_ALEN)
232 break;
233 elems->fils_hlp = pos;
234 elems->fils_hlp_len = elen;
235 break;
236 case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
237 if (elen < 1)
238 break;
239 elems->fils_ip_addr_assign = pos;
240 elems->fils_ip_addr_assign_len = elen;
241 break;
242 case WLAN_EID_EXT_KEY_DELIVERY:
243 if (elen < WPA_KEY_RSC_LEN)
244 break;
245 elems->key_delivery = pos;
246 elems->key_delivery_len = elen;
247 break;
248 case WLAN_EID_EXT_FILS_WRAPPED_DATA:
249 elems->fils_wrapped_data = pos;
250 elems->fils_wrapped_data_len = elen;
251 break;
252 case WLAN_EID_EXT_FILS_PUBLIC_KEY:
253 if (elen < 1)
254 break;
255 elems->fils_pk = pos;
256 elems->fils_pk_len = elen;
257 break;
258 case WLAN_EID_EXT_FILS_NONCE:
259 if (elen != FILS_NONCE_LEN)
260 break;
261 elems->fils_nonce = pos;
262 break;
263 case WLAN_EID_EXT_OWE_DH_PARAM:
264 if (elen < 2)
265 break;
266 elems->owe_dh = pos;
267 elems->owe_dh_len = elen;
268 break;
269 case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
270 elems->password_id = pos;
271 elems->password_id_len = elen;
272 break;
273 case WLAN_EID_EXT_HE_CAPABILITIES:
274 elems->he_capabilities = pos;
275 elems->he_capabilities_len = elen;
276 break;
277 case WLAN_EID_EXT_HE_OPERATION:
278 elems->he_operation = pos;
279 elems->he_operation_len = elen;
280 break;
281 case WLAN_EID_EXT_OCV_OCI:
282 elems->oci = pos;
283 elems->oci_len = elen;
284 break;
285 default:
286 if (show_errors) {
287 wpa_printf(MSG_MSGDUMP,
288 "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
289 ext_id, (unsigned int) elen);
290 }
291 return -1;
292 }
293
294 return 0;
295 }
296
297
298 /**
299 * ieee802_11_parse_elems - Parse information elements in management frames
300 * @start: Pointer to the start of IEs
301 * @len: Length of IE buffer in octets
302 * @elems: Data structure for parsed elements
303 * @show_errors: Whether to show parsing errors in debug log
304 * Returns: Parsing result
305 */
ieee802_11_parse_elems(const u8 * start,size_t len,struct ieee802_11_elems * elems,int show_errors)306 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
307 struct ieee802_11_elems *elems,
308 int show_errors)
309 {
310 const struct element *elem;
311 int unknown = 0;
312
313 os_memset(elems, 0, sizeof(*elems));
314
315 if (!start)
316 return ParseOK;
317
318 for_each_element(elem, start, len) {
319 u8 id = elem->id, elen = elem->datalen;
320 const u8 *pos = elem->data;
321
322 switch (id) {
323 case WLAN_EID_SSID:
324 if (elen > SSID_MAX_LEN) {
325 wpa_printf(MSG_DEBUG,
326 "Ignored too long SSID element (elen=%u)",
327 elen);
328 break;
329 }
330 elems->ssid = pos;
331 elems->ssid_len = elen;
332 break;
333 case WLAN_EID_SUPP_RATES:
334 elems->supp_rates = pos;
335 elems->supp_rates_len = elen;
336 break;
337 case WLAN_EID_DS_PARAMS:
338 if (elen < 1)
339 break;
340 elems->ds_params = pos;
341 break;
342 case WLAN_EID_CF_PARAMS:
343 case WLAN_EID_TIM:
344 break;
345 case WLAN_EID_CHALLENGE:
346 elems->challenge = pos;
347 elems->challenge_len = elen;
348 break;
349 case WLAN_EID_ERP_INFO:
350 if (elen < 1)
351 break;
352 elems->erp_info = pos;
353 break;
354 case WLAN_EID_EXT_SUPP_RATES:
355 elems->ext_supp_rates = pos;
356 elems->ext_supp_rates_len = elen;
357 break;
358 case WLAN_EID_VENDOR_SPECIFIC:
359 if (ieee802_11_parse_vendor_specific(pos, elen,
360 elems,
361 show_errors))
362 unknown++;
363 break;
364 case WLAN_EID_RSN:
365 elems->rsn_ie = pos;
366 elems->rsn_ie_len = elen;
367 break;
368 case WLAN_EID_PWR_CAPABILITY:
369 if (elen < 2)
370 break;
371 elems->power_capab = pos;
372 elems->power_capab_len = elen;
373 break;
374 case WLAN_EID_SUPPORTED_CHANNELS:
375 elems->supp_channels = pos;
376 elems->supp_channels_len = elen;
377 break;
378 case WLAN_EID_MOBILITY_DOMAIN:
379 if (elen < sizeof(struct rsn_mdie))
380 break;
381 elems->mdie = pos;
382 elems->mdie_len = elen;
383 break;
384 case WLAN_EID_FAST_BSS_TRANSITION:
385 if (elen < sizeof(struct rsn_ftie))
386 break;
387 elems->ftie = pos;
388 elems->ftie_len = elen;
389 break;
390 case WLAN_EID_TIMEOUT_INTERVAL:
391 if (elen != 5)
392 break;
393 elems->timeout_int = pos;
394 break;
395 case WLAN_EID_HT_CAP:
396 if (elen < sizeof(struct ieee80211_ht_capabilities))
397 break;
398 elems->ht_capabilities = pos;
399 break;
400 case WLAN_EID_HT_OPERATION:
401 if (elen < sizeof(struct ieee80211_ht_operation))
402 break;
403 elems->ht_operation = pos;
404 break;
405 case WLAN_EID_MESH_CONFIG:
406 elems->mesh_config = pos;
407 elems->mesh_config_len = elen;
408 break;
409 case WLAN_EID_MESH_ID:
410 elems->mesh_id = pos;
411 elems->mesh_id_len = elen;
412 break;
413 case WLAN_EID_PEER_MGMT:
414 elems->peer_mgmt = pos;
415 elems->peer_mgmt_len = elen;
416 break;
417 case WLAN_EID_VHT_CAP:
418 if (elen < sizeof(struct ieee80211_vht_capabilities))
419 break;
420 elems->vht_capabilities = pos;
421 break;
422 case WLAN_EID_VHT_OPERATION:
423 if (elen < sizeof(struct ieee80211_vht_operation))
424 break;
425 elems->vht_operation = pos;
426 break;
427 case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
428 if (elen != 1)
429 break;
430 elems->vht_opmode_notif = pos;
431 break;
432 case WLAN_EID_LINK_ID:
433 if (elen < 18)
434 break;
435 elems->link_id = pos;
436 break;
437 case WLAN_EID_INTERWORKING:
438 elems->interworking = pos;
439 elems->interworking_len = elen;
440 break;
441 case WLAN_EID_QOS_MAP_SET:
442 if (elen < 16)
443 break;
444 elems->qos_map_set = pos;
445 elems->qos_map_set_len = elen;
446 break;
447 case WLAN_EID_EXT_CAPAB:
448 elems->ext_capab = pos;
449 elems->ext_capab_len = elen;
450 break;
451 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
452 if (elen < 3)
453 break;
454 elems->bss_max_idle_period = pos;
455 break;
456 case WLAN_EID_SSID_LIST:
457 elems->ssid_list = pos;
458 elems->ssid_list_len = elen;
459 break;
460 case WLAN_EID_AMPE:
461 elems->ampe = pos;
462 elems->ampe_len = elen;
463 break;
464 case WLAN_EID_MIC:
465 elems->mic = pos;
466 elems->mic_len = elen;
467 /* after mic everything is encrypted, so stop. */
468 goto done;
469 case WLAN_EID_MULTI_BAND:
470 if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
471 wpa_printf(MSG_MSGDUMP,
472 "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
473 id, elen);
474 break;
475 }
476
477 elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
478 elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
479 elems->mb_ies.nof_ies++;
480 break;
481 case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
482 elems->supp_op_classes = pos;
483 elems->supp_op_classes_len = elen;
484 break;
485 case WLAN_EID_RRM_ENABLED_CAPABILITIES:
486 elems->rrm_enabled = pos;
487 elems->rrm_enabled_len = elen;
488 break;
489 case WLAN_EID_CAG_NUMBER:
490 elems->cag_number = pos;
491 elems->cag_number_len = elen;
492 break;
493 case WLAN_EID_AP_CSN:
494 if (elen < 1)
495 break;
496 elems->ap_csn = pos;
497 break;
498 case WLAN_EID_FILS_INDICATION:
499 if (elen < 2)
500 break;
501 elems->fils_indic = pos;
502 elems->fils_indic_len = elen;
503 break;
504 case WLAN_EID_DILS:
505 if (elen < 2)
506 break;
507 elems->dils = pos;
508 elems->dils_len = elen;
509 break;
510 case WLAN_EID_FRAGMENT:
511 /* TODO */
512 break;
513 case WLAN_EID_EXTENSION:
514 if (ieee802_11_parse_extension(pos, elen, elems,
515 show_errors))
516 unknown++;
517 break;
518 default:
519 unknown++;
520 if (!show_errors)
521 break;
522 wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
523 "ignored unknown element (id=%d elen=%d)",
524 id, elen);
525 break;
526 }
527 }
528
529 if (!for_each_element_completed(elem, start, len)) {
530 if (show_errors) {
531 wpa_printf(MSG_DEBUG,
532 "IEEE 802.11 element parse failed @%d",
533 (int) (start + len - (const u8 *) elem));
534 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
535 }
536 return ParseFailed;
537 }
538
539 done:
540 return unknown ? ParseUnknown : ParseOK;
541 }
542
543
ieee802_11_ie_count(const u8 * ies,size_t ies_len)544 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
545 {
546 const struct element *elem;
547 int count = 0;
548
549 if (ies == NULL)
550 return 0;
551
552 for_each_element(elem, ies, ies_len)
553 count++;
554
555 return count;
556 }
557
558
ieee802_11_vendor_ie_concat(const u8 * ies,size_t ies_len,u32 oui_type)559 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
560 u32 oui_type)
561 {
562 struct wpabuf *buf;
563 const struct element *elem, *found = NULL;
564
565 for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
566 if (elem->datalen >= 4 &&
567 WPA_GET_BE32(elem->data) == oui_type) {
568 found = elem;
569 break;
570 }
571 }
572
573 if (!found)
574 return NULL; /* No specified vendor IE found */
575
576 buf = wpabuf_alloc(ies_len);
577 if (buf == NULL)
578 return NULL;
579
580 /*
581 * There may be multiple vendor IEs in the message, so need to
582 * concatenate their data fields.
583 */
584 for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
585 if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type)
586 wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4);
587 }
588
589 return buf;
590 }
591
592
get_hdr_bssid(const struct ieee80211_hdr * hdr,size_t len)593 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
594 {
595 u16 fc, type, stype;
596
597 /*
598 * PS-Poll frames are 16 bytes. All other frames are
599 * 24 bytes or longer.
600 */
601 if (len < 16)
602 return NULL;
603
604 fc = le_to_host16(hdr->frame_control);
605 type = WLAN_FC_GET_TYPE(fc);
606 stype = WLAN_FC_GET_STYPE(fc);
607
608 switch (type) {
609 case WLAN_FC_TYPE_DATA:
610 if (len < 24)
611 return NULL;
612 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
613 case WLAN_FC_FROMDS | WLAN_FC_TODS:
614 case WLAN_FC_TODS:
615 return hdr->addr1;
616 case WLAN_FC_FROMDS:
617 return hdr->addr2;
618 default:
619 return NULL;
620 }
621 case WLAN_FC_TYPE_CTRL:
622 if (stype != WLAN_FC_STYPE_PSPOLL)
623 return NULL;
624 return hdr->addr1;
625 case WLAN_FC_TYPE_MGMT:
626 return hdr->addr3;
627 default:
628 return NULL;
629 }
630 }
631
632
hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],const char * name,const char * val)633 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
634 const char *name, const char *val)
635 {
636 int num, v;
637 const char *pos;
638 struct hostapd_wmm_ac_params *ac;
639
640 /* skip 'wme_ac_' or 'wmm_ac_' prefix */
641 pos = name + 7;
642 if (os_strncmp(pos, "be_", 3) == 0) {
643 num = 0;
644 pos += 3;
645 } else if (os_strncmp(pos, "bk_", 3) == 0) {
646 num = 1;
647 pos += 3;
648 } else if (os_strncmp(pos, "vi_", 3) == 0) {
649 num = 2;
650 pos += 3;
651 } else if (os_strncmp(pos, "vo_", 3) == 0) {
652 num = 3;
653 pos += 3;
654 } else {
655 wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
656 return -1;
657 }
658
659 ac = &wmm_ac_params[num];
660
661 if (os_strcmp(pos, "aifs") == 0) {
662 v = atoi(val);
663 if (v < 1 || v > 255) {
664 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
665 return -1;
666 }
667 ac->aifs = v;
668 } else if (os_strcmp(pos, "cwmin") == 0) {
669 v = atoi(val);
670 if (v < 0 || v > 15) {
671 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
672 return -1;
673 }
674 ac->cwmin = v;
675 } else if (os_strcmp(pos, "cwmax") == 0) {
676 v = atoi(val);
677 if (v < 0 || v > 15) {
678 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
679 return -1;
680 }
681 ac->cwmax = v;
682 } else if (os_strcmp(pos, "txop_limit") == 0) {
683 v = atoi(val);
684 if (v < 0 || v > 0xffff) {
685 wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
686 return -1;
687 }
688 ac->txop_limit = v;
689 } else if (os_strcmp(pos, "acm") == 0) {
690 v = atoi(val);
691 if (v < 0 || v > 1) {
692 wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
693 return -1;
694 }
695 ac->admission_control_mandatory = v;
696 } else {
697 wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
698 return -1;
699 }
700
701 return 0;
702 }
703
704
ieee80211_freq_to_chan(int freq,u8 * channel)705 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
706 {
707 u8 op_class;
708
709 return ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT,
710 &op_class, channel);
711 }
712
713
714 /**
715 * ieee80211_freq_to_channel_ext - Convert frequency into channel info
716 * for HT40 and VHT. DFS channels are not covered.
717 * @freq: Frequency (MHz) to convert
718 * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
719 * @vht: VHT channel width (CHANWIDTH_*)
720 * @op_class: Buffer for returning operating class
721 * @channel: Buffer for returning channel number
722 * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
723 */
ieee80211_freq_to_channel_ext(unsigned int freq,int sec_channel,int vht,u8 * op_class,u8 * channel)724 enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
725 int sec_channel, int vht,
726 u8 *op_class, u8 *channel)
727 {
728 u8 vht_opclass;
729
730 /* TODO: more operating classes */
731
732 if (sec_channel > 1 || sec_channel < -1)
733 return NUM_HOSTAPD_MODES;
734
735 if (freq >= 2412 && freq <= 2472) {
736 if ((freq - 2407) % 5)
737 return NUM_HOSTAPD_MODES;
738
739 if (vht)
740 return NUM_HOSTAPD_MODES;
741
742 /* 2.407 GHz, channels 1..13 */
743 if (sec_channel == 1)
744 *op_class = 83;
745 else if (sec_channel == -1)
746 *op_class = 84;
747 else
748 *op_class = 81;
749
750 *channel = (freq - 2407) / 5;
751
752 return HOSTAPD_MODE_IEEE80211G;
753 }
754
755 if (freq == 2484) {
756 if (sec_channel || vht)
757 return NUM_HOSTAPD_MODES;
758
759 *op_class = 82; /* channel 14 */
760 *channel = 14;
761
762 return HOSTAPD_MODE_IEEE80211B;
763 }
764
765 if (freq >= 4900 && freq < 5000) {
766 if ((freq - 4000) % 5)
767 return NUM_HOSTAPD_MODES;
768 *channel = (freq - 4000) / 5;
769 *op_class = 0; /* TODO */
770 return HOSTAPD_MODE_IEEE80211A;
771 }
772
773 switch (vht) {
774 case CHANWIDTH_80MHZ:
775 vht_opclass = 128;
776 break;
777 case CHANWIDTH_160MHZ:
778 vht_opclass = 129;
779 break;
780 case CHANWIDTH_80P80MHZ:
781 vht_opclass = 130;
782 break;
783 default:
784 vht_opclass = 0;
785 break;
786 }
787
788 /* 5 GHz, channels 36..48 */
789 if (freq >= 5180 && freq <= 5240) {
790 if ((freq - 5000) % 5)
791 return NUM_HOSTAPD_MODES;
792
793 if (vht_opclass)
794 *op_class = vht_opclass;
795 else if (sec_channel == 1)
796 *op_class = 116;
797 else if (sec_channel == -1)
798 *op_class = 117;
799 else
800 *op_class = 115;
801
802 *channel = (freq - 5000) / 5;
803
804 return HOSTAPD_MODE_IEEE80211A;
805 }
806
807 /* 5 GHz, channels 52..64 */
808 if (freq >= 5260 && freq <= 5320) {
809 if ((freq - 5000) % 5)
810 return NUM_HOSTAPD_MODES;
811
812 if (vht_opclass)
813 *op_class = vht_opclass;
814 else if (sec_channel == 1)
815 *op_class = 119;
816 else if (sec_channel == -1)
817 *op_class = 120;
818 else
819 *op_class = 118;
820
821 *channel = (freq - 5000) / 5;
822
823 return HOSTAPD_MODE_IEEE80211A;
824 }
825
826 /* 5 GHz, channels 149..169 */
827 if (freq >= 5745 && freq <= 5845) {
828 if ((freq - 5000) % 5)
829 return NUM_HOSTAPD_MODES;
830
831 if (vht_opclass)
832 *op_class = vht_opclass;
833 else if (sec_channel == 1)
834 *op_class = 126;
835 else if (sec_channel == -1)
836 *op_class = 127;
837 else if (freq <= 5805)
838 *op_class = 124;
839 else
840 *op_class = 125;
841
842 *channel = (freq - 5000) / 5;
843
844 return HOSTAPD_MODE_IEEE80211A;
845 }
846
847 /* 5 GHz, channels 100..140 */
848 if (freq >= 5000 && freq <= 5700) {
849 if ((freq - 5000) % 5)
850 return NUM_HOSTAPD_MODES;
851
852 if (vht_opclass)
853 *op_class = vht_opclass;
854 else if (sec_channel == 1)
855 *op_class = 122;
856 else if (sec_channel == -1)
857 *op_class = 123;
858 else
859 *op_class = 121;
860
861 *channel = (freq - 5000) / 5;
862
863 return HOSTAPD_MODE_IEEE80211A;
864 }
865
866 if (freq >= 5000 && freq < 5900) {
867 if ((freq - 5000) % 5)
868 return NUM_HOSTAPD_MODES;
869 *channel = (freq - 5000) / 5;
870 *op_class = 0; /* TODO */
871 return HOSTAPD_MODE_IEEE80211A;
872 }
873
874 /* 56.16 GHz, channel 1..4 */
875 if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
876 if (sec_channel || vht)
877 return NUM_HOSTAPD_MODES;
878
879 *channel = (freq - 56160) / 2160;
880 *op_class = 180;
881
882 return HOSTAPD_MODE_IEEE80211AD;
883 }
884
885 return NUM_HOSTAPD_MODES;
886 }
887
888
ieee80211_chaninfo_to_channel(unsigned int freq,enum chan_width chanwidth,int sec_channel,u8 * op_class,u8 * channel)889 int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
890 int sec_channel, u8 *op_class, u8 *channel)
891 {
892 int vht = CHAN_WIDTH_UNKNOWN;
893
894 switch (chanwidth) {
895 case CHAN_WIDTH_UNKNOWN:
896 case CHAN_WIDTH_20_NOHT:
897 case CHAN_WIDTH_20:
898 case CHAN_WIDTH_40:
899 vht = CHANWIDTH_USE_HT;
900 break;
901 case CHAN_WIDTH_80:
902 vht = CHANWIDTH_80MHZ;
903 break;
904 case CHAN_WIDTH_80P80:
905 vht = CHANWIDTH_80P80MHZ;
906 break;
907 case CHAN_WIDTH_160:
908 vht = CHANWIDTH_160MHZ;
909 break;
910 }
911
912 if (ieee80211_freq_to_channel_ext(freq, sec_channel, vht, op_class,
913 channel) == NUM_HOSTAPD_MODES) {
914 wpa_printf(MSG_WARNING,
915 "Cannot determine operating class and channel (freq=%u chanwidth=%d sec_channel=%d)",
916 freq, chanwidth, sec_channel);
917 return -1;
918 }
919
920 return 0;
921 }
922
923
924 static const char *const us_op_class_cc[] = {
925 "US", "CA", NULL
926 };
927
928 static const char *const eu_op_class_cc[] = {
929 "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
930 "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
931 "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
932 "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
933 };
934
935 static const char *const jp_op_class_cc[] = {
936 "JP", NULL
937 };
938
939 static const char *const cn_op_class_cc[] = {
940 "CN", NULL
941 };
942
943
country_match(const char * const cc[],const char * const country)944 static int country_match(const char *const cc[], const char *const country)
945 {
946 int i;
947
948 if (country == NULL)
949 return 0;
950 for (i = 0; cc[i]; i++) {
951 if (cc[i][0] == country[0] && cc[i][1] == country[1])
952 return 1;
953 }
954
955 return 0;
956 }
957
958
ieee80211_chan_to_freq_us(u8 op_class,u8 chan)959 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
960 {
961 switch (op_class) {
962 case 12: /* channels 1..11 */
963 case 32: /* channels 1..7; 40 MHz */
964 case 33: /* channels 5..11; 40 MHz */
965 if (chan < 1 || chan > 11)
966 return -1;
967 return 2407 + 5 * chan;
968 case 1: /* channels 36,40,44,48 */
969 case 2: /* channels 52,56,60,64; dfs */
970 case 22: /* channels 36,44; 40 MHz */
971 case 23: /* channels 52,60; 40 MHz */
972 case 27: /* channels 40,48; 40 MHz */
973 case 28: /* channels 56,64; 40 MHz */
974 if (chan < 36 || chan > 64)
975 return -1;
976 return 5000 + 5 * chan;
977 case 4: /* channels 100-144 */
978 case 24: /* channels 100-140; 40 MHz */
979 if (chan < 100 || chan > 144)
980 return -1;
981 return 5000 + 5 * chan;
982 case 3: /* channels 149,153,157,161 */
983 case 25: /* channels 149,157; 40 MHz */
984 case 26: /* channels 149,157; 40 MHz */
985 case 30: /* channels 153,161; 40 MHz */
986 case 31: /* channels 153,161; 40 MHz */
987 if (chan < 149 || chan > 161)
988 return -1;
989 return 5000 + 5 * chan;
990 case 5: /* channels 149,153,157,161,165 */
991 if (chan < 149 || chan > 165)
992 return -1;
993 return 5000 + 5 * chan;
994 case 34: /* 60 GHz band, channels 1..3 */
995 if (chan < 1 || chan > 3)
996 return -1;
997 return 56160 + 2160 * chan;
998 }
999 return -1;
1000 }
1001
1002
ieee80211_chan_to_freq_eu(u8 op_class,u8 chan)1003 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
1004 {
1005 switch (op_class) {
1006 case 4: /* channels 1..13 */
1007 case 11: /* channels 1..9; 40 MHz */
1008 case 12: /* channels 5..13; 40 MHz */
1009 if (chan < 1 || chan > 13)
1010 return -1;
1011 return 2407 + 5 * chan;
1012 case 1: /* channels 36,40,44,48 */
1013 case 2: /* channels 52,56,60,64; dfs */
1014 case 5: /* channels 36,44; 40 MHz */
1015 case 6: /* channels 52,60; 40 MHz */
1016 case 8: /* channels 40,48; 40 MHz */
1017 case 9: /* channels 56,64; 40 MHz */
1018 if (chan < 36 || chan > 64)
1019 return -1;
1020 return 5000 + 5 * chan;
1021 case 3: /* channels 100-140 */
1022 case 7: /* channels 100-132; 40 MHz */
1023 case 10: /* channels 104-136; 40 MHz */
1024 case 16: /* channels 100-140 */
1025 if (chan < 100 || chan > 140)
1026 return -1;
1027 return 5000 + 5 * chan;
1028 case 17: /* channels 149,153,157,161,165,169 */
1029 if (chan < 149 || chan > 169)
1030 return -1;
1031 return 5000 + 5 * chan;
1032 case 18: /* 60 GHz band, channels 1..4 */
1033 if (chan < 1 || chan > 4)
1034 return -1;
1035 return 56160 + 2160 * chan;
1036 }
1037 return -1;
1038 }
1039
1040
ieee80211_chan_to_freq_jp(u8 op_class,u8 chan)1041 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
1042 {
1043 switch (op_class) {
1044 case 30: /* channels 1..13 */
1045 case 56: /* channels 1..9; 40 MHz */
1046 case 57: /* channels 5..13; 40 MHz */
1047 if (chan < 1 || chan > 13)
1048 return -1;
1049 return 2407 + 5 * chan;
1050 case 31: /* channel 14 */
1051 if (chan != 14)
1052 return -1;
1053 return 2414 + 5 * chan;
1054 case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
1055 case 32: /* channels 52,56,60,64 */
1056 case 33: /* channels 52,56,60,64 */
1057 case 36: /* channels 36,44; 40 MHz */
1058 case 37: /* channels 52,60; 40 MHz */
1059 case 38: /* channels 52,60; 40 MHz */
1060 case 41: /* channels 40,48; 40 MHz */
1061 case 42: /* channels 56,64; 40 MHz */
1062 case 43: /* channels 56,64; 40 MHz */
1063 if (chan < 34 || chan > 64)
1064 return -1;
1065 return 5000 + 5 * chan;
1066 case 34: /* channels 100-140 */
1067 case 35: /* channels 100-140 */
1068 case 39: /* channels 100-132; 40 MHz */
1069 case 40: /* channels 100-132; 40 MHz */
1070 case 44: /* channels 104-136; 40 MHz */
1071 case 45: /* channels 104-136; 40 MHz */
1072 case 58: /* channels 100-140 */
1073 if (chan < 100 || chan > 140)
1074 return -1;
1075 return 5000 + 5 * chan;
1076 case 59: /* 60 GHz band, channels 1..4 */
1077 if (chan < 1 || chan > 3)
1078 return -1;
1079 return 56160 + 2160 * chan;
1080 }
1081 return -1;
1082 }
1083
1084
ieee80211_chan_to_freq_cn(u8 op_class,u8 chan)1085 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
1086 {
1087 switch (op_class) {
1088 case 7: /* channels 1..13 */
1089 case 8: /* channels 1..9; 40 MHz */
1090 case 9: /* channels 5..13; 40 MHz */
1091 if (chan < 1 || chan > 13)
1092 return -1;
1093 return 2407 + 5 * chan;
1094 case 1: /* channels 36,40,44,48 */
1095 case 2: /* channels 52,56,60,64; dfs */
1096 case 4: /* channels 36,44; 40 MHz */
1097 case 5: /* channels 52,60; 40 MHz */
1098 if (chan < 36 || chan > 64)
1099 return -1;
1100 return 5000 + 5 * chan;
1101 case 3: /* channels 149,153,157,161,165 */
1102 case 6: /* channels 149,157; 40 MHz */
1103 if (chan < 149 || chan > 165)
1104 return -1;
1105 return 5000 + 5 * chan;
1106 }
1107 return -1;
1108 }
1109
1110
ieee80211_chan_to_freq_global(u8 op_class,u8 chan)1111 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
1112 {
1113 /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
1114 switch (op_class) {
1115 case 81:
1116 /* channels 1..13 */
1117 if (chan < 1 || chan > 13)
1118 return -1;
1119 return 2407 + 5 * chan;
1120 case 82:
1121 /* channel 14 */
1122 if (chan != 14)
1123 return -1;
1124 return 2414 + 5 * chan;
1125 case 83: /* channels 1..9; 40 MHz */
1126 case 84: /* channels 5..13; 40 MHz */
1127 if (chan < 1 || chan > 13)
1128 return -1;
1129 return 2407 + 5 * chan;
1130 case 115: /* channels 36,40,44,48; indoor only */
1131 case 116: /* channels 36,44; 40 MHz; indoor only */
1132 case 117: /* channels 40,48; 40 MHz; indoor only */
1133 case 118: /* channels 52,56,60,64; dfs */
1134 case 119: /* channels 52,60; 40 MHz; dfs */
1135 case 120: /* channels 56,64; 40 MHz; dfs */
1136 if (chan < 36 || chan > 64)
1137 return -1;
1138 return 5000 + 5 * chan;
1139 case 121: /* channels 100-140 */
1140 case 122: /* channels 100-142; 40 MHz */
1141 case 123: /* channels 104-136; 40 MHz */
1142 if (chan < 100 || chan > 140)
1143 return -1;
1144 return 5000 + 5 * chan;
1145 case 124: /* channels 149,153,157,161 */
1146 case 126: /* channels 149,157; 40 MHz */
1147 case 127: /* channels 153,161; 40 MHz */
1148 if (chan < 149 || chan > 161)
1149 return -1;
1150 return 5000 + 5 * chan;
1151 case 125: /* channels 149,153,157,161,165,169 */
1152 if (chan < 149 || chan > 169)
1153 return -1;
1154 return 5000 + 5 * chan;
1155 case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
1156 case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
1157 if (chan < 36 || chan > 161)
1158 return -1;
1159 return 5000 + 5 * chan;
1160 case 129: /* center freqs 50, 114; 160 MHz */
1161 if (chan < 36 || chan > 128)
1162 return -1;
1163 return 5000 + 5 * chan;
1164 case 180: /* 60 GHz band, channels 1..4 */
1165 if (chan < 1 || chan > 4)
1166 return -1;
1167 return 56160 + 2160 * chan;
1168 }
1169 return -1;
1170 }
1171
1172 /**
1173 * ieee80211_chan_to_freq - Convert channel info to frequency
1174 * @country: Country code, if known; otherwise, global operating class is used
1175 * @op_class: Operating class
1176 * @chan: Channel number
1177 * Returns: Frequency in MHz or -1 if the specified channel is unknown
1178 */
ieee80211_chan_to_freq(const char * country,u8 op_class,u8 chan)1179 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
1180 {
1181 int freq;
1182
1183 if (country_match(us_op_class_cc, country)) {
1184 freq = ieee80211_chan_to_freq_us(op_class, chan);
1185 if (freq > 0)
1186 return freq;
1187 }
1188
1189 if (country_match(eu_op_class_cc, country)) {
1190 freq = ieee80211_chan_to_freq_eu(op_class, chan);
1191 if (freq > 0)
1192 return freq;
1193 }
1194
1195 if (country_match(jp_op_class_cc, country)) {
1196 freq = ieee80211_chan_to_freq_jp(op_class, chan);
1197 if (freq > 0)
1198 return freq;
1199 }
1200
1201 if (country_match(cn_op_class_cc, country)) {
1202 freq = ieee80211_chan_to_freq_cn(op_class, chan);
1203 if (freq > 0)
1204 return freq;
1205 }
1206
1207 return ieee80211_chan_to_freq_global(op_class, chan);
1208 }
1209
1210
ieee80211_is_dfs(int freq,const struct hostapd_hw_modes * modes,u16 num_modes)1211 int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
1212 u16 num_modes)
1213 {
1214 int i, j;
1215
1216 if (!modes || !num_modes)
1217 return (freq >= 5260 && freq <= 5320) ||
1218 (freq >= 5500 && freq <= 5700);
1219
1220 for (i = 0; i < num_modes; i++) {
1221 for (j = 0; j < modes[i].num_channels; j++) {
1222 if (modes[i].channels[j].freq == freq &&
1223 (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR))
1224 return 1;
1225 }
1226 }
1227
1228 return 0;
1229 }
1230
1231
is_11b(u8 rate)1232 static int is_11b(u8 rate)
1233 {
1234 return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
1235 }
1236
1237
supp_rates_11b_only(struct ieee802_11_elems * elems)1238 int supp_rates_11b_only(struct ieee802_11_elems *elems)
1239 {
1240 int num_11b = 0, num_others = 0;
1241 int i;
1242
1243 if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
1244 return 0;
1245
1246 for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
1247 if (is_11b(elems->supp_rates[i]))
1248 num_11b++;
1249 else
1250 num_others++;
1251 }
1252
1253 for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
1254 i++) {
1255 if (is_11b(elems->ext_supp_rates[i]))
1256 num_11b++;
1257 else
1258 num_others++;
1259 }
1260
1261 return num_11b > 0 && num_others == 0;
1262 }
1263
1264
fc2str(u16 fc)1265 const char * fc2str(u16 fc)
1266 {
1267 u16 stype = WLAN_FC_GET_STYPE(fc);
1268 #define C2S(x) case x: return #x;
1269
1270 switch (WLAN_FC_GET_TYPE(fc)) {
1271 case WLAN_FC_TYPE_MGMT:
1272 switch (stype) {
1273 C2S(WLAN_FC_STYPE_ASSOC_REQ)
1274 C2S(WLAN_FC_STYPE_ASSOC_RESP)
1275 C2S(WLAN_FC_STYPE_REASSOC_REQ)
1276 C2S(WLAN_FC_STYPE_REASSOC_RESP)
1277 C2S(WLAN_FC_STYPE_PROBE_REQ)
1278 C2S(WLAN_FC_STYPE_PROBE_RESP)
1279 C2S(WLAN_FC_STYPE_BEACON)
1280 C2S(WLAN_FC_STYPE_ATIM)
1281 C2S(WLAN_FC_STYPE_DISASSOC)
1282 C2S(WLAN_FC_STYPE_AUTH)
1283 C2S(WLAN_FC_STYPE_DEAUTH)
1284 C2S(WLAN_FC_STYPE_ACTION)
1285 }
1286 break;
1287 case WLAN_FC_TYPE_CTRL:
1288 switch (stype) {
1289 C2S(WLAN_FC_STYPE_PSPOLL)
1290 C2S(WLAN_FC_STYPE_RTS)
1291 C2S(WLAN_FC_STYPE_CTS)
1292 C2S(WLAN_FC_STYPE_ACK)
1293 C2S(WLAN_FC_STYPE_CFEND)
1294 C2S(WLAN_FC_STYPE_CFENDACK)
1295 }
1296 break;
1297 case WLAN_FC_TYPE_DATA:
1298 switch (stype) {
1299 C2S(WLAN_FC_STYPE_DATA)
1300 C2S(WLAN_FC_STYPE_DATA_CFACK)
1301 C2S(WLAN_FC_STYPE_DATA_CFPOLL)
1302 C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
1303 C2S(WLAN_FC_STYPE_NULLFUNC)
1304 C2S(WLAN_FC_STYPE_CFACK)
1305 C2S(WLAN_FC_STYPE_CFPOLL)
1306 C2S(WLAN_FC_STYPE_CFACKPOLL)
1307 C2S(WLAN_FC_STYPE_QOS_DATA)
1308 C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
1309 C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
1310 C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
1311 C2S(WLAN_FC_STYPE_QOS_NULL)
1312 C2S(WLAN_FC_STYPE_QOS_CFPOLL)
1313 C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
1314 }
1315 break;
1316 }
1317 return "WLAN_FC_TYPE_UNKNOWN";
1318 #undef C2S
1319 }
1320
1321
reason2str(u16 reason)1322 const char * reason2str(u16 reason)
1323 {
1324 #define R2S(r) case WLAN_REASON_ ## r: return #r;
1325 switch (reason) {
1326 R2S(UNSPECIFIED)
1327 R2S(PREV_AUTH_NOT_VALID)
1328 R2S(DEAUTH_LEAVING)
1329 R2S(DISASSOC_DUE_TO_INACTIVITY)
1330 R2S(DISASSOC_AP_BUSY)
1331 R2S(CLASS2_FRAME_FROM_NONAUTH_STA)
1332 R2S(CLASS3_FRAME_FROM_NONASSOC_STA)
1333 R2S(DISASSOC_STA_HAS_LEFT)
1334 R2S(STA_REQ_ASSOC_WITHOUT_AUTH)
1335 R2S(PWR_CAPABILITY_NOT_VALID)
1336 R2S(SUPPORTED_CHANNEL_NOT_VALID)
1337 R2S(BSS_TRANSITION_DISASSOC)
1338 R2S(INVALID_IE)
1339 R2S(MICHAEL_MIC_FAILURE)
1340 R2S(4WAY_HANDSHAKE_TIMEOUT)
1341 R2S(GROUP_KEY_UPDATE_TIMEOUT)
1342 R2S(IE_IN_4WAY_DIFFERS)
1343 R2S(GROUP_CIPHER_NOT_VALID)
1344 R2S(PAIRWISE_CIPHER_NOT_VALID)
1345 R2S(AKMP_NOT_VALID)
1346 R2S(UNSUPPORTED_RSN_IE_VERSION)
1347 R2S(INVALID_RSN_IE_CAPAB)
1348 R2S(IEEE_802_1X_AUTH_FAILED)
1349 R2S(CIPHER_SUITE_REJECTED)
1350 R2S(TDLS_TEARDOWN_UNREACHABLE)
1351 R2S(TDLS_TEARDOWN_UNSPECIFIED)
1352 R2S(SSP_REQUESTED_DISASSOC)
1353 R2S(NO_SSP_ROAMING_AGREEMENT)
1354 R2S(BAD_CIPHER_OR_AKM)
1355 R2S(NOT_AUTHORIZED_THIS_LOCATION)
1356 R2S(SERVICE_CHANGE_PRECLUDES_TS)
1357 R2S(UNSPECIFIED_QOS_REASON)
1358 R2S(NOT_ENOUGH_BANDWIDTH)
1359 R2S(DISASSOC_LOW_ACK)
1360 R2S(EXCEEDED_TXOP)
1361 R2S(STA_LEAVING)
1362 R2S(END_TS_BA_DLS)
1363 R2S(UNKNOWN_TS_BA)
1364 R2S(TIMEOUT)
1365 R2S(PEERKEY_MISMATCH)
1366 R2S(AUTHORIZED_ACCESS_LIMIT_REACHED)
1367 R2S(EXTERNAL_SERVICE_REQUIREMENTS)
1368 R2S(INVALID_FT_ACTION_FRAME_COUNT)
1369 R2S(INVALID_PMKID)
1370 R2S(INVALID_MDE)
1371 R2S(INVALID_FTE)
1372 R2S(MESH_PEERING_CANCELLED)
1373 R2S(MESH_MAX_PEERS)
1374 R2S(MESH_CONFIG_POLICY_VIOLATION)
1375 R2S(MESH_CLOSE_RCVD)
1376 R2S(MESH_MAX_RETRIES)
1377 R2S(MESH_CONFIRM_TIMEOUT)
1378 R2S(MESH_INVALID_GTK)
1379 R2S(MESH_INCONSISTENT_PARAMS)
1380 R2S(MESH_INVALID_SECURITY_CAP)
1381 R2S(MESH_PATH_ERROR_NO_PROXY_INFO)
1382 R2S(MESH_PATH_ERROR_NO_FORWARDING_INFO)
1383 R2S(MESH_PATH_ERROR_DEST_UNREACHABLE)
1384 R2S(MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS)
1385 R2S(MESH_CHANNEL_SWITCH_REGULATORY_REQ)
1386 R2S(MESH_CHANNEL_SWITCH_UNSPECIFIED)
1387 }
1388 return "UNKNOWN";
1389 #undef R2S
1390 }
1391
1392
status2str(u16 status)1393 const char * status2str(u16 status)
1394 {
1395 #define S2S(s) case WLAN_STATUS_ ## s: return #s;
1396 switch (status) {
1397 S2S(SUCCESS)
1398 S2S(UNSPECIFIED_FAILURE)
1399 S2S(TDLS_WAKEUP_ALTERNATE)
1400 S2S(TDLS_WAKEUP_REJECT)
1401 S2S(SECURITY_DISABLED)
1402 S2S(UNACCEPTABLE_LIFETIME)
1403 S2S(NOT_IN_SAME_BSS)
1404 S2S(CAPS_UNSUPPORTED)
1405 S2S(REASSOC_NO_ASSOC)
1406 S2S(ASSOC_DENIED_UNSPEC)
1407 S2S(NOT_SUPPORTED_AUTH_ALG)
1408 S2S(UNKNOWN_AUTH_TRANSACTION)
1409 S2S(CHALLENGE_FAIL)
1410 S2S(AUTH_TIMEOUT)
1411 S2S(AP_UNABLE_TO_HANDLE_NEW_STA)
1412 S2S(ASSOC_DENIED_RATES)
1413 S2S(ASSOC_DENIED_NOSHORT)
1414 S2S(SPEC_MGMT_REQUIRED)
1415 S2S(PWR_CAPABILITY_NOT_VALID)
1416 S2S(SUPPORTED_CHANNEL_NOT_VALID)
1417 S2S(ASSOC_DENIED_NO_SHORT_SLOT_TIME)
1418 S2S(ASSOC_DENIED_NO_HT)
1419 S2S(R0KH_UNREACHABLE)
1420 S2S(ASSOC_DENIED_NO_PCO)
1421 S2S(ASSOC_REJECTED_TEMPORARILY)
1422 S2S(ROBUST_MGMT_FRAME_POLICY_VIOLATION)
1423 S2S(UNSPECIFIED_QOS_FAILURE)
1424 S2S(DENIED_INSUFFICIENT_BANDWIDTH)
1425 S2S(DENIED_POOR_CHANNEL_CONDITIONS)
1426 S2S(DENIED_QOS_NOT_SUPPORTED)
1427 S2S(REQUEST_DECLINED)
1428 S2S(INVALID_PARAMETERS)
1429 S2S(REJECTED_WITH_SUGGESTED_CHANGES)
1430 S2S(INVALID_IE)
1431 S2S(GROUP_CIPHER_NOT_VALID)
1432 S2S(PAIRWISE_CIPHER_NOT_VALID)
1433 S2S(AKMP_NOT_VALID)
1434 S2S(UNSUPPORTED_RSN_IE_VERSION)
1435 S2S(INVALID_RSN_IE_CAPAB)
1436 S2S(CIPHER_REJECTED_PER_POLICY)
1437 S2S(TS_NOT_CREATED)
1438 S2S(DIRECT_LINK_NOT_ALLOWED)
1439 S2S(DEST_STA_NOT_PRESENT)
1440 S2S(DEST_STA_NOT_QOS_STA)
1441 S2S(ASSOC_DENIED_LISTEN_INT_TOO_LARGE)
1442 S2S(INVALID_FT_ACTION_FRAME_COUNT)
1443 S2S(INVALID_PMKID)
1444 S2S(INVALID_MDIE)
1445 S2S(INVALID_FTIE)
1446 S2S(REQUESTED_TCLAS_NOT_SUPPORTED)
1447 S2S(INSUFFICIENT_TCLAS_PROCESSING_RESOURCES)
1448 S2S(TRY_ANOTHER_BSS)
1449 S2S(GAS_ADV_PROTO_NOT_SUPPORTED)
1450 S2S(NO_OUTSTANDING_GAS_REQ)
1451 S2S(GAS_RESP_NOT_RECEIVED)
1452 S2S(STA_TIMED_OUT_WAITING_FOR_GAS_RESP)
1453 S2S(GAS_RESP_LARGER_THAN_LIMIT)
1454 S2S(REQ_REFUSED_HOME)
1455 S2S(ADV_SRV_UNREACHABLE)
1456 S2S(REQ_REFUSED_SSPN)
1457 S2S(REQ_REFUSED_UNAUTH_ACCESS)
1458 S2S(INVALID_RSNIE)
1459 S2S(U_APSD_COEX_NOT_SUPPORTED)
1460 S2S(U_APSD_COEX_MODE_NOT_SUPPORTED)
1461 S2S(BAD_INTERVAL_WITH_U_APSD_COEX)
1462 S2S(ANTI_CLOGGING_TOKEN_REQ)
1463 S2S(FINITE_CYCLIC_GROUP_NOT_SUPPORTED)
1464 S2S(CANNOT_FIND_ALT_TBTT)
1465 S2S(TRANSMISSION_FAILURE)
1466 S2S(REQ_TCLAS_NOT_SUPPORTED)
1467 S2S(TCLAS_RESOURCES_EXCHAUSTED)
1468 S2S(REJECTED_WITH_SUGGESTED_BSS_TRANSITION)
1469 S2S(REJECT_WITH_SCHEDULE)
1470 S2S(REJECT_NO_WAKEUP_SPECIFIED)
1471 S2S(SUCCESS_POWER_SAVE_MODE)
1472 S2S(PENDING_ADMITTING_FST_SESSION)
1473 S2S(PERFORMING_FST_NOW)
1474 S2S(PENDING_GAP_IN_BA_WINDOW)
1475 S2S(REJECT_U_PID_SETTING)
1476 S2S(REFUSED_EXTERNAL_REASON)
1477 S2S(REFUSED_AP_OUT_OF_MEMORY)
1478 S2S(REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED)
1479 S2S(QUERY_RESP_OUTSTANDING)
1480 S2S(REJECT_DSE_BAND)
1481 S2S(TCLAS_PROCESSING_TERMINATED)
1482 S2S(TS_SCHEDULE_CONFLICT)
1483 S2S(DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL)
1484 S2S(MCCAOP_RESERVATION_CONFLICT)
1485 S2S(MAF_LIMIT_EXCEEDED)
1486 S2S(MCCA_TRACK_LIMIT_EXCEEDED)
1487 S2S(DENIED_DUE_TO_SPECTRUM_MANAGEMENT)
1488 S2S(ASSOC_DENIED_NO_VHT)
1489 S2S(ENABLEMENT_DENIED)
1490 S2S(RESTRICTION_FROM_AUTHORIZED_GDB)
1491 S2S(AUTHORIZATION_DEENABLED)
1492 S2S(FILS_AUTHENTICATION_FAILURE)
1493 S2S(UNKNOWN_AUTHENTICATION_SERVER)
1494 S2S(UNKNOWN_PASSWORD_IDENTIFIER)
1495 }
1496 return "UNKNOWN";
1497 #undef S2S
1498 }
1499
1500
mb_ies_info_by_ies(struct mb_ies_info * info,const u8 * ies_buf,size_t ies_len)1501 int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
1502 size_t ies_len)
1503 {
1504 const struct element *elem;
1505
1506 os_memset(info, 0, sizeof(*info));
1507
1508 if (!ies_buf)
1509 return 0;
1510
1511 for_each_element_id(elem, WLAN_EID_MULTI_BAND, ies_buf, ies_len) {
1512 if (info->nof_ies >= MAX_NOF_MB_IES_SUPPORTED)
1513 return 0;
1514
1515 wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
1516 elem->datalen + 2);
1517 info->ies[info->nof_ies].ie = elem->data;
1518 info->ies[info->nof_ies].ie_len = elem->datalen;
1519 info->nof_ies++;
1520 }
1521
1522 if (!for_each_element_completed(elem, ies_buf, ies_len)) {
1523 wpa_hexdump(MSG_DEBUG, "Truncated IEs", ies_buf, ies_len);
1524 return -1;
1525 }
1526
1527 return 0;
1528 }
1529
1530
mb_ies_by_info(struct mb_ies_info * info)1531 struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
1532 {
1533 struct wpabuf *mb_ies = NULL;
1534
1535 WPA_ASSERT(info != NULL);
1536
1537 if (info->nof_ies) {
1538 u8 i;
1539 size_t mb_ies_size = 0;
1540
1541 for (i = 0; i < info->nof_ies; i++)
1542 mb_ies_size += 2 + info->ies[i].ie_len;
1543
1544 mb_ies = wpabuf_alloc(mb_ies_size);
1545 if (mb_ies) {
1546 for (i = 0; i < info->nof_ies; i++) {
1547 wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
1548 wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
1549 wpabuf_put_data(mb_ies,
1550 info->ies[i].ie,
1551 info->ies[i].ie_len);
1552 }
1553 }
1554 }
1555
1556 return mb_ies;
1557 }
1558
1559
1560 const struct oper_class_map global_op_class[] = {
1561 { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
1562 { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
1563
1564 /* Do not enable HT40 on 2.4 GHz for P2P use for now */
1565 { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
1566 { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
1567
1568 { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
1569 { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
1570 { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
1571 { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
1572 { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
1573 { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
1574 { HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
1575 { HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
1576 { HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
1577 { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
1578 { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
1579 { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
1580 { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
1581
1582 /*
1583 * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
1584 * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
1585 * 80 MHz, but currently use the following definition for simplicity
1586 * (these center frequencies are not actual channels, which makes
1587 * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
1588 * care of removing invalid channels.
1589 */
1590 { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
1591 { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
1592 { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
1593 { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
1594 { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
1595 };
1596
1597
ieee80211_phy_type_by_freq(int freq)1598 static enum phy_type ieee80211_phy_type_by_freq(int freq)
1599 {
1600 enum hostapd_hw_mode hw_mode;
1601 u8 channel;
1602
1603 hw_mode = ieee80211_freq_to_chan(freq, &channel);
1604
1605 switch (hw_mode) {
1606 case HOSTAPD_MODE_IEEE80211A:
1607 return PHY_TYPE_OFDM;
1608 case HOSTAPD_MODE_IEEE80211B:
1609 return PHY_TYPE_HRDSSS;
1610 case HOSTAPD_MODE_IEEE80211G:
1611 return PHY_TYPE_ERP;
1612 case HOSTAPD_MODE_IEEE80211AD:
1613 return PHY_TYPE_DMG;
1614 default:
1615 return PHY_TYPE_UNSPECIFIED;
1616 };
1617 }
1618
1619
1620 /* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
ieee80211_get_phy_type(int freq,int ht,int vht)1621 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
1622 {
1623 if (vht)
1624 return PHY_TYPE_VHT;
1625 if (ht)
1626 return PHY_TYPE_HT;
1627
1628 return ieee80211_phy_type_by_freq(freq);
1629 }
1630
1631
1632 size_t global_op_class_size = ARRAY_SIZE(global_op_class);
1633
1634
1635 /**
1636 * get_ie - Fetch a specified information element from IEs buffer
1637 * @ies: Information elements buffer
1638 * @len: Information elements buffer length
1639 * @eid: Information element identifier (WLAN_EID_*)
1640 * Returns: Pointer to the information element (id field) or %NULL if not found
1641 *
1642 * This function returns the first matching information element in the IEs
1643 * buffer or %NULL in case the element is not found.
1644 */
get_ie(const u8 * ies,size_t len,u8 eid)1645 const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
1646 {
1647 const struct element *elem;
1648
1649 if (!ies)
1650 return NULL;
1651
1652 for_each_element_id(elem, eid, ies, len)
1653 return &elem->id;
1654
1655 return NULL;
1656 }
1657
1658
1659 /**
1660 * get_ie_ext - Fetch a specified extended information element from IEs buffer
1661 * @ies: Information elements buffer
1662 * @len: Information elements buffer length
1663 * @ext: Information element extension identifier (WLAN_EID_EXT_*)
1664 * Returns: Pointer to the information element (id field) or %NULL if not found
1665 *
1666 * This function returns the first matching information element in the IEs
1667 * buffer or %NULL in case the element is not found.
1668 */
get_ie_ext(const u8 * ies,size_t len,u8 ext)1669 const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext)
1670 {
1671 const struct element *elem;
1672
1673 if (!ies)
1674 return NULL;
1675
1676 for_each_element_extid(elem, ext, ies, len)
1677 return &elem->id;
1678
1679 return NULL;
1680 }
1681
1682
get_vendor_ie(const u8 * ies,size_t len,u32 vendor_type)1683 const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type)
1684 {
1685 const struct element *elem;
1686
1687 for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, len) {
1688 if (elem->datalen >= 4 &&
1689 vendor_type == WPA_GET_BE32(elem->data))
1690 return &elem->id;
1691 }
1692
1693 return NULL;
1694 }
1695
1696
mbo_add_ie(u8 * buf,size_t len,const u8 * attr,size_t attr_len)1697 size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
1698 {
1699 /*
1700 * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
1701 * OUI (3), OUI type (1).
1702 */
1703 if (len < 6 + attr_len) {
1704 wpa_printf(MSG_DEBUG,
1705 "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
1706 len, attr_len);
1707 return 0;
1708 }
1709
1710 *buf++ = WLAN_EID_VENDOR_SPECIFIC;
1711 *buf++ = attr_len + 4;
1712 WPA_PUT_BE24(buf, OUI_WFA);
1713 buf += 3;
1714 *buf++ = MBO_OUI_TYPE;
1715 os_memcpy(buf, attr, attr_len);
1716
1717 return 6 + attr_len;
1718 }
1719
1720
add_multi_ap_ie(u8 * buf,size_t len,u8 value)1721 size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
1722 {
1723 u8 *pos = buf;
1724
1725 if (len < 9)
1726 return 0;
1727
1728 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
1729 *pos++ = 7; /* len */
1730 WPA_PUT_BE24(pos, OUI_WFA);
1731 pos += 3;
1732 *pos++ = MULTI_AP_OUI_TYPE;
1733 *pos++ = MULTI_AP_SUB_ELEM_TYPE;
1734 *pos++ = 1; /* len */
1735 *pos++ = value;
1736
1737 return pos - buf;
1738 }
1739
1740
1741 static const struct country_op_class us_op_class[] = {
1742 { 1, 115 },
1743 { 2, 118 },
1744 { 3, 124 },
1745 { 4, 121 },
1746 { 5, 125 },
1747 { 12, 81 },
1748 { 22, 116 },
1749 { 23, 119 },
1750 { 24, 122 },
1751 { 25, 126 },
1752 { 26, 126 },
1753 { 27, 117 },
1754 { 28, 120 },
1755 { 29, 123 },
1756 { 30, 127 },
1757 { 31, 127 },
1758 { 32, 83 },
1759 { 33, 84 },
1760 { 34, 180 },
1761 };
1762
1763 static const struct country_op_class eu_op_class[] = {
1764 { 1, 115 },
1765 { 2, 118 },
1766 { 3, 121 },
1767 { 4, 81 },
1768 { 5, 116 },
1769 { 6, 119 },
1770 { 7, 122 },
1771 { 8, 117 },
1772 { 9, 120 },
1773 { 10, 123 },
1774 { 11, 83 },
1775 { 12, 84 },
1776 { 17, 125 },
1777 { 18, 180 },
1778 };
1779
1780 static const struct country_op_class jp_op_class[] = {
1781 { 1, 115 },
1782 { 30, 81 },
1783 { 31, 82 },
1784 { 32, 118 },
1785 { 33, 118 },
1786 { 34, 121 },
1787 { 35, 121 },
1788 { 36, 116 },
1789 { 37, 119 },
1790 { 38, 119 },
1791 { 39, 122 },
1792 { 40, 122 },
1793 { 41, 117 },
1794 { 42, 120 },
1795 { 43, 120 },
1796 { 44, 123 },
1797 { 45, 123 },
1798 { 56, 83 },
1799 { 57, 84 },
1800 { 58, 121 },
1801 { 59, 180 },
1802 };
1803
1804 static const struct country_op_class cn_op_class[] = {
1805 { 1, 115 },
1806 { 2, 118 },
1807 { 3, 125 },
1808 { 4, 116 },
1809 { 5, 119 },
1810 { 6, 126 },
1811 { 7, 81 },
1812 { 8, 83 },
1813 { 9, 84 },
1814 };
1815
1816 static u8
global_op_class_from_country_array(u8 op_class,size_t array_size,const struct country_op_class * country_array)1817 global_op_class_from_country_array(u8 op_class, size_t array_size,
1818 const struct country_op_class *country_array)
1819 {
1820 size_t i;
1821
1822 for (i = 0; i < array_size; i++) {
1823 if (country_array[i].country_op_class == op_class)
1824 return country_array[i].global_op_class;
1825 }
1826
1827 return 0;
1828 }
1829
1830
country_to_global_op_class(const char * country,u8 op_class)1831 u8 country_to_global_op_class(const char *country, u8 op_class)
1832 {
1833 const struct country_op_class *country_array;
1834 size_t size;
1835 u8 g_op_class;
1836
1837 if (country_match(us_op_class_cc, country)) {
1838 country_array = us_op_class;
1839 size = ARRAY_SIZE(us_op_class);
1840 } else if (country_match(eu_op_class_cc, country)) {
1841 country_array = eu_op_class;
1842 size = ARRAY_SIZE(eu_op_class);
1843 } else if (country_match(jp_op_class_cc, country)) {
1844 country_array = jp_op_class;
1845 size = ARRAY_SIZE(jp_op_class);
1846 } else if (country_match(cn_op_class_cc, country)) {
1847 country_array = cn_op_class;
1848 size = ARRAY_SIZE(cn_op_class);
1849 } else {
1850 /*
1851 * Countries that do not match any of the above countries use
1852 * global operating classes
1853 */
1854 return op_class;
1855 }
1856
1857 g_op_class = global_op_class_from_country_array(op_class, size,
1858 country_array);
1859
1860 /*
1861 * If the given operating class did not match any of the country's
1862 * operating classes, assume that global operating class is used.
1863 */
1864 return g_op_class ? g_op_class : op_class;
1865 }
1866
1867
get_oper_class(const char * country,u8 op_class)1868 const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
1869 {
1870 const struct oper_class_map *op;
1871
1872 if (country)
1873 op_class = country_to_global_op_class(country, op_class);
1874
1875 op = &global_op_class[0];
1876 while (op->op_class && op->op_class != op_class)
1877 op++;
1878
1879 if (!op->op_class)
1880 return NULL;
1881
1882 return op;
1883 }
1884
1885
oper_class_bw_to_int(const struct oper_class_map * map)1886 int oper_class_bw_to_int(const struct oper_class_map *map)
1887 {
1888 switch (map->bw) {
1889 case BW20:
1890 return 20;
1891 case BW40PLUS:
1892 case BW40MINUS:
1893 return 40;
1894 case BW80:
1895 return 80;
1896 case BW80P80:
1897 case BW160:
1898 return 160;
1899 case BW2160:
1900 return 2160;
1901 default:
1902 return 0;
1903 }
1904 }
1905
1906
ieee802_11_parse_candidate_list(const char * pos,u8 * nei_rep,size_t nei_rep_len)1907 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
1908 size_t nei_rep_len)
1909 {
1910 u8 *nei_pos = nei_rep;
1911 const char *end;
1912
1913 /*
1914 * BSS Transition Candidate List Entries - Neighbor Report elements
1915 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
1916 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
1917 */
1918 while (pos) {
1919 u8 *nei_start;
1920 long int val;
1921 char *endptr, *tmp;
1922
1923 pos = os_strstr(pos, " neighbor=");
1924 if (!pos)
1925 break;
1926 if (nei_pos + 15 > nei_rep + nei_rep_len) {
1927 wpa_printf(MSG_DEBUG,
1928 "Not enough room for additional neighbor");
1929 return -1;
1930 }
1931 pos += 10;
1932
1933 nei_start = nei_pos;
1934 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
1935 nei_pos++; /* length to be filled in */
1936
1937 if (hwaddr_aton(pos, nei_pos)) {
1938 wpa_printf(MSG_DEBUG, "Invalid BSSID");
1939 return -1;
1940 }
1941 nei_pos += ETH_ALEN;
1942 pos += 17;
1943 if (*pos != ',') {
1944 wpa_printf(MSG_DEBUG, "Missing BSSID Information");
1945 return -1;
1946 }
1947 pos++;
1948
1949 val = strtol(pos, &endptr, 0);
1950 WPA_PUT_LE32(nei_pos, val);
1951 nei_pos += 4;
1952 if (*endptr != ',') {
1953 wpa_printf(MSG_DEBUG, "Missing Operating Class");
1954 return -1;
1955 }
1956 pos = endptr + 1;
1957
1958 *nei_pos++ = atoi(pos); /* Operating Class */
1959 pos = os_strchr(pos, ',');
1960 if (pos == NULL) {
1961 wpa_printf(MSG_DEBUG, "Missing Channel Number");
1962 return -1;
1963 }
1964 pos++;
1965
1966 *nei_pos++ = atoi(pos); /* Channel Number */
1967 pos = os_strchr(pos, ',');
1968 if (pos == NULL) {
1969 wpa_printf(MSG_DEBUG, "Missing PHY Type");
1970 return -1;
1971 }
1972 pos++;
1973
1974 *nei_pos++ = atoi(pos); /* PHY Type */
1975 end = os_strchr(pos, ' ');
1976 tmp = os_strchr(pos, ',');
1977 if (tmp && (!end || tmp < end)) {
1978 /* Optional Subelements (hexdump) */
1979 size_t len;
1980
1981 pos = tmp + 1;
1982 end = os_strchr(pos, ' ');
1983 if (end)
1984 len = end - pos;
1985 else
1986 len = os_strlen(pos);
1987 if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
1988 wpa_printf(MSG_DEBUG,
1989 "Not enough room for neighbor subelements");
1990 return -1;
1991 }
1992 if (len & 0x01 ||
1993 hexstr2bin(pos, nei_pos, len / 2) < 0) {
1994 wpa_printf(MSG_DEBUG,
1995 "Invalid neighbor subelement info");
1996 return -1;
1997 }
1998 nei_pos += len / 2;
1999 pos = end;
2000 }
2001
2002 nei_start[1] = nei_pos - nei_start - 2;
2003 }
2004
2005 return nei_pos - nei_rep;
2006 }
2007
2008
ieee802_11_ext_capab(const u8 * ie,unsigned int capab)2009 int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
2010 {
2011 if (!ie || ie[1] <= capab / 8)
2012 return 0;
2013 return !!(ie[2 + capab / 8] & BIT(capab % 8));
2014 }
2015