xref: /freebsd/contrib/wpa/src/common/ieee802_11_common.c (revision 98e0ffaefb0f241cda3a72395d3be04192ae0d47)
1 /*
2  * IEEE 802.11 Common routines
3  * Copyright (c) 2002-2013, 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 "ieee802_11_defs.h"
14 #include "ieee802_11_common.h"
15 
16 
17 static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
18 					    struct ieee802_11_elems *elems,
19 					    int show_errors)
20 {
21 	unsigned int oui;
22 
23 	/* first 3 bytes in vendor specific information element are the IEEE
24 	 * OUI of the vendor. The following byte is used a vendor specific
25 	 * sub-type. */
26 	if (elen < 4) {
27 		if (show_errors) {
28 			wpa_printf(MSG_MSGDUMP, "short vendor specific "
29 				   "information element ignored (len=%lu)",
30 				   (unsigned long) elen);
31 		}
32 		return -1;
33 	}
34 
35 	oui = WPA_GET_BE24(pos);
36 	switch (oui) {
37 	case OUI_MICROSOFT:
38 		/* Microsoft/Wi-Fi information elements are further typed and
39 		 * subtyped */
40 		switch (pos[3]) {
41 		case 1:
42 			/* Microsoft OUI (00:50:F2) with OUI Type 1:
43 			 * real WPA information element */
44 			elems->wpa_ie = pos;
45 			elems->wpa_ie_len = elen;
46 			break;
47 		case WMM_OUI_TYPE:
48 			/* WMM information element */
49 			if (elen < 5) {
50 				wpa_printf(MSG_MSGDUMP, "short WMM "
51 					   "information element ignored "
52 					   "(len=%lu)",
53 					   (unsigned long) elen);
54 				return -1;
55 			}
56 			switch (pos[4]) {
57 			case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
58 			case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
59 				/*
60 				 * Share same pointer since only one of these
61 				 * is used and they start with same data.
62 				 * Length field can be used to distinguish the
63 				 * IEs.
64 				 */
65 				elems->wmm = pos;
66 				elems->wmm_len = elen;
67 				break;
68 			case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
69 				elems->wmm_tspec = pos;
70 				elems->wmm_tspec_len = elen;
71 				break;
72 			default:
73 				wpa_printf(MSG_EXCESSIVE, "unknown WMM "
74 					   "information element ignored "
75 					   "(subtype=%d len=%lu)",
76 					   pos[4], (unsigned long) elen);
77 				return -1;
78 			}
79 			break;
80 		case 4:
81 			/* Wi-Fi Protected Setup (WPS) IE */
82 			elems->wps_ie = pos;
83 			elems->wps_ie_len = elen;
84 			break;
85 		default:
86 			wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
87 				   "information element ignored "
88 				   "(type=%d len=%lu)",
89 				   pos[3], (unsigned long) elen);
90 			return -1;
91 		}
92 		break;
93 
94 	case OUI_WFA:
95 		switch (pos[3]) {
96 		case P2P_OUI_TYPE:
97 			/* Wi-Fi Alliance - P2P IE */
98 			elems->p2p = pos;
99 			elems->p2p_len = elen;
100 			break;
101 		case WFD_OUI_TYPE:
102 			/* Wi-Fi Alliance - WFD IE */
103 			elems->wfd = pos;
104 			elems->wfd_len = elen;
105 			break;
106 		case HS20_INDICATION_OUI_TYPE:
107 			/* Hotspot 2.0 */
108 			elems->hs20 = pos;
109 			elems->hs20_len = elen;
110 			break;
111 		case HS20_OSEN_OUI_TYPE:
112 			/* Hotspot 2.0 OSEN */
113 			elems->osen = pos;
114 			elems->osen_len = elen;
115 			break;
116 		default:
117 			wpa_printf(MSG_MSGDUMP, "Unknown WFA "
118 				   "information element ignored "
119 				   "(type=%d len=%lu)",
120 				   pos[3], (unsigned long) elen);
121 			return -1;
122 		}
123 		break;
124 
125 	case OUI_BROADCOM:
126 		switch (pos[3]) {
127 		case VENDOR_HT_CAPAB_OUI_TYPE:
128 			elems->vendor_ht_cap = pos;
129 			elems->vendor_ht_cap_len = elen;
130 			break;
131 		case VENDOR_VHT_TYPE:
132 			if (elen > 4 &&
133 			    (pos[4] == VENDOR_VHT_SUBTYPE ||
134 			     pos[4] == VENDOR_VHT_SUBTYPE2)) {
135 				elems->vendor_vht = pos;
136 				elems->vendor_vht_len = elen;
137 			} else
138 				return -1;
139 			break;
140 		default:
141 			wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
142 				   "information element ignored "
143 				   "(type=%d len=%lu)",
144 				   pos[3], (unsigned long) elen);
145 			return -1;
146 		}
147 		break;
148 
149 	default:
150 		wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
151 			   "information element ignored (vendor OUI "
152 			   "%02x:%02x:%02x len=%lu)",
153 			   pos[0], pos[1], pos[2], (unsigned long) elen);
154 		return -1;
155 	}
156 
157 	return 0;
158 }
159 
160 
161 /**
162  * ieee802_11_parse_elems - Parse information elements in management frames
163  * @start: Pointer to the start of IEs
164  * @len: Length of IE buffer in octets
165  * @elems: Data structure for parsed elements
166  * @show_errors: Whether to show parsing errors in debug log
167  * Returns: Parsing result
168  */
169 ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
170 				struct ieee802_11_elems *elems,
171 				int show_errors)
172 {
173 	size_t left = len;
174 	const u8 *pos = start;
175 	int unknown = 0;
176 
177 	os_memset(elems, 0, sizeof(*elems));
178 
179 	while (left >= 2) {
180 		u8 id, elen;
181 
182 		id = *pos++;
183 		elen = *pos++;
184 		left -= 2;
185 
186 		if (elen > left) {
187 			if (show_errors) {
188 				wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
189 					   "parse failed (id=%d elen=%d "
190 					   "left=%lu)",
191 					   id, elen, (unsigned long) left);
192 				wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
193 			}
194 			return ParseFailed;
195 		}
196 
197 		switch (id) {
198 		case WLAN_EID_SSID:
199 			elems->ssid = pos;
200 			elems->ssid_len = elen;
201 			break;
202 		case WLAN_EID_SUPP_RATES:
203 			elems->supp_rates = pos;
204 			elems->supp_rates_len = elen;
205 			break;
206 		case WLAN_EID_DS_PARAMS:
207 			elems->ds_params = pos;
208 			elems->ds_params_len = elen;
209 			break;
210 		case WLAN_EID_CF_PARAMS:
211 		case WLAN_EID_TIM:
212 			break;
213 		case WLAN_EID_CHALLENGE:
214 			elems->challenge = pos;
215 			elems->challenge_len = elen;
216 			break;
217 		case WLAN_EID_ERP_INFO:
218 			elems->erp_info = pos;
219 			elems->erp_info_len = elen;
220 			break;
221 		case WLAN_EID_EXT_SUPP_RATES:
222 			elems->ext_supp_rates = pos;
223 			elems->ext_supp_rates_len = elen;
224 			break;
225 		case WLAN_EID_VENDOR_SPECIFIC:
226 			if (ieee802_11_parse_vendor_specific(pos, elen,
227 							     elems,
228 							     show_errors))
229 				unknown++;
230 			break;
231 		case WLAN_EID_RSN:
232 			elems->rsn_ie = pos;
233 			elems->rsn_ie_len = elen;
234 			break;
235 		case WLAN_EID_PWR_CAPABILITY:
236 			break;
237 		case WLAN_EID_SUPPORTED_CHANNELS:
238 			elems->supp_channels = pos;
239 			elems->supp_channels_len = elen;
240 			break;
241 		case WLAN_EID_MOBILITY_DOMAIN:
242 			elems->mdie = pos;
243 			elems->mdie_len = elen;
244 			break;
245 		case WLAN_EID_FAST_BSS_TRANSITION:
246 			elems->ftie = pos;
247 			elems->ftie_len = elen;
248 			break;
249 		case WLAN_EID_TIMEOUT_INTERVAL:
250 			elems->timeout_int = pos;
251 			elems->timeout_int_len = elen;
252 			break;
253 		case WLAN_EID_HT_CAP:
254 			elems->ht_capabilities = pos;
255 			elems->ht_capabilities_len = elen;
256 			break;
257 		case WLAN_EID_HT_OPERATION:
258 			elems->ht_operation = pos;
259 			elems->ht_operation_len = elen;
260 			break;
261 		case WLAN_EID_MESH_CONFIG:
262 			elems->mesh_config = pos;
263 			elems->mesh_config_len = elen;
264 			break;
265 		case WLAN_EID_MESH_ID:
266 			elems->mesh_id = pos;
267 			elems->mesh_id_len = elen;
268 			break;
269 		case WLAN_EID_PEER_MGMT:
270 			elems->peer_mgmt = pos;
271 			elems->peer_mgmt_len = elen;
272 			break;
273 		case WLAN_EID_VHT_CAP:
274 			elems->vht_capabilities = pos;
275 			elems->vht_capabilities_len = elen;
276 			break;
277 		case WLAN_EID_VHT_OPERATION:
278 			elems->vht_operation = pos;
279 			elems->vht_operation_len = elen;
280 			break;
281 		case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
282 			if (elen != 1)
283 				break;
284 			elems->vht_opmode_notif = pos;
285 			break;
286 		case WLAN_EID_LINK_ID:
287 			if (elen < 18)
288 				break;
289 			elems->link_id = pos;
290 			break;
291 		case WLAN_EID_INTERWORKING:
292 			elems->interworking = pos;
293 			elems->interworking_len = elen;
294 			break;
295 		case WLAN_EID_QOS_MAP_SET:
296 			if (elen < 16)
297 				break;
298 			elems->qos_map_set = pos;
299 			elems->qos_map_set_len = elen;
300 			break;
301 		case WLAN_EID_EXT_CAPAB:
302 			elems->ext_capab = pos;
303 			elems->ext_capab_len = elen;
304 			break;
305 		case WLAN_EID_BSS_MAX_IDLE_PERIOD:
306 			if (elen < 3)
307 				break;
308 			elems->bss_max_idle_period = pos;
309 			break;
310 		case WLAN_EID_SSID_LIST:
311 			elems->ssid_list = pos;
312 			elems->ssid_list_len = elen;
313 			break;
314 		case WLAN_EID_AMPE:
315 			elems->ampe = pos;
316 			elems->ampe_len = elen;
317 			break;
318 		case WLAN_EID_MIC:
319 			elems->mic = pos;
320 			elems->mic_len = elen;
321 			/* after mic everything is encrypted, so stop. */
322 			left = elen;
323 			break;
324 		default:
325 			unknown++;
326 			if (!show_errors)
327 				break;
328 			wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
329 				   "ignored unknown element (id=%d elen=%d)",
330 				   id, elen);
331 			break;
332 		}
333 
334 		left -= elen;
335 		pos += elen;
336 	}
337 
338 	if (left)
339 		return ParseFailed;
340 
341 	return unknown ? ParseUnknown : ParseOK;
342 }
343 
344 
345 int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
346 {
347 	int count = 0;
348 	const u8 *pos, *end;
349 
350 	if (ies == NULL)
351 		return 0;
352 
353 	pos = ies;
354 	end = ies + ies_len;
355 
356 	while (pos + 2 <= end) {
357 		if (pos + 2 + pos[1] > end)
358 			break;
359 		count++;
360 		pos += 2 + pos[1];
361 	}
362 
363 	return count;
364 }
365 
366 
367 struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
368 					    u32 oui_type)
369 {
370 	struct wpabuf *buf;
371 	const u8 *end, *pos, *ie;
372 
373 	pos = ies;
374 	end = ies + ies_len;
375 	ie = NULL;
376 
377 	while (pos + 1 < end) {
378 		if (pos + 2 + pos[1] > end)
379 			return NULL;
380 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
381 		    WPA_GET_BE32(&pos[2]) == oui_type) {
382 			ie = pos;
383 			break;
384 		}
385 		pos += 2 + pos[1];
386 	}
387 
388 	if (ie == NULL)
389 		return NULL; /* No specified vendor IE found */
390 
391 	buf = wpabuf_alloc(ies_len);
392 	if (buf == NULL)
393 		return NULL;
394 
395 	/*
396 	 * There may be multiple vendor IEs in the message, so need to
397 	 * concatenate their data fields.
398 	 */
399 	while (pos + 1 < end) {
400 		if (pos + 2 + pos[1] > end)
401 			break;
402 		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
403 		    WPA_GET_BE32(&pos[2]) == oui_type)
404 			wpabuf_put_data(buf, pos + 6, pos[1] - 4);
405 		pos += 2 + pos[1];
406 	}
407 
408 	return buf;
409 }
410 
411 
412 const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
413 {
414 	u16 fc, type, stype;
415 
416 	/*
417 	 * PS-Poll frames are 16 bytes. All other frames are
418 	 * 24 bytes or longer.
419 	 */
420 	if (len < 16)
421 		return NULL;
422 
423 	fc = le_to_host16(hdr->frame_control);
424 	type = WLAN_FC_GET_TYPE(fc);
425 	stype = WLAN_FC_GET_STYPE(fc);
426 
427 	switch (type) {
428 	case WLAN_FC_TYPE_DATA:
429 		if (len < 24)
430 			return NULL;
431 		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
432 		case WLAN_FC_FROMDS | WLAN_FC_TODS:
433 		case WLAN_FC_TODS:
434 			return hdr->addr1;
435 		case WLAN_FC_FROMDS:
436 			return hdr->addr2;
437 		default:
438 			return NULL;
439 		}
440 	case WLAN_FC_TYPE_CTRL:
441 		if (stype != WLAN_FC_STYPE_PSPOLL)
442 			return NULL;
443 		return hdr->addr1;
444 	case WLAN_FC_TYPE_MGMT:
445 		return hdr->addr3;
446 	default:
447 		return NULL;
448 	}
449 }
450 
451 
452 int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
453 			  const char *name, const char *val)
454 {
455 	int num, v;
456 	const char *pos;
457 	struct hostapd_wmm_ac_params *ac;
458 
459 	/* skip 'wme_ac_' or 'wmm_ac_' prefix */
460 	pos = name + 7;
461 	if (os_strncmp(pos, "be_", 3) == 0) {
462 		num = 0;
463 		pos += 3;
464 	} else if (os_strncmp(pos, "bk_", 3) == 0) {
465 		num = 1;
466 		pos += 3;
467 	} else if (os_strncmp(pos, "vi_", 3) == 0) {
468 		num = 2;
469 		pos += 3;
470 	} else if (os_strncmp(pos, "vo_", 3) == 0) {
471 		num = 3;
472 		pos += 3;
473 	} else {
474 		wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
475 		return -1;
476 	}
477 
478 	ac = &wmm_ac_params[num];
479 
480 	if (os_strcmp(pos, "aifs") == 0) {
481 		v = atoi(val);
482 		if (v < 1 || v > 255) {
483 			wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
484 			return -1;
485 		}
486 		ac->aifs = v;
487 	} else if (os_strcmp(pos, "cwmin") == 0) {
488 		v = atoi(val);
489 		if (v < 0 || v > 12) {
490 			wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
491 			return -1;
492 		}
493 		ac->cwmin = v;
494 	} else if (os_strcmp(pos, "cwmax") == 0) {
495 		v = atoi(val);
496 		if (v < 0 || v > 12) {
497 			wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
498 			return -1;
499 		}
500 		ac->cwmax = v;
501 	} else if (os_strcmp(pos, "txop_limit") == 0) {
502 		v = atoi(val);
503 		if (v < 0 || v > 0xffff) {
504 			wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
505 			return -1;
506 		}
507 		ac->txop_limit = v;
508 	} else if (os_strcmp(pos, "acm") == 0) {
509 		v = atoi(val);
510 		if (v < 0 || v > 1) {
511 			wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
512 			return -1;
513 		}
514 		ac->admission_control_mandatory = v;
515 	} else {
516 		wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos);
517 		return -1;
518 	}
519 
520 	return 0;
521 }
522 
523 
524 enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
525 {
526 	enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
527 
528 	if (freq >= 2412 && freq <= 2472) {
529 		mode = HOSTAPD_MODE_IEEE80211G;
530 		*channel = (freq - 2407) / 5;
531 	} else if (freq == 2484) {
532 		mode = HOSTAPD_MODE_IEEE80211B;
533 		*channel = 14;
534 	} else if (freq >= 4900 && freq < 5000) {
535 		mode = HOSTAPD_MODE_IEEE80211A;
536 		*channel = (freq - 4000) / 5;
537 	} else if (freq >= 5000 && freq < 5900) {
538 		mode = HOSTAPD_MODE_IEEE80211A;
539 		*channel = (freq - 5000) / 5;
540 	} else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
541 		mode = HOSTAPD_MODE_IEEE80211AD;
542 		*channel = (freq - 56160) / 2160;
543 	}
544 
545 	return mode;
546 }
547 
548 
549 static const char *us_op_class_cc[] = {
550 	"US", "CA", NULL
551 };
552 
553 static const char *eu_op_class_cc[] = {
554 	"AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
555 	"DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
556 	"LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
557 	"RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
558 };
559 
560 static const char *jp_op_class_cc[] = {
561 	"JP", NULL
562 };
563 
564 static const char *cn_op_class_cc[] = {
565 	"CN", "CA", NULL
566 };
567 
568 
569 static int country_match(const char *cc[], const char *country)
570 {
571 	int i;
572 
573 	if (country == NULL)
574 		return 0;
575 	for (i = 0; cc[i]; i++) {
576 		if (cc[i][0] == country[0] && cc[i][1] == country[1])
577 			return 1;
578 	}
579 
580 	return 0;
581 }
582 
583 
584 static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
585 {
586 	switch (op_class) {
587 	case 12: /* channels 1..11 */
588 	case 32: /* channels 1..7; 40 MHz */
589 	case 33: /* channels 5..11; 40 MHz */
590 		if (chan < 1 || chan > 11)
591 			return -1;
592 		return 2407 + 5 * chan;
593 	case 1: /* channels 36,40,44,48 */
594 	case 2: /* channels 52,56,60,64; dfs */
595 	case 22: /* channels 36,44; 40 MHz */
596 	case 23: /* channels 52,60; 40 MHz */
597 	case 27: /* channels 40,48; 40 MHz */
598 	case 28: /* channels 56,64; 40 MHz */
599 		if (chan < 36 || chan > 64)
600 			return -1;
601 		return 5000 + 5 * chan;
602 	case 4: /* channels 100-144 */
603 	case 24: /* channels 100-140; 40 MHz */
604 		if (chan < 100 || chan > 144)
605 			return -1;
606 		return 5000 + 5 * chan;
607 	case 3: /* channels 149,153,157,161 */
608 	case 25: /* channels 149,157; 40 MHz */
609 	case 26: /* channels 149,157; 40 MHz */
610 	case 30: /* channels 153,161; 40 MHz */
611 	case 31: /* channels 153,161; 40 MHz */
612 		if (chan < 149 || chan > 161)
613 			return -1;
614 		return 5000 + 5 * chan;
615 	case 34: /* 60 GHz band, channels 1..3 */
616 		if (chan < 1 || chan > 3)
617 			return -1;
618 		return 56160 + 2160 * chan;
619 	}
620 	return -1;
621 }
622 
623 
624 static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
625 {
626 	switch (op_class) {
627 	case 4: /* channels 1..13 */
628 	case 11: /* channels 1..9; 40 MHz */
629 	case 12: /* channels 5..13; 40 MHz */
630 		if (chan < 1 || chan > 13)
631 			return -1;
632 		return 2407 + 5 * chan;
633 	case 1: /* channels 36,40,44,48 */
634 	case 2: /* channels 52,56,60,64; dfs */
635 	case 5: /* channels 36,44; 40 MHz */
636 	case 6: /* channels 52,60; 40 MHz */
637 	case 8: /* channels 40,48; 40 MHz */
638 	case 9: /* channels 56,64; 40 MHz */
639 		if (chan < 36 || chan > 64)
640 			return -1;
641 		return 5000 + 5 * chan;
642 	case 3: /* channels 100-140 */
643 	case 7: /* channels 100-132; 40 MHz */
644 	case 10: /* channels 104-136; 40 MHz */
645 	case 16: /* channels 100-140 */
646 		if (chan < 100 || chan > 140)
647 			return -1;
648 		return 5000 + 5 * chan;
649 	case 17: /* channels 149,153,157,161,165,169 */
650 		if (chan < 149 || chan > 169)
651 			return -1;
652 		return 5000 + 5 * chan;
653 	case 18: /* 60 GHz band, channels 1..4 */
654 		if (chan < 1 || chan > 4)
655 			return -1;
656 		return 56160 + 2160 * chan;
657 	}
658 	return -1;
659 }
660 
661 
662 static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
663 {
664 	switch (op_class) {
665 	case 30: /* channels 1..13 */
666 	case 56: /* channels 1..9; 40 MHz */
667 	case 57: /* channels 5..13; 40 MHz */
668 		if (chan < 1 || chan > 13)
669 			return -1;
670 		return 2407 + 5 * chan;
671 	case 31: /* channel 14 */
672 		if (chan != 14)
673 			return -1;
674 		return 2414 + 5 * chan;
675 	case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
676 	case 32: /* channels 52,56,60,64 */
677 	case 33: /* channels 52,56,60,64 */
678 	case 36: /* channels 36,44; 40 MHz */
679 	case 37: /* channels 52,60; 40 MHz */
680 	case 38: /* channels 52,60; 40 MHz */
681 	case 41: /* channels 40,48; 40 MHz */
682 	case 42: /* channels 56,64; 40 MHz */
683 	case 43: /* channels 56,64; 40 MHz */
684 		if (chan < 34 || chan > 64)
685 			return -1;
686 		return 5000 + 5 * chan;
687 	case 34: /* channels 100-140 */
688 	case 35: /* channels 100-140 */
689 	case 39: /* channels 100-132; 40 MHz */
690 	case 40: /* channels 100-132; 40 MHz */
691 	case 44: /* channels 104-136; 40 MHz */
692 	case 45: /* channels 104-136; 40 MHz */
693 	case 58: /* channels 100-140 */
694 		if (chan < 100 || chan > 140)
695 			return -1;
696 		return 5000 + 5 * chan;
697 	case 59: /* 60 GHz band, channels 1..4 */
698 		if (chan < 1 || chan > 3)
699 			return -1;
700 		return 56160 + 2160 * chan;
701 	}
702 	return -1;
703 }
704 
705 
706 static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
707 {
708 	switch (op_class) {
709 	case 7: /* channels 1..13 */
710 	case 8: /* channels 1..9; 40 MHz */
711 	case 9: /* channels 5..13; 40 MHz */
712 		if (chan < 1 || chan > 13)
713 			return -1;
714 		return 2407 + 5 * chan;
715 	case 1: /* channels 36,40,44,48 */
716 	case 2: /* channels 52,56,60,64; dfs */
717 	case 4: /* channels 36,44; 40 MHz */
718 	case 5: /* channels 52,60; 40 MHz */
719 		if (chan < 36 || chan > 64)
720 			return -1;
721 		return 5000 + 5 * chan;
722 	case 3: /* channels 149,153,157,161,165 */
723 	case 6: /* channels 149,157; 40 MHz */
724 		if (chan < 149 || chan > 165)
725 			return -1;
726 		return 5000 + 5 * chan;
727 	}
728 	return -1;
729 }
730 
731 
732 static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
733 {
734 	/* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
735 	switch (op_class) {
736 	case 81:
737 		/* channels 1..13 */
738 		if (chan < 1 || chan > 13)
739 			return -1;
740 		return 2407 + 5 * chan;
741 	case 82:
742 		/* channel 14 */
743 		if (chan != 14)
744 			return -1;
745 		return 2414 + 5 * chan;
746 	case 83: /* channels 1..9; 40 MHz */
747 	case 84: /* channels 5..13; 40 MHz */
748 		if (chan < 1 || chan > 13)
749 			return -1;
750 		return 2407 + 5 * chan;
751 	case 115: /* channels 36,40,44,48; indoor only */
752 	case 116: /* channels 36,44; 40 MHz; indoor only */
753 	case 117: /* channels 40,48; 40 MHz; indoor only */
754 	case 118: /* channels 52,56,60,64; dfs */
755 	case 119: /* channels 52,60; 40 MHz; dfs */
756 	case 120: /* channels 56,64; 40 MHz; dfs */
757 		if (chan < 36 || chan > 64)
758 			return -1;
759 		return 5000 + 5 * chan;
760 	case 121: /* channels 100-140 */
761 	case 122: /* channels 100-142; 40 MHz */
762 	case 123: /* channels 104-136; 40 MHz */
763 		if (chan < 100 || chan > 140)
764 			return -1;
765 		return 5000 + 5 * chan;
766 	case 124: /* channels 149,153,157,161 */
767 	case 125: /* channels 149,153,157,161,165,169 */
768 	case 126: /* channels 149,157; 40 MHz */
769 	case 127: /* channels 153,161; 40 MHz */
770 		if (chan < 149 || chan > 161)
771 			return -1;
772 		return 5000 + 5 * chan;
773 	case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
774 	case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
775 		if (chan < 36 || chan > 161)
776 			return -1;
777 		return 5000 + 5 * chan;
778 	case 129: /* center freqs 50, 114; 160 MHz */
779 		if (chan < 50 || chan > 114)
780 			return -1;
781 		return 5000 + 5 * chan;
782 	case 180: /* 60 GHz band, channels 1..4 */
783 		if (chan < 1 || chan > 4)
784 			return -1;
785 		return 56160 + 2160 * chan;
786 	}
787 	return -1;
788 }
789 
790 /**
791  * ieee80211_chan_to_freq - Convert channel info to frequency
792  * @country: Country code, if known; otherwise, global operating class is used
793  * @op_class: Operating class
794  * @chan: Channel number
795  * Returns: Frequency in MHz or -1 if the specified channel is unknown
796  */
797 int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
798 {
799 	int freq;
800 
801 	if (country_match(us_op_class_cc, country)) {
802 		freq = ieee80211_chan_to_freq_us(op_class, chan);
803 		if (freq > 0)
804 			return freq;
805 	}
806 
807 	if (country_match(eu_op_class_cc, country)) {
808 		freq = ieee80211_chan_to_freq_eu(op_class, chan);
809 		if (freq > 0)
810 			return freq;
811 	}
812 
813 	if (country_match(jp_op_class_cc, country)) {
814 		freq = ieee80211_chan_to_freq_jp(op_class, chan);
815 		if (freq > 0)
816 			return freq;
817 	}
818 
819 	if (country_match(cn_op_class_cc, country)) {
820 		freq = ieee80211_chan_to_freq_cn(op_class, chan);
821 		if (freq > 0)
822 			return freq;
823 	}
824 
825 	return ieee80211_chan_to_freq_global(op_class, chan);
826 }
827 
828 
829 int ieee80211_is_dfs(int freq)
830 {
831 	/* TODO: this could be more accurate to better cover all domains */
832 	return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
833 }
834 
835 
836 static int is_11b(u8 rate)
837 {
838 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
839 }
840 
841 
842 int supp_rates_11b_only(struct ieee802_11_elems *elems)
843 {
844 	int num_11b = 0, num_others = 0;
845 	int i;
846 
847 	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
848 		return 0;
849 
850 	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
851 		if (is_11b(elems->supp_rates[i]))
852 			num_11b++;
853 		else
854 			num_others++;
855 	}
856 
857 	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
858 	     i++) {
859 		if (is_11b(elems->ext_supp_rates[i]))
860 			num_11b++;
861 		else
862 			num_others++;
863 	}
864 
865 	return num_11b > 0 && num_others == 0;
866 }
867 
868 
869 const char * fc2str(u16 fc)
870 {
871 	u16 stype = WLAN_FC_GET_STYPE(fc);
872 #define C2S(x) case x: return #x;
873 
874 	switch (WLAN_FC_GET_TYPE(fc)) {
875 	case WLAN_FC_TYPE_MGMT:
876 		switch (stype) {
877 		C2S(WLAN_FC_STYPE_ASSOC_REQ)
878 		C2S(WLAN_FC_STYPE_ASSOC_RESP)
879 		C2S(WLAN_FC_STYPE_REASSOC_REQ)
880 		C2S(WLAN_FC_STYPE_REASSOC_RESP)
881 		C2S(WLAN_FC_STYPE_PROBE_REQ)
882 		C2S(WLAN_FC_STYPE_PROBE_RESP)
883 		C2S(WLAN_FC_STYPE_BEACON)
884 		C2S(WLAN_FC_STYPE_ATIM)
885 		C2S(WLAN_FC_STYPE_DISASSOC)
886 		C2S(WLAN_FC_STYPE_AUTH)
887 		C2S(WLAN_FC_STYPE_DEAUTH)
888 		C2S(WLAN_FC_STYPE_ACTION)
889 		}
890 		break;
891 	case WLAN_FC_TYPE_CTRL:
892 		switch (stype) {
893 		C2S(WLAN_FC_STYPE_PSPOLL)
894 		C2S(WLAN_FC_STYPE_RTS)
895 		C2S(WLAN_FC_STYPE_CTS)
896 		C2S(WLAN_FC_STYPE_ACK)
897 		C2S(WLAN_FC_STYPE_CFEND)
898 		C2S(WLAN_FC_STYPE_CFENDACK)
899 		}
900 		break;
901 	case WLAN_FC_TYPE_DATA:
902 		switch (stype) {
903 		C2S(WLAN_FC_STYPE_DATA)
904 		C2S(WLAN_FC_STYPE_DATA_CFACK)
905 		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
906 		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
907 		C2S(WLAN_FC_STYPE_NULLFUNC)
908 		C2S(WLAN_FC_STYPE_CFACK)
909 		C2S(WLAN_FC_STYPE_CFPOLL)
910 		C2S(WLAN_FC_STYPE_CFACKPOLL)
911 		C2S(WLAN_FC_STYPE_QOS_DATA)
912 		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
913 		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
914 		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
915 		C2S(WLAN_FC_STYPE_QOS_NULL)
916 		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
917 		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
918 		}
919 		break;
920 	}
921 	return "WLAN_FC_TYPE_UNKNOWN";
922 #undef C2S
923 }
924