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