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