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