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