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