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