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