Home | History | Annotate | Download | only in common
      1 /*
      2  * IEEE 802.11 Common routines
      3  * Copyright (c) 2002-2015, Jouni Malinen <j (at) 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 
     18 static 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  */
    170 ParseRes 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 
    363 int 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 
    385 struct 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 
    430 const 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 
    470 int 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 
    542 enum 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 
    567 static const char *const us_op_class_cc[] = {
    568 	"US", "CA", NULL
    569 };
    570 
    571 static 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 
    578 static const char *const jp_op_class_cc[] = {
    579 	"JP", NULL
    580 };
    581 
    582 static const char *const cn_op_class_cc[] = {
    583 	"CN", NULL
    584 };
    585 
    586 
    587 static 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 
    602 static 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 
    646 static 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 
    684 static 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 
    728 static 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 
    754 static 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  */
    822 int 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 
    854 int 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 
    861 static int is_11b(u8 rate)
    862 {
    863 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
    864 }
    865 
    866 
    867 int 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 
    894 const 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