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 
ieee802_11_parse_vendor_specific(const u8 * pos,size_t elen,struct ieee802_11_elems * elems,int show_errors)19 static 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 
182 /**
183  * ieee802_11_parse_elems - Parse information elements in management frames
184  * @start: Pointer to the start of IEs
185  * @len: Length of IE buffer in octets
186  * @elems: Data structure for parsed elements
187  * @show_errors: Whether to show parsing errors in debug log
188  * Returns: Parsing result
189  */
ieee802_11_parse_elems(const u8 * start,size_t len,struct ieee802_11_elems * elems,int show_errors)190 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
191 				struct ieee802_11_elems *elems,
192 				int show_errors)
193 {
194 	size_t left = len;
195 	const u8 *pos = start;
196 	int unknown = 0;
197 
198 	os_memset(elems, 0, sizeof(*elems));
199 
200 	while (left >= 2) {
201 		u8 id, elen;
202 
203 		id = *pos++;
204 		elen = *pos++;
205 		left -= 2;
206 
207 		if (elen > left) {
208 			if (show_errors) {
209 				wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
210 					   "parse failed (id=%d elen=%d "
211 					   "left=%lu)",
212 					   id, elen, (unsigned long) left);
213 				wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
214 			}
215 			return ParseFailed;
216 		}
217 
218 		switch (id) {
219 		case WLAN_EID_SSID:
220 			if (elen > SSID_MAX_LEN) {
221 				wpa_printf(MSG_DEBUG,
222 					   "Ignored too long SSID element (elen=%u)",
223 					   elen);
224 				break;
225 			}
226 			elems->ssid = pos;
227 			elems->ssid_len = elen;
228 			break;
229 		case WLAN_EID_SUPP_RATES:
230 			elems->supp_rates = pos;
231 			elems->supp_rates_len = elen;
232 			break;
233 		case WLAN_EID_DS_PARAMS:
234 			if (elen < 1)
235 				break;
236 			elems->ds_params = pos;
237 			break;
238 		case WLAN_EID_CF_PARAMS:
239 		case WLAN_EID_TIM:
240 			break;
241 		case WLAN_EID_CHALLENGE:
242 			elems->challenge = pos;
243 			elems->challenge_len = elen;
244 			break;
245 		case WLAN_EID_ERP_INFO:
246 			if (elen < 1)
247 				break;
248 			elems->erp_info = pos;
249 			break;
250 		case WLAN_EID_EXT_SUPP_RATES:
251 			elems->ext_supp_rates = pos;
252 			elems->ext_supp_rates_len = elen;
253 			break;
254 		case WLAN_EID_VENDOR_SPECIFIC:
255 			if (ieee802_11_parse_vendor_specific(pos, elen,
256 							     elems,
257 							     show_errors))
258 				unknown++;
259 			break;
260 		case WLAN_EID_RSN:
261 			elems->rsn_ie = pos;
262 			elems->rsn_ie_len = elen;
263 			break;
264 		case WLAN_EID_PWR_CAPABILITY:
265 			break;
266 		case WLAN_EID_SUPPORTED_CHANNELS:
267 			elems->supp_channels = pos;
268 			elems->supp_channels_len = elen;
269 			break;
270 		case WLAN_EID_MOBILITY_DOMAIN:
271 			if (elen < sizeof(struct rsn_mdie))
272 				break;
273 			elems->mdie = pos;
274 			elems->mdie_len = elen;
275 			break;
276 		case WLAN_EID_FAST_BSS_TRANSITION:
277 			if (elen < sizeof(struct rsn_ftie))
278 				break;
279 			elems->ftie = pos;
280 			elems->ftie_len = elen;
281 			break;
282 		case WLAN_EID_TIMEOUT_INTERVAL:
283 			if (elen != 5)
284 				break;
285 			elems->timeout_int = pos;
286 			break;
287 		case WLAN_EID_HT_CAP:
288 			if (elen < sizeof(struct ieee80211_ht_capabilities))
289 				break;
290 			elems->ht_capabilities = pos;
291 			break;
292 		case WLAN_EID_HT_OPERATION:
293 			if (elen < sizeof(struct ieee80211_ht_operation))
294 				break;
295 			elems->ht_operation = pos;
296 			break;
297 		case WLAN_EID_MESH_CONFIG:
298 			elems->mesh_config = pos;
299 			elems->mesh_config_len = elen;
300 			break;
301 		case WLAN_EID_MESH_ID:
302 			elems->mesh_id = pos;
303 			elems->mesh_id_len = elen;
304 			break;
305 		case WLAN_EID_PEER_MGMT:
306 			elems->peer_mgmt = pos;
307 			elems->peer_mgmt_len = elen;
308 			break;
309 		case WLAN_EID_VHT_CAP:
310 			if (elen < sizeof(struct ieee80211_vht_capabilities))
311 				break;
312 			elems->vht_capabilities = pos;
313 			break;
314 		case WLAN_EID_VHT_OPERATION:
315 			if (elen < sizeof(struct ieee80211_vht_operation))
316 				break;
317 			elems->vht_operation = pos;
318 			break;
319 		case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
320 			if (elen != 1)
321 				break;
322 			elems->vht_opmode_notif = pos;
323 			break;
324 		case WLAN_EID_LINK_ID:
325 			if (elen < 18)
326 				break;
327 			elems->link_id = pos;
328 			break;
329 		case WLAN_EID_INTERWORKING:
330 			elems->interworking = pos;
331 			elems->interworking_len = elen;
332 			break;
333 		case WLAN_EID_QOS_MAP_SET:
334 			if (elen < 16)
335 				break;
336 			elems->qos_map_set = pos;
337 			elems->qos_map_set_len = elen;
338 			break;
339 		case WLAN_EID_EXT_CAPAB:
340 			elems->ext_capab = pos;
341 			elems->ext_capab_len = elen;
342 			break;
343 		case WLAN_EID_BSS_MAX_IDLE_PERIOD:
344 			if (elen < 3)
345 				break;
346 			elems->bss_max_idle_period = pos;
347 			break;
348 		case WLAN_EID_SSID_LIST:
349 			elems->ssid_list = pos;
350 			elems->ssid_list_len = elen;
351 			break;
352 		case WLAN_EID_AMPE:
353 			elems->ampe = pos;
354 			elems->ampe_len = elen;
355 			break;
356 		case WLAN_EID_MIC:
357 			elems->mic = pos;
358 			elems->mic_len = elen;
359 			/* after mic everything is encrypted, so stop. */
360 			left = elen;
361 			break;
362 		case WLAN_EID_MULTI_BAND:
363 			if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
364 				wpa_printf(MSG_MSGDUMP,
365 					   "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
366 					   id, elen);
367 				break;
368 			}
369 
370 			elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
371 			elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
372 			elems->mb_ies.nof_ies++;
373 			break;
374 		case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
375 			elems->supp_op_classes = pos;
376 			elems->supp_op_classes_len = elen;
377 			break;
378 		default:
379 			unknown++;
380 			if (!show_errors)
381 				break;
382 			wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
383 				   "ignored unknown element (id=%d elen=%d)",
384 				   id, elen);
385 			break;
386 		}
387 
388 		left -= elen;
389 		pos += elen;
390 	}
391 
392 	if (left)
393 		return ParseFailed;
394 
395 	return unknown ? ParseUnknown : ParseOK;
396 }
397 
398 
ieee802_11_ie_count(const u8 * ies,size_t ies_len)399 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
400 {
401 	int count = 0;
402 	const u8 *pos, *end;
403 
404 	if (ies == NULL)
405 		return 0;
406 
407 	pos = ies;
408 	end = ies + ies_len;
409 
410 	while (end - pos >= 2) {
411 		if (2 + pos[1] > end - pos)
412 			break;
413 		count++;
414 		pos += 2 + pos[1];
415 	}
416 
417 	return count;
418 }
419 
420 
ieee802_11_vendor_ie_concat(const u8 * ies,size_t ies_len,u32 oui_type)421 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
422 					    u32 oui_type)
423 {
424 	struct wpabuf *buf;
425 	const u8 *end, *pos, *ie;
426 
427 	pos = ies;
428 	end = ies + ies_len;
429 	ie = NULL;
430 
431 	while (end - pos > 1) {
432 		if (2 + pos[1] > end - pos)
433 			return NULL;
434 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
435 		    WPA_GET_BE32(&pos[2]) == oui_type) {
436 			ie = pos;
437 			break;
438 		}
439 		pos += 2 + pos[1];
440 	}
441 
442 	if (ie == NULL)
443 		return NULL; /* No specified vendor IE found */
444 
445 	buf = wpabuf_alloc(ies_len);
446 	if (buf == NULL)
447 		return NULL;
448 
449 	/*
450 	 * There may be multiple vendor IEs in the message, so need to
451 	 * concatenate their data fields.
452 	 */
453 	while (end - pos > 1) {
454 		if (2 + pos[1] > end - pos)
455 			break;
456 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
457 		    WPA_GET_BE32(&pos[2]) == oui_type)
458 			wpabuf_put_data(buf, pos + 6, pos[1] - 4);
459 		pos += 2 + pos[1];
460 	}
461 
462 	return buf;
463 }
464 
465 
get_hdr_bssid(const struct ieee80211_hdr * hdr,size_t len)466 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
467 {
468 	u16 fc, type, stype;
469 
470 	/*
471 	 * PS-Poll frames are 16 bytes. All other frames are
472 	 * 24 bytes or longer.
473 	 */
474 	if (len < 16)
475 		return NULL;
476 
477 	fc = le_to_host16(hdr->frame_control);
478 	type = WLAN_FC_GET_TYPE(fc);
479 	stype = WLAN_FC_GET_STYPE(fc);
480 
481 	switch (type) {
482 	case WLAN_FC_TYPE_DATA:
483 		if (len < 24)
484 			return NULL;
485 		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
486 		case WLAN_FC_FROMDS | WLAN_FC_TODS:
487 		case WLAN_FC_TODS:
488 			return hdr->addr1;
489 		case WLAN_FC_FROMDS:
490 			return hdr->addr2;
491 		default:
492 			return NULL;
493 		}
494 	case WLAN_FC_TYPE_CTRL:
495 		if (stype != WLAN_FC_STYPE_PSPOLL)
496 			return NULL;
497 		return hdr->addr1;
498 	case WLAN_FC_TYPE_MGMT:
499 		return hdr->addr3;
500 	default:
501 		return NULL;
502 	}
503 }
504 
505 
hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],const char * name,const char * val)506 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
507 			  const char *name, const char *val)
508 {
509 	int num, v;
510 	const char *pos;
511 	struct hostapd_wmm_ac_params *ac;
512 
513 	/* skip 'wme_ac_' or 'wmm_ac_' prefix */
514 	pos = name + 7;
515 	if (os_strncmp(pos, "be_", 3) == 0) {
516 		num = 0;
517 		pos += 3;
518 	} else if (os_strncmp(pos, "bk_", 3) == 0) {
519 		num = 1;
520 		pos += 3;
521 	} else if (os_strncmp(pos, "vi_", 3) == 0) {
522 		num = 2;
523 		pos += 3;
524 	} else if (os_strncmp(pos, "vo_", 3) == 0) {
525 		num = 3;
526 		pos += 3;
527 	} else {
528 		wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
529 		return -1;
530 	}
531 
532 	ac = &wmm_ac_params[num];
533 
534 	if (os_strcmp(pos, "aifs") == 0) {
535 		v = atoi(val);
536 		if (v < 1 || v > 255) {
537 			wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
538 			return -1;
539 		}
540 		ac->aifs = v;
541 	} else if (os_strcmp(pos, "cwmin") == 0) {
542 		v = atoi(val);
543 		if (v < 0 || v > 15) {
544 			wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
545 			return -1;
546 		}
547 		ac->cwmin = v;
548 	} else if (os_strcmp(pos, "cwmax") == 0) {
549 		v = atoi(val);
550 		if (v < 0 || v > 15) {
551 			wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
552 			return -1;
553 		}
554 		ac->cwmax = v;
555 	} else if (os_strcmp(pos, "txop_limit") == 0) {
556 		v = atoi(val);
557 		if (v < 0 || v > 0xffff) {
558 			wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
559 			return -1;
560 		}
561 		ac->txop_limit = v;
562 	} else if (os_strcmp(pos, "acm") == 0) {
563 		v = atoi(val);
564 		if (v < 0 || v > 1) {
565 			wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
566 			return -1;
567 		}
568 		ac->admission_control_mandatory = v;
569 	} else {
570 		wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
571 		return -1;
572 	}
573 
574 	return 0;
575 }
576 
577 
ieee80211_freq_to_chan(int freq,u8 * channel)578 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
579 {
580 	u8 op_class;
581 
582 	return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
583 					     &op_class, channel);
584 }
585 
586 
587 /**
588  * ieee80211_freq_to_channel_ext - Convert frequency into channel info
589  * for HT40 and VHT. DFS channels are not covered.
590  * @freq: Frequency (MHz) to convert
591  * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
592  * @vht: VHT channel width (VHT_CHANWIDTH_*)
593  * @op_class: Buffer for returning operating class
594  * @channel: Buffer for returning channel number
595  * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
596  */
ieee80211_freq_to_channel_ext(unsigned int freq,int sec_channel,int vht,u8 * op_class,u8 * channel)597 enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
598 						   int sec_channel, int vht,
599 						   u8 *op_class, u8 *channel)
600 {
601 	u8 vht_opclass;
602 
603 	/* TODO: more operating classes */
604 
605 	if (sec_channel > 1 || sec_channel < -1)
606 		return NUM_HOSTAPD_MODES;
607 
608 	if (freq >= 2412 && freq <= 2472) {
609 		if ((freq - 2407) % 5)
610 			return NUM_HOSTAPD_MODES;
611 
612 		if (vht)
613 			return NUM_HOSTAPD_MODES;
614 
615 		/* 2.407 GHz, channels 1..13 */
616 		if (sec_channel == 1)
617 			*op_class = 83;
618 		else if (sec_channel == -1)
619 			*op_class = 84;
620 		else
621 			*op_class = 81;
622 
623 		*channel = (freq - 2407) / 5;
624 
625 		return HOSTAPD_MODE_IEEE80211G;
626 	}
627 
628 	if (freq == 2484) {
629 		if (sec_channel || vht)
630 			return NUM_HOSTAPD_MODES;
631 
632 		*op_class = 82; /* channel 14 */
633 		*channel = 14;
634 
635 		return HOSTAPD_MODE_IEEE80211B;
636 	}
637 
638 	if (freq >= 4900 && freq < 5000) {
639 		if ((freq - 4000) % 5)
640 			return NUM_HOSTAPD_MODES;
641 		*channel = (freq - 4000) / 5;
642 		*op_class = 0; /* TODO */
643 		return HOSTAPD_MODE_IEEE80211A;
644 	}
645 
646 	switch (vht) {
647 	case VHT_CHANWIDTH_80MHZ:
648 		vht_opclass = 128;
649 		break;
650 	case VHT_CHANWIDTH_160MHZ:
651 		vht_opclass = 129;
652 		break;
653 	case VHT_CHANWIDTH_80P80MHZ:
654 		vht_opclass = 130;
655 		break;
656 	default:
657 		vht_opclass = 0;
658 		break;
659 	}
660 
661 	/* 5 GHz, channels 36..48 */
662 	if (freq >= 5180 && freq <= 5240) {
663 		if ((freq - 5000) % 5)
664 			return NUM_HOSTAPD_MODES;
665 
666 		if (vht_opclass)
667 			*op_class = vht_opclass;
668 		else if (sec_channel == 1)
669 			*op_class = 116;
670 		else if (sec_channel == -1)
671 			*op_class = 117;
672 		else
673 			*op_class = 115;
674 
675 		*channel = (freq - 5000) / 5;
676 
677 		return HOSTAPD_MODE_IEEE80211A;
678 	}
679 
680 	/* 5 GHz, channels 149..169 */
681 	if (freq >= 5745 && freq <= 5845) {
682 		if ((freq - 5000) % 5)
683 			return NUM_HOSTAPD_MODES;
684 
685 		if (vht_opclass)
686 			*op_class = vht_opclass;
687 		else if (sec_channel == 1)
688 			*op_class = 126;
689 		else if (sec_channel == -1)
690 			*op_class = 127;
691 		else if (freq <= 5805)
692 			*op_class = 124;
693 		else
694 			*op_class = 125;
695 
696 		*channel = (freq - 5000) / 5;
697 
698 		return HOSTAPD_MODE_IEEE80211A;
699 	}
700 
701 	/* 5 GHz, channels 100..140 */
702 	if (freq >= 5000 && freq <= 5700) {
703 		if ((freq - 5000) % 5)
704 			return NUM_HOSTAPD_MODES;
705 
706 		if (vht_opclass)
707 			*op_class = vht_opclass;
708 		else if (sec_channel == 1)
709 			*op_class = 122;
710 		else if (sec_channel == -1)
711 			*op_class = 123;
712 		else
713 			*op_class = 121;
714 
715 		*channel = (freq - 5000) / 5;
716 
717 		return HOSTAPD_MODE_IEEE80211A;
718 	}
719 
720 	if (freq >= 5000 && freq < 5900) {
721 		if ((freq - 5000) % 5)
722 			return NUM_HOSTAPD_MODES;
723 		*channel = (freq - 5000) / 5;
724 		*op_class = 0; /* TODO */
725 		return HOSTAPD_MODE_IEEE80211A;
726 	}
727 
728 	/* 56.16 GHz, channel 1..4 */
729 	if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
730 		if (sec_channel || vht)
731 			return NUM_HOSTAPD_MODES;
732 
733 		*channel = (freq - 56160) / 2160;
734 		*op_class = 180;
735 
736 		return HOSTAPD_MODE_IEEE80211AD;
737 	}
738 
739 	return NUM_HOSTAPD_MODES;
740 }
741 
742 
743 static const char *const us_op_class_cc[] = {
744 	"US", "CA", NULL
745 };
746 
747 static const char *const eu_op_class_cc[] = {
748 	"AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
749 	"DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
750 	"LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
751 	"RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
752 };
753 
754 static const char *const jp_op_class_cc[] = {
755 	"JP", NULL
756 };
757 
758 static const char *const cn_op_class_cc[] = {
759 	"CN", NULL
760 };
761 
762 
country_match(const char * const cc[],const char * const country)763 static int country_match(const char *const cc[], const char *const country)
764 {
765 	int i;
766 
767 	if (country == NULL)
768 		return 0;
769 	for (i = 0; cc[i]; i++) {
770 		if (cc[i][0] == country[0] && cc[i][1] == country[1])
771 			return 1;
772 	}
773 
774 	return 0;
775 }
776 
777 
ieee80211_chan_to_freq_us(u8 op_class,u8 chan)778 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
779 {
780 	switch (op_class) {
781 	case 12: /* channels 1..11 */
782 	case 32: /* channels 1..7; 40 MHz */
783 	case 33: /* channels 5..11; 40 MHz */
784 		if (chan < 1 || chan > 11)
785 			return -1;
786 		return 2407 + 5 * chan;
787 	case 1: /* channels 36,40,44,48 */
788 	case 2: /* channels 52,56,60,64; dfs */
789 	case 22: /* channels 36,44; 40 MHz */
790 	case 23: /* channels 52,60; 40 MHz */
791 	case 27: /* channels 40,48; 40 MHz */
792 	case 28: /* channels 56,64; 40 MHz */
793 		if (chan < 36 || chan > 64)
794 			return -1;
795 		return 5000 + 5 * chan;
796 	case 4: /* channels 100-144 */
797 	case 24: /* channels 100-140; 40 MHz */
798 		if (chan < 100 || chan > 144)
799 			return -1;
800 		return 5000 + 5 * chan;
801 	case 3: /* channels 149,153,157,161 */
802 	case 25: /* channels 149,157; 40 MHz */
803 	case 26: /* channels 149,157; 40 MHz */
804 	case 30: /* channels 153,161; 40 MHz */
805 	case 31: /* channels 153,161; 40 MHz */
806 		if (chan < 149 || chan > 161)
807 			return -1;
808 		return 5000 + 5 * chan;
809 	case 5: /* channels 149,153,157,161,165 */
810 		if (chan < 149 || chan > 165)
811 			return -1;
812 		return 5000 + 5 * chan;
813 	case 34: /* 60 GHz band, channels 1..3 */
814 		if (chan < 1 || chan > 3)
815 			return -1;
816 		return 56160 + 2160 * chan;
817 	}
818 	return -1;
819 }
820 
821 
ieee80211_chan_to_freq_eu(u8 op_class,u8 chan)822 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
823 {
824 	switch (op_class) {
825 	case 4: /* channels 1..13 */
826 	case 11: /* channels 1..9; 40 MHz */
827 	case 12: /* channels 5..13; 40 MHz */
828 		if (chan < 1 || chan > 13)
829 			return -1;
830 		return 2407 + 5 * chan;
831 	case 1: /* channels 36,40,44,48 */
832 	case 2: /* channels 52,56,60,64; dfs */
833 	case 5: /* channels 36,44; 40 MHz */
834 	case 6: /* channels 52,60; 40 MHz */
835 	case 8: /* channels 40,48; 40 MHz */
836 	case 9: /* channels 56,64; 40 MHz */
837 		if (chan < 36 || chan > 64)
838 			return -1;
839 		return 5000 + 5 * chan;
840 	case 3: /* channels 100-140 */
841 	case 7: /* channels 100-132; 40 MHz */
842 	case 10: /* channels 104-136; 40 MHz */
843 	case 16: /* channels 100-140 */
844 		if (chan < 100 || chan > 140)
845 			return -1;
846 		return 5000 + 5 * chan;
847 	case 17: /* channels 149,153,157,161,165,169 */
848 		if (chan < 149 || chan > 169)
849 			return -1;
850 		return 5000 + 5 * chan;
851 	case 18: /* 60 GHz band, channels 1..4 */
852 		if (chan < 1 || chan > 4)
853 			return -1;
854 		return 56160 + 2160 * chan;
855 	}
856 	return -1;
857 }
858 
859 
ieee80211_chan_to_freq_jp(u8 op_class,u8 chan)860 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
861 {
862 	switch (op_class) {
863 	case 30: /* channels 1..13 */
864 	case 56: /* channels 1..9; 40 MHz */
865 	case 57: /* channels 5..13; 40 MHz */
866 		if (chan < 1 || chan > 13)
867 			return -1;
868 		return 2407 + 5 * chan;
869 	case 31: /* channel 14 */
870 		if (chan != 14)
871 			return -1;
872 		return 2414 + 5 * chan;
873 	case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
874 	case 32: /* channels 52,56,60,64 */
875 	case 33: /* channels 52,56,60,64 */
876 	case 36: /* channels 36,44; 40 MHz */
877 	case 37: /* channels 52,60; 40 MHz */
878 	case 38: /* channels 52,60; 40 MHz */
879 	case 41: /* channels 40,48; 40 MHz */
880 	case 42: /* channels 56,64; 40 MHz */
881 	case 43: /* channels 56,64; 40 MHz */
882 		if (chan < 34 || chan > 64)
883 			return -1;
884 		return 5000 + 5 * chan;
885 	case 34: /* channels 100-140 */
886 	case 35: /* channels 100-140 */
887 	case 39: /* channels 100-132; 40 MHz */
888 	case 40: /* channels 100-132; 40 MHz */
889 	case 44: /* channels 104-136; 40 MHz */
890 	case 45: /* channels 104-136; 40 MHz */
891 	case 58: /* channels 100-140 */
892 		if (chan < 100 || chan > 140)
893 			return -1;
894 		return 5000 + 5 * chan;
895 	case 59: /* 60 GHz band, channels 1..4 */
896 		if (chan < 1 || chan > 3)
897 			return -1;
898 		return 56160 + 2160 * chan;
899 	}
900 	return -1;
901 }
902 
903 
ieee80211_chan_to_freq_cn(u8 op_class,u8 chan)904 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
905 {
906 	switch (op_class) {
907 	case 7: /* channels 1..13 */
908 	case 8: /* channels 1..9; 40 MHz */
909 	case 9: /* channels 5..13; 40 MHz */
910 		if (chan < 1 || chan > 13)
911 			return -1;
912 		return 2407 + 5 * chan;
913 	case 1: /* channels 36,40,44,48 */
914 	case 2: /* channels 52,56,60,64; dfs */
915 	case 4: /* channels 36,44; 40 MHz */
916 	case 5: /* channels 52,60; 40 MHz */
917 		if (chan < 36 || chan > 64)
918 			return -1;
919 		return 5000 + 5 * chan;
920 	case 3: /* channels 149,153,157,161,165 */
921 	case 6: /* channels 149,157; 40 MHz */
922 		if (chan < 149 || chan > 165)
923 			return -1;
924 		return 5000 + 5 * chan;
925 	}
926 	return -1;
927 }
928 
929 
ieee80211_chan_to_freq_global(u8 op_class,u8 chan)930 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
931 {
932 	/* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
933 	switch (op_class) {
934 	case 81:
935 		/* channels 1..13 */
936 		if (chan < 1 || chan > 13)
937 			return -1;
938 		return 2407 + 5 * chan;
939 	case 82:
940 		/* channel 14 */
941 		if (chan != 14)
942 			return -1;
943 		return 2414 + 5 * chan;
944 	case 83: /* channels 1..9; 40 MHz */
945 	case 84: /* channels 5..13; 40 MHz */
946 		if (chan < 1 || chan > 13)
947 			return -1;
948 		return 2407 + 5 * chan;
949 	case 115: /* channels 36,40,44,48; indoor only */
950 	case 116: /* channels 36,44; 40 MHz; indoor only */
951 	case 117: /* channels 40,48; 40 MHz; indoor only */
952 	case 118: /* channels 52,56,60,64; dfs */
953 	case 119: /* channels 52,60; 40 MHz; dfs */
954 	case 120: /* channels 56,64; 40 MHz; dfs */
955 		if (chan < 36 || chan > 64)
956 			return -1;
957 		return 5000 + 5 * chan;
958 	case 121: /* channels 100-140 */
959 	case 122: /* channels 100-142; 40 MHz */
960 	case 123: /* channels 104-136; 40 MHz */
961 		if (chan < 100 || chan > 140)
962 			return -1;
963 		return 5000 + 5 * chan;
964 	case 124: /* channels 149,153,157,161 */
965 	case 126: /* channels 149,157; 40 MHz */
966 	case 127: /* channels 153,161; 40 MHz */
967 		if (chan < 149 || chan > 161)
968 			return -1;
969 		return 5000 + 5 * chan;
970 	case 125: /* channels 149,153,157,161,165,169 */
971 		if (chan < 149 || chan > 169)
972 			return -1;
973 		return 5000 + 5 * chan;
974 	case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
975 	case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
976 		if (chan < 36 || chan > 161)
977 			return -1;
978 		return 5000 + 5 * chan;
979 	case 129: /* center freqs 50, 114; 160 MHz */
980 		if (chan < 50 || chan > 114)
981 			return -1;
982 		return 5000 + 5 * chan;
983 	case 180: /* 60 GHz band, channels 1..4 */
984 		if (chan < 1 || chan > 4)
985 			return -1;
986 		return 56160 + 2160 * chan;
987 	}
988 	return -1;
989 }
990 
991 /**
992  * ieee80211_chan_to_freq - Convert channel info to frequency
993  * @country: Country code, if known; otherwise, global operating class is used
994  * @op_class: Operating class
995  * @chan: Channel number
996  * Returns: Frequency in MHz or -1 if the specified channel is unknown
997  */
ieee80211_chan_to_freq(const char * country,u8 op_class,u8 chan)998 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
999 {
1000 	int freq;
1001 
1002 	if (country_match(us_op_class_cc, country)) {
1003 		freq = ieee80211_chan_to_freq_us(op_class, chan);
1004 		if (freq > 0)
1005 			return freq;
1006 	}
1007 
1008 	if (country_match(eu_op_class_cc, country)) {
1009 		freq = ieee80211_chan_to_freq_eu(op_class, chan);
1010 		if (freq > 0)
1011 			return freq;
1012 	}
1013 
1014 	if (country_match(jp_op_class_cc, country)) {
1015 		freq = ieee80211_chan_to_freq_jp(op_class, chan);
1016 		if (freq > 0)
1017 			return freq;
1018 	}
1019 
1020 	if (country_match(cn_op_class_cc, country)) {
1021 		freq = ieee80211_chan_to_freq_cn(op_class, chan);
1022 		if (freq > 0)
1023 			return freq;
1024 	}
1025 
1026 	return ieee80211_chan_to_freq_global(op_class, chan);
1027 }
1028 
1029 
ieee80211_is_dfs(int freq)1030 int ieee80211_is_dfs(int freq)
1031 {
1032 	/* TODO: this could be more accurate to better cover all domains */
1033 	return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
1034 }
1035 
1036 
is_11b(u8 rate)1037 static int is_11b(u8 rate)
1038 {
1039 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
1040 }
1041 
1042 
supp_rates_11b_only(struct ieee802_11_elems * elems)1043 int supp_rates_11b_only(struct ieee802_11_elems *elems)
1044 {
1045 	int num_11b = 0, num_others = 0;
1046 	int i;
1047 
1048 	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
1049 		return 0;
1050 
1051 	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
1052 		if (is_11b(elems->supp_rates[i]))
1053 			num_11b++;
1054 		else
1055 			num_others++;
1056 	}
1057 
1058 	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
1059 	     i++) {
1060 		if (is_11b(elems->ext_supp_rates[i]))
1061 			num_11b++;
1062 		else
1063 			num_others++;
1064 	}
1065 
1066 	return num_11b > 0 && num_others == 0;
1067 }
1068 
1069 
fc2str(u16 fc)1070 const char * fc2str(u16 fc)
1071 {
1072 	u16 stype = WLAN_FC_GET_STYPE(fc);
1073 #define C2S(x) case x: return #x;
1074 
1075 	switch (WLAN_FC_GET_TYPE(fc)) {
1076 	case WLAN_FC_TYPE_MGMT:
1077 		switch (stype) {
1078 		C2S(WLAN_FC_STYPE_ASSOC_REQ)
1079 		C2S(WLAN_FC_STYPE_ASSOC_RESP)
1080 		C2S(WLAN_FC_STYPE_REASSOC_REQ)
1081 		C2S(WLAN_FC_STYPE_REASSOC_RESP)
1082 		C2S(WLAN_FC_STYPE_PROBE_REQ)
1083 		C2S(WLAN_FC_STYPE_PROBE_RESP)
1084 		C2S(WLAN_FC_STYPE_BEACON)
1085 		C2S(WLAN_FC_STYPE_ATIM)
1086 		C2S(WLAN_FC_STYPE_DISASSOC)
1087 		C2S(WLAN_FC_STYPE_AUTH)
1088 		C2S(WLAN_FC_STYPE_DEAUTH)
1089 		C2S(WLAN_FC_STYPE_ACTION)
1090 		}
1091 		break;
1092 	case WLAN_FC_TYPE_CTRL:
1093 		switch (stype) {
1094 		C2S(WLAN_FC_STYPE_PSPOLL)
1095 		C2S(WLAN_FC_STYPE_RTS)
1096 		C2S(WLAN_FC_STYPE_CTS)
1097 		C2S(WLAN_FC_STYPE_ACK)
1098 		C2S(WLAN_FC_STYPE_CFEND)
1099 		C2S(WLAN_FC_STYPE_CFENDACK)
1100 		}
1101 		break;
1102 	case WLAN_FC_TYPE_DATA:
1103 		switch (stype) {
1104 		C2S(WLAN_FC_STYPE_DATA)
1105 		C2S(WLAN_FC_STYPE_DATA_CFACK)
1106 		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
1107 		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
1108 		C2S(WLAN_FC_STYPE_NULLFUNC)
1109 		C2S(WLAN_FC_STYPE_CFACK)
1110 		C2S(WLAN_FC_STYPE_CFPOLL)
1111 		C2S(WLAN_FC_STYPE_CFACKPOLL)
1112 		C2S(WLAN_FC_STYPE_QOS_DATA)
1113 		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
1114 		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
1115 		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
1116 		C2S(WLAN_FC_STYPE_QOS_NULL)
1117 		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
1118 		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
1119 		}
1120 		break;
1121 	}
1122 	return "WLAN_FC_TYPE_UNKNOWN";
1123 #undef C2S
1124 }
1125 
1126 
mb_ies_info_by_ies(struct mb_ies_info * info,const u8 * ies_buf,size_t ies_len)1127 int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
1128 		       size_t ies_len)
1129 {
1130 	os_memset(info, 0, sizeof(*info));
1131 
1132 	while (ies_buf && ies_len >= 2 &&
1133 	       info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
1134 		size_t len = 2 + ies_buf[1];
1135 
1136 		if (len > ies_len) {
1137 			wpa_hexdump(MSG_DEBUG, "Truncated IEs",
1138 				    ies_buf, ies_len);
1139 			return -1;
1140 		}
1141 
1142 		if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
1143 			wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
1144 			info->ies[info->nof_ies].ie = ies_buf + 2;
1145 			info->ies[info->nof_ies].ie_len = ies_buf[1];
1146 			info->nof_ies++;
1147 		}
1148 
1149 		ies_len -= len;
1150 		ies_buf += len;
1151 	}
1152 
1153 	return 0;
1154 }
1155 
1156 
mb_ies_by_info(struct mb_ies_info * info)1157 struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
1158 {
1159 	struct wpabuf *mb_ies = NULL;
1160 
1161 	WPA_ASSERT(info != NULL);
1162 
1163 	if (info->nof_ies) {
1164 		u8 i;
1165 		size_t mb_ies_size = 0;
1166 
1167 		for (i = 0; i < info->nof_ies; i++)
1168 			mb_ies_size += 2 + info->ies[i].ie_len;
1169 
1170 		mb_ies = wpabuf_alloc(mb_ies_size);
1171 		if (mb_ies) {
1172 			for (i = 0; i < info->nof_ies; i++) {
1173 				wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
1174 				wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
1175 				wpabuf_put_data(mb_ies,
1176 						info->ies[i].ie,
1177 						info->ies[i].ie_len);
1178 			}
1179 		}
1180 	}
1181 
1182 	return mb_ies;
1183 }
1184 
1185 
1186 const struct oper_class_map global_op_class[] = {
1187 	{ HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
1188 	{ HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
1189 
1190 	/* Do not enable HT40 on 2.4 GHz for P2P use for now */
1191 	{ HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
1192 	{ HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
1193 
1194 	{ HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
1195 	{ HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
1196 	{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
1197 	{ HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
1198 	{ HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
1199 	{ HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
1200 	{ HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
1201 	{ HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
1202 	{ HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
1203 	{ HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
1204 	{ HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
1205 	{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
1206 	{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
1207 
1208 	/*
1209 	 * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
1210 	 * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
1211 	 * 80 MHz, but currently use the following definition for simplicity
1212 	 * (these center frequencies are not actual channels, which makes
1213 	 * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
1214 	 * care of removing invalid channels.
1215 	 */
1216 	{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
1217 	{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
1218 	{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
1219 	{ HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
1220 	{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
1221 };
1222 
1223 
ieee80211_phy_type_by_freq(int freq)1224 static enum phy_type ieee80211_phy_type_by_freq(int freq)
1225 {
1226 	enum hostapd_hw_mode hw_mode;
1227 	u8 channel;
1228 
1229 	hw_mode = ieee80211_freq_to_chan(freq, &channel);
1230 
1231 	switch (hw_mode) {
1232 	case HOSTAPD_MODE_IEEE80211A:
1233 		return PHY_TYPE_OFDM;
1234 	case HOSTAPD_MODE_IEEE80211B:
1235 		return PHY_TYPE_HRDSSS;
1236 	case HOSTAPD_MODE_IEEE80211G:
1237 		return PHY_TYPE_ERP;
1238 	case HOSTAPD_MODE_IEEE80211AD:
1239 		return PHY_TYPE_DMG;
1240 	default:
1241 		return PHY_TYPE_UNSPECIFIED;
1242 	};
1243 }
1244 
1245 
1246 /* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
ieee80211_get_phy_type(int freq,int ht,int vht)1247 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
1248 {
1249 	if (vht)
1250 		return PHY_TYPE_VHT;
1251 	if (ht)
1252 		return PHY_TYPE_HT;
1253 
1254 	return ieee80211_phy_type_by_freq(freq);
1255 }
1256 
1257 
1258 size_t global_op_class_size = ARRAY_SIZE(global_op_class);
1259 
1260 
1261 /**
1262  * get_ie - Fetch a specified information element from IEs buffer
1263  * @ies: Information elements buffer
1264  * @len: Information elements buffer length
1265  * @eid: Information element identifier (WLAN_EID_*)
1266  * Returns: Pointer to the information element (id field) or %NULL if not found
1267  *
1268  * This function returns the first matching information element in the IEs
1269  * buffer or %NULL in case the element is not found.
1270  */
get_ie(const u8 * ies,size_t len,u8 eid)1271 const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
1272 {
1273 	const u8 *end;
1274 
1275 	if (!ies)
1276 		return NULL;
1277 
1278 	end = ies + len;
1279 
1280 	while (end - ies > 1) {
1281 		if (2 + ies[1] > end - ies)
1282 			break;
1283 
1284 		if (ies[0] == eid)
1285 			return ies;
1286 
1287 		ies += 2 + ies[1];
1288 	}
1289 
1290 	return NULL;
1291 }
1292 
1293 
mbo_add_ie(u8 * buf,size_t len,const u8 * attr,size_t attr_len)1294 size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
1295 {
1296 	/*
1297 	 * MBO IE requires 6 bytes without the attributes: EID (1), length (1),
1298 	 * OUI (3), OUI type (1).
1299 	 */
1300 	if (len < 6 + attr_len) {
1301 		wpa_printf(MSG_DEBUG,
1302 			   "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
1303 			   len, attr_len);
1304 		return 0;
1305 	}
1306 
1307 	*buf++ = WLAN_EID_VENDOR_SPECIFIC;
1308 	*buf++ = attr_len + 4;
1309 	WPA_PUT_BE24(buf, OUI_WFA);
1310 	buf += 3;
1311 	*buf++ = MBO_OUI_TYPE;
1312 	os_memcpy(buf, attr, attr_len);
1313 
1314 	return 6 + attr_len;
1315 }
1316