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