ieee802_11_common.c revision 9d9e60286e05ae45025b672636490bd12586138d
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 > 12) {
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 > 12) {
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 *us_op_class_cc[] = {
568	"US", "CA", NULL
569};
570
571static const char *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 *jp_op_class_cc[] = {
579	"JP", NULL
580};
581
582static const char *cn_op_class_cc[] = {
583	"CN", "CA", NULL
584};
585
586
587static int country_match(const char *cc[], const char *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 34: /* 60 GHz band, channels 1..3 */
634		if (chan < 1 || chan > 3)
635			return -1;
636		return 56160 + 2160 * chan;
637	}
638	return -1;
639}
640
641
642static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
643{
644	switch (op_class) {
645	case 4: /* channels 1..13 */
646	case 11: /* channels 1..9; 40 MHz */
647	case 12: /* channels 5..13; 40 MHz */
648		if (chan < 1 || chan > 13)
649			return -1;
650		return 2407 + 5 * chan;
651	case 1: /* channels 36,40,44,48 */
652	case 2: /* channels 52,56,60,64; dfs */
653	case 5: /* channels 36,44; 40 MHz */
654	case 6: /* channels 52,60; 40 MHz */
655	case 8: /* channels 40,48; 40 MHz */
656	case 9: /* channels 56,64; 40 MHz */
657		if (chan < 36 || chan > 64)
658			return -1;
659		return 5000 + 5 * chan;
660	case 3: /* channels 100-140 */
661	case 7: /* channels 100-132; 40 MHz */
662	case 10: /* channels 104-136; 40 MHz */
663	case 16: /* channels 100-140 */
664		if (chan < 100 || chan > 140)
665			return -1;
666		return 5000 + 5 * chan;
667	case 17: /* channels 149,153,157,161,165,169 */
668		if (chan < 149 || chan > 169)
669			return -1;
670		return 5000 + 5 * chan;
671	case 18: /* 60 GHz band, channels 1..4 */
672		if (chan < 1 || chan > 4)
673			return -1;
674		return 56160 + 2160 * chan;
675	}
676	return -1;
677}
678
679
680static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
681{
682	switch (op_class) {
683	case 30: /* channels 1..13 */
684	case 56: /* channels 1..9; 40 MHz */
685	case 57: /* channels 5..13; 40 MHz */
686		if (chan < 1 || chan > 13)
687			return -1;
688		return 2407 + 5 * chan;
689	case 31: /* channel 14 */
690		if (chan != 14)
691			return -1;
692		return 2414 + 5 * chan;
693	case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
694	case 32: /* channels 52,56,60,64 */
695	case 33: /* channels 52,56,60,64 */
696	case 36: /* channels 36,44; 40 MHz */
697	case 37: /* channels 52,60; 40 MHz */
698	case 38: /* channels 52,60; 40 MHz */
699	case 41: /* channels 40,48; 40 MHz */
700	case 42: /* channels 56,64; 40 MHz */
701	case 43: /* channels 56,64; 40 MHz */
702		if (chan < 34 || chan > 64)
703			return -1;
704		return 5000 + 5 * chan;
705	case 34: /* channels 100-140 */
706	case 35: /* channels 100-140 */
707	case 39: /* channels 100-132; 40 MHz */
708	case 40: /* channels 100-132; 40 MHz */
709	case 44: /* channels 104-136; 40 MHz */
710	case 45: /* channels 104-136; 40 MHz */
711	case 58: /* channels 100-140 */
712		if (chan < 100 || chan > 140)
713			return -1;
714		return 5000 + 5 * chan;
715	case 59: /* 60 GHz band, channels 1..4 */
716		if (chan < 1 || chan > 3)
717			return -1;
718		return 56160 + 2160 * chan;
719	}
720	return -1;
721}
722
723
724static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
725{
726	switch (op_class) {
727	case 7: /* channels 1..13 */
728	case 8: /* channels 1..9; 40 MHz */
729	case 9: /* channels 5..13; 40 MHz */
730		if (chan < 1 || chan > 13)
731			return -1;
732		return 2407 + 5 * chan;
733	case 1: /* channels 36,40,44,48 */
734	case 2: /* channels 52,56,60,64; dfs */
735	case 4: /* channels 36,44; 40 MHz */
736	case 5: /* channels 52,60; 40 MHz */
737		if (chan < 36 || chan > 64)
738			return -1;
739		return 5000 + 5 * chan;
740	case 3: /* channels 149,153,157,161,165 */
741	case 6: /* channels 149,157; 40 MHz */
742		if (chan < 149 || chan > 165)
743			return -1;
744		return 5000 + 5 * chan;
745	}
746	return -1;
747}
748
749
750static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
751{
752	/* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
753	switch (op_class) {
754	case 81:
755		/* channels 1..13 */
756		if (chan < 1 || chan > 13)
757			return -1;
758		return 2407 + 5 * chan;
759	case 82:
760		/* channel 14 */
761		if (chan != 14)
762			return -1;
763		return 2414 + 5 * chan;
764	case 83: /* channels 1..9; 40 MHz */
765	case 84: /* channels 5..13; 40 MHz */
766		if (chan < 1 || chan > 13)
767			return -1;
768		return 2407 + 5 * chan;
769	case 115: /* channels 36,40,44,48; indoor only */
770	case 116: /* channels 36,44; 40 MHz; indoor only */
771	case 117: /* channels 40,48; 40 MHz; indoor only */
772	case 118: /* channels 52,56,60,64; dfs */
773	case 119: /* channels 52,60; 40 MHz; dfs */
774	case 120: /* channels 56,64; 40 MHz; dfs */
775		if (chan < 36 || chan > 64)
776			return -1;
777		return 5000 + 5 * chan;
778	case 121: /* channels 100-140 */
779	case 122: /* channels 100-142; 40 MHz */
780	case 123: /* channels 104-136; 40 MHz */
781		if (chan < 100 || chan > 140)
782			return -1;
783		return 5000 + 5 * chan;
784	case 124: /* channels 149,153,157,161 */
785	case 125: /* channels 149,153,157,161,165,169 */
786	case 126: /* channels 149,157; 40 MHz */
787	case 127: /* channels 153,161; 40 MHz */
788		if (chan < 149 || chan > 161)
789			return -1;
790		return 5000 + 5 * chan;
791	case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
792	case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
793		if (chan < 36 || chan > 161)
794			return -1;
795		return 5000 + 5 * chan;
796	case 129: /* center freqs 50, 114; 160 MHz */
797		if (chan < 50 || chan > 114)
798			return -1;
799		return 5000 + 5 * chan;
800	case 180: /* 60 GHz band, channels 1..4 */
801		if (chan < 1 || chan > 4)
802			return -1;
803		return 56160 + 2160 * chan;
804	}
805	return -1;
806}
807
808/**
809 * ieee80211_chan_to_freq - Convert channel info to frequency
810 * @country: Country code, if known; otherwise, global operating class is used
811 * @op_class: Operating class
812 * @chan: Channel number
813 * Returns: Frequency in MHz or -1 if the specified channel is unknown
814 */
815int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
816{
817	int freq;
818
819	if (country_match(us_op_class_cc, country)) {
820		freq = ieee80211_chan_to_freq_us(op_class, chan);
821		if (freq > 0)
822			return freq;
823	}
824
825	if (country_match(eu_op_class_cc, country)) {
826		freq = ieee80211_chan_to_freq_eu(op_class, chan);
827		if (freq > 0)
828			return freq;
829	}
830
831	if (country_match(jp_op_class_cc, country)) {
832		freq = ieee80211_chan_to_freq_jp(op_class, chan);
833		if (freq > 0)
834			return freq;
835	}
836
837	if (country_match(cn_op_class_cc, country)) {
838		freq = ieee80211_chan_to_freq_cn(op_class, chan);
839		if (freq > 0)
840			return freq;
841	}
842
843	return ieee80211_chan_to_freq_global(op_class, chan);
844}
845
846
847int ieee80211_is_dfs(int freq)
848{
849	/* TODO: this could be more accurate to better cover all domains */
850	return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
851}
852
853
854static int is_11b(u8 rate)
855{
856	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
857}
858
859
860int supp_rates_11b_only(struct ieee802_11_elems *elems)
861{
862	int num_11b = 0, num_others = 0;
863	int i;
864
865	if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL)
866		return 0;
867
868	for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) {
869		if (is_11b(elems->supp_rates[i]))
870			num_11b++;
871		else
872			num_others++;
873	}
874
875	for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len;
876	     i++) {
877		if (is_11b(elems->ext_supp_rates[i]))
878			num_11b++;
879		else
880			num_others++;
881	}
882
883	return num_11b > 0 && num_others == 0;
884}
885
886
887const char * fc2str(u16 fc)
888{
889	u16 stype = WLAN_FC_GET_STYPE(fc);
890#define C2S(x) case x: return #x;
891
892	switch (WLAN_FC_GET_TYPE(fc)) {
893	case WLAN_FC_TYPE_MGMT:
894		switch (stype) {
895		C2S(WLAN_FC_STYPE_ASSOC_REQ)
896		C2S(WLAN_FC_STYPE_ASSOC_RESP)
897		C2S(WLAN_FC_STYPE_REASSOC_REQ)
898		C2S(WLAN_FC_STYPE_REASSOC_RESP)
899		C2S(WLAN_FC_STYPE_PROBE_REQ)
900		C2S(WLAN_FC_STYPE_PROBE_RESP)
901		C2S(WLAN_FC_STYPE_BEACON)
902		C2S(WLAN_FC_STYPE_ATIM)
903		C2S(WLAN_FC_STYPE_DISASSOC)
904		C2S(WLAN_FC_STYPE_AUTH)
905		C2S(WLAN_FC_STYPE_DEAUTH)
906		C2S(WLAN_FC_STYPE_ACTION)
907		}
908		break;
909	case WLAN_FC_TYPE_CTRL:
910		switch (stype) {
911		C2S(WLAN_FC_STYPE_PSPOLL)
912		C2S(WLAN_FC_STYPE_RTS)
913		C2S(WLAN_FC_STYPE_CTS)
914		C2S(WLAN_FC_STYPE_ACK)
915		C2S(WLAN_FC_STYPE_CFEND)
916		C2S(WLAN_FC_STYPE_CFENDACK)
917		}
918		break;
919	case WLAN_FC_TYPE_DATA:
920		switch (stype) {
921		C2S(WLAN_FC_STYPE_DATA)
922		C2S(WLAN_FC_STYPE_DATA_CFACK)
923		C2S(WLAN_FC_STYPE_DATA_CFPOLL)
924		C2S(WLAN_FC_STYPE_DATA_CFACKPOLL)
925		C2S(WLAN_FC_STYPE_NULLFUNC)
926		C2S(WLAN_FC_STYPE_CFACK)
927		C2S(WLAN_FC_STYPE_CFPOLL)
928		C2S(WLAN_FC_STYPE_CFACKPOLL)
929		C2S(WLAN_FC_STYPE_QOS_DATA)
930		C2S(WLAN_FC_STYPE_QOS_DATA_CFACK)
931		C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL)
932		C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL)
933		C2S(WLAN_FC_STYPE_QOS_NULL)
934		C2S(WLAN_FC_STYPE_QOS_CFPOLL)
935		C2S(WLAN_FC_STYPE_QOS_CFACKPOLL)
936		}
937		break;
938	}
939	return "WLAN_FC_TYPE_UNKNOWN";
940#undef C2S
941}
942