1 /* 2 * hostapd / Hardware feature query and different modes 3 * Copyright 2002-2003, Instant802 Networks, Inc. 4 * Copyright 2005-2006, Devicescape Software, Inc. 5 * Copyright (c) 2008-2009, Jouni Malinen <j (at) w1.fi> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Alternatively, this software may be distributed under the terms of BSD 12 * license. 13 * 14 * See README and COPYING for more details. 15 */ 16 17 #include "utils/includes.h" 18 19 #include "utils/common.h" 20 #include "utils/eloop.h" 21 #include "common/ieee802_11_defs.h" 22 #include "common/ieee802_11_common.h" 23 #include "drivers/driver.h" 24 #include "hostapd.h" 25 #include "ap_config.h" 26 #include "ap_drv_ops.h" 27 #include "hw_features.h" 28 29 30 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 31 size_t num_hw_features) 32 { 33 size_t i; 34 35 if (hw_features == NULL) 36 return; 37 38 for (i = 0; i < num_hw_features; i++) { 39 os_free(hw_features[i].channels); 40 os_free(hw_features[i].rates); 41 } 42 43 os_free(hw_features); 44 } 45 46 47 int hostapd_get_hw_features(struct hostapd_iface *iface) 48 { 49 struct hostapd_data *hapd = iface->bss[0]; 50 int ret = 0, i, j; 51 u16 num_modes, flags; 52 struct hostapd_hw_modes *modes; 53 54 if (hostapd_drv_none(hapd)) 55 return -1; 56 modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); 57 if (modes == NULL) { 58 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 59 HOSTAPD_LEVEL_DEBUG, 60 "Fetching hardware channel/rate support not " 61 "supported."); 62 return -1; 63 } 64 65 iface->hw_flags = flags; 66 67 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 68 iface->hw_features = modes; 69 iface->num_hw_features = num_modes; 70 71 for (i = 0; i < num_modes; i++) { 72 struct hostapd_hw_modes *feature = &modes[i]; 73 /* set flag for channels we can use in current regulatory 74 * domain */ 75 for (j = 0; j < feature->num_channels; j++) { 76 /* 77 * Disable all channels that are marked not to allow 78 * IBSS operation or active scanning. In addition, 79 * disable all channels that require radar detection, 80 * since that (in addition to full DFS) is not yet 81 * supported. 82 */ 83 if (feature->channels[j].flag & 84 (HOSTAPD_CHAN_NO_IBSS | 85 HOSTAPD_CHAN_PASSIVE_SCAN | 86 HOSTAPD_CHAN_RADAR)) 87 feature->channels[j].flag |= 88 HOSTAPD_CHAN_DISABLED; 89 if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 90 continue; 91 wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 92 "chan=%d freq=%d MHz max_tx_power=%d dBm", 93 feature->mode, 94 feature->channels[j].chan, 95 feature->channels[j].freq, 96 feature->channels[j].max_tx_power); 97 } 98 } 99 100 return ret; 101 } 102 103 104 int hostapd_prepare_rates(struct hostapd_data *hapd, 105 struct hostapd_hw_modes *mode) 106 { 107 int i, num_basic_rates = 0; 108 int basic_rates_a[] = { 60, 120, 240, -1 }; 109 int basic_rates_b[] = { 10, 20, -1 }; 110 int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 111 int *basic_rates; 112 113 if (hapd->iconf->basic_rates) 114 basic_rates = hapd->iconf->basic_rates; 115 else switch (mode->mode) { 116 case HOSTAPD_MODE_IEEE80211A: 117 basic_rates = basic_rates_a; 118 break; 119 case HOSTAPD_MODE_IEEE80211B: 120 basic_rates = basic_rates_b; 121 break; 122 case HOSTAPD_MODE_IEEE80211G: 123 basic_rates = basic_rates_g; 124 break; 125 default: 126 return -1; 127 } 128 129 if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates, 130 basic_rates, mode->mode)) { 131 wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel " 132 "module"); 133 } 134 135 os_free(hapd->iface->current_rates); 136 hapd->iface->num_rates = 0; 137 138 hapd->iface->current_rates = 139 os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data)); 140 if (!hapd->iface->current_rates) { 141 wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 142 "table."); 143 return -1; 144 } 145 146 for (i = 0; i < mode->num_rates; i++) { 147 struct hostapd_rate_data *rate; 148 149 if (hapd->iconf->supported_rates && 150 !hostapd_rate_found(hapd->iconf->supported_rates, 151 mode->rates[i])) 152 continue; 153 154 rate = &hapd->iface->current_rates[hapd->iface->num_rates]; 155 rate->rate = mode->rates[i]; 156 if (hostapd_rate_found(basic_rates, rate->rate)) { 157 rate->flags |= HOSTAPD_RATE_BASIC; 158 num_basic_rates++; 159 } 160 wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 161 hapd->iface->num_rates, rate->rate, rate->flags); 162 hapd->iface->num_rates++; 163 } 164 165 if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) && 166 (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) { 167 wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 168 "rate sets (%d,%d).", 169 hapd->iface->num_rates, num_basic_rates); 170 return -1; 171 } 172 173 return 0; 174 } 175 176 177 #ifdef CONFIG_IEEE80211N 178 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 179 { 180 int sec_chan, ok, j, first; 181 int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 182 184, 192 }; 183 size_t k; 184 185 if (!iface->conf->secondary_channel) 186 return 1; /* HT40 not used */ 187 188 sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; 189 wpa_printf(MSG_DEBUG, "HT40: control channel: %d " 190 "secondary channel: %d", 191 iface->conf->channel, sec_chan); 192 193 /* Verify that HT40 secondary channel is an allowed 20 MHz 194 * channel */ 195 ok = 0; 196 for (j = 0; j < iface->current_mode->num_channels; j++) { 197 struct hostapd_channel_data *chan = 198 &iface->current_mode->channels[j]; 199 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 200 chan->chan == sec_chan) { 201 ok = 1; 202 break; 203 } 204 } 205 if (!ok) { 206 wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", 207 sec_chan); 208 return 0; 209 } 210 211 /* 212 * Verify that HT40 primary,secondary channel pair is allowed per 213 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since 214 * 2.4 GHz rules allow all cases where the secondary channel fits into 215 * the list of allowed channels (already checked above). 216 */ 217 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 218 return 1; 219 220 if (iface->conf->secondary_channel > 0) 221 first = iface->conf->channel; 222 else 223 first = sec_chan; 224 225 ok = 0; 226 for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) { 227 if (first == allowed[k]) { 228 ok = 1; 229 break; 230 } 231 } 232 if (!ok) { 233 wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", 234 iface->conf->channel, 235 iface->conf->secondary_channel); 236 return 0; 237 } 238 239 return 1; 240 } 241 242 243 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 244 { 245 if (iface->conf->secondary_channel > 0) { 246 iface->conf->channel += 4; 247 iface->conf->secondary_channel = -1; 248 } else { 249 iface->conf->channel -= 4; 250 iface->conf->secondary_channel = 1; 251 } 252 } 253 254 255 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, 256 int *pri_chan, int *sec_chan) 257 { 258 struct ieee80211_ht_operation *oper; 259 struct ieee802_11_elems elems; 260 261 *pri_chan = *sec_chan = 0; 262 263 ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); 264 if (elems.ht_operation && 265 elems.ht_operation_len >= sizeof(*oper)) { 266 oper = (struct ieee80211_ht_operation *) elems.ht_operation; 267 *pri_chan = oper->control_chan; 268 if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { 269 int sec = oper->ht_param & 270 HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; 271 if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) 272 *sec_chan = *pri_chan + 4; 273 else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) 274 *sec_chan = *pri_chan - 4; 275 } 276 } 277 } 278 279 280 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 281 struct wpa_scan_results *scan_res) 282 { 283 int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; 284 int bss_pri_chan, bss_sec_chan; 285 size_t i; 286 int match; 287 288 pri_chan = iface->conf->channel; 289 sec_chan = iface->conf->secondary_channel * 4; 290 pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); 291 if (iface->conf->secondary_channel > 0) 292 sec_freq = pri_freq + 20; 293 else 294 sec_freq = pri_freq - 20; 295 296 /* 297 * Switch PRI/SEC channels if Beacons were detected on selected SEC 298 * channel, but not on selected PRI channel. 299 */ 300 pri_bss = sec_bss = 0; 301 for (i = 0; i < scan_res->num; i++) { 302 struct wpa_scan_res *bss = scan_res->res[i]; 303 if (bss->freq == pri_freq) 304 pri_bss++; 305 else if (bss->freq == sec_freq) 306 sec_bss++; 307 } 308 if (sec_bss && !pri_bss) { 309 wpa_printf(MSG_INFO, "Switch own primary and secondary " 310 "channel to get secondary channel with no Beacons " 311 "from other BSSes"); 312 ieee80211n_switch_pri_sec(iface); 313 } 314 315 /* 316 * Match PRI/SEC channel with any existing HT40 BSS on the same 317 * channels that we are about to use (if already mixed order in 318 * existing BSSes, use own preference). 319 */ 320 match = 0; 321 for (i = 0; i < scan_res->num; i++) { 322 struct wpa_scan_res *bss = scan_res->res[i]; 323 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); 324 if (pri_chan == bss_pri_chan && 325 sec_chan == bss_sec_chan) { 326 match = 1; 327 break; 328 } 329 } 330 if (!match) { 331 for (i = 0; i < scan_res->num; i++) { 332 struct wpa_scan_res *bss = scan_res->res[i]; 333 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, 334 &bss_sec_chan); 335 if (pri_chan == bss_sec_chan && 336 sec_chan == bss_pri_chan) { 337 wpa_printf(MSG_INFO, "Switch own primary and " 338 "secondary channel due to BSS " 339 "overlap with " MACSTR, 340 MAC2STR(bss->bssid)); 341 ieee80211n_switch_pri_sec(iface); 342 break; 343 } 344 } 345 } 346 347 return 1; 348 } 349 350 351 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 352 struct wpa_scan_results *scan_res) 353 { 354 int pri_freq, sec_freq; 355 int affected_start, affected_end; 356 size_t i; 357 358 pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 359 if (iface->conf->secondary_channel > 0) 360 sec_freq = pri_freq + 20; 361 else 362 sec_freq = pri_freq - 20; 363 affected_start = (pri_freq + sec_freq) / 2 - 25; 364 affected_end = (pri_freq + sec_freq) / 2 + 25; 365 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 366 affected_start, affected_end); 367 for (i = 0; i < scan_res->num; i++) { 368 struct wpa_scan_res *bss = scan_res->res[i]; 369 int pri = bss->freq; 370 int sec = pri; 371 int sec_chan, pri_chan; 372 373 ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); 374 375 if (sec_chan) { 376 if (sec_chan < pri_chan) 377 sec = pri - 20; 378 else 379 sec = pri + 20; 380 } 381 382 if ((pri < affected_start || pri > affected_end) && 383 (sec < affected_start || sec > affected_end)) 384 continue; /* not within affected channel range */ 385 386 wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR 387 " freq=%d pri=%d sec=%d", 388 MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); 389 390 if (sec_chan) { 391 if (pri_freq != pri || sec_freq != sec) { 392 wpa_printf(MSG_DEBUG, "40 MHz pri/sec " 393 "mismatch with BSS " MACSTR 394 " <%d,%d> (chan=%d%c) vs. <%d,%d>", 395 MAC2STR(bss->bssid), 396 pri, sec, pri_chan, 397 sec > pri ? '+' : '-', 398 pri_freq, sec_freq); 399 return 0; 400 } 401 } 402 403 /* TODO: 40 MHz intolerant */ 404 } 405 406 return 1; 407 } 408 409 410 static void wpa_scan_results_free(struct wpa_scan_results *res) 411 { 412 size_t i; 413 414 if (res == NULL) 415 return; 416 417 for (i = 0; i < res->num; i++) 418 os_free(res->res[i]); 419 os_free(res->res); 420 os_free(res); 421 } 422 423 424 static void ieee80211n_check_scan(struct hostapd_iface *iface) 425 { 426 struct wpa_scan_results *scan_res; 427 int oper40; 428 int res; 429 430 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 431 * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */ 432 433 iface->scan_cb = NULL; 434 435 scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 436 if (scan_res == NULL) { 437 hostapd_setup_interface_complete(iface, 1); 438 return; 439 } 440 441 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 442 oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 443 else 444 oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 445 wpa_scan_results_free(scan_res); 446 447 if (!oper40) { 448 wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 449 "channel pri=%d sec=%d based on overlapping BSSes", 450 iface->conf->channel, 451 iface->conf->channel + 452 iface->conf->secondary_channel * 4); 453 iface->conf->secondary_channel = 0; 454 iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 455 } 456 457 res = ieee80211n_allowed_ht40_channel_pair(iface); 458 hostapd_setup_interface_complete(iface, !res); 459 } 460 461 462 static int ieee80211n_check_40mhz(struct hostapd_iface *iface) 463 { 464 struct wpa_driver_scan_params params; 465 466 if (!iface->conf->secondary_channel) 467 return 0; /* HT40 not used */ 468 469 wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 470 "40 MHz channel"); 471 os_memset(¶ms, 0, sizeof(params)); 472 /* TODO: scan only the needed frequency */ 473 if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { 474 wpa_printf(MSG_ERROR, "Failed to request a scan of " 475 "neighboring BSSes"); 476 return -1; 477 } 478 479 iface->scan_cb = ieee80211n_check_scan; 480 return 1; 481 } 482 483 484 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 485 { 486 u16 hw = iface->current_mode->ht_capab; 487 u16 conf = iface->conf->ht_capab; 488 489 if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 490 !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 491 wpa_printf(MSG_ERROR, "Driver does not support configured " 492 "HT capability [LDPC]"); 493 return 0; 494 } 495 496 if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 497 !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 498 wpa_printf(MSG_ERROR, "Driver does not support configured " 499 "HT capability [HT40*]"); 500 return 0; 501 } 502 503 if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) && 504 (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) { 505 wpa_printf(MSG_ERROR, "Driver does not support configured " 506 "HT capability [SMPS-*]"); 507 return 0; 508 } 509 510 if ((conf & HT_CAP_INFO_GREEN_FIELD) && 511 !(hw & HT_CAP_INFO_GREEN_FIELD)) { 512 wpa_printf(MSG_ERROR, "Driver does not support configured " 513 "HT capability [GF]"); 514 return 0; 515 } 516 517 if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 518 !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 519 wpa_printf(MSG_ERROR, "Driver does not support configured " 520 "HT capability [SHORT-GI-20]"); 521 return 0; 522 } 523 524 if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 525 !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 526 wpa_printf(MSG_ERROR, "Driver does not support configured " 527 "HT capability [SHORT-GI-40]"); 528 return 0; 529 } 530 531 if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 532 wpa_printf(MSG_ERROR, "Driver does not support configured " 533 "HT capability [TX-STBC]"); 534 return 0; 535 } 536 537 if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 538 (hw & HT_CAP_INFO_RX_STBC_MASK)) { 539 wpa_printf(MSG_ERROR, "Driver does not support configured " 540 "HT capability [RX-STBC*]"); 541 return 0; 542 } 543 544 if ((conf & HT_CAP_INFO_DELAYED_BA) && 545 !(hw & HT_CAP_INFO_DELAYED_BA)) { 546 wpa_printf(MSG_ERROR, "Driver does not support configured " 547 "HT capability [DELAYED-BA]"); 548 return 0; 549 } 550 551 if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 552 !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 553 wpa_printf(MSG_ERROR, "Driver does not support configured " 554 "HT capability [MAX-AMSDU-7935]"); 555 return 0; 556 } 557 558 if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 559 !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 560 wpa_printf(MSG_ERROR, "Driver does not support configured " 561 "HT capability [DSSS_CCK-40]"); 562 return 0; 563 } 564 565 if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) { 566 wpa_printf(MSG_ERROR, "Driver does not support configured " 567 "HT capability [PSMP]"); 568 return 0; 569 } 570 571 if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 572 !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 573 wpa_printf(MSG_ERROR, "Driver does not support configured " 574 "HT capability [LSIG-TXOP-PROT]"); 575 return 0; 576 } 577 578 return 1; 579 } 580 581 #endif /* CONFIG_IEEE80211N */ 582 583 584 int hostapd_check_ht_capab(struct hostapd_iface *iface) 585 { 586 #ifdef CONFIG_IEEE80211N 587 int ret; 588 if (!iface->conf->ieee80211n) 589 return 0; 590 if (!ieee80211n_supported_ht_capab(iface)) 591 return -1; 592 ret = ieee80211n_check_40mhz(iface); 593 if (ret) 594 return ret; 595 if (!ieee80211n_allowed_ht40_channel_pair(iface)) 596 return -1; 597 #endif /* CONFIG_IEEE80211N */ 598 599 return 0; 600 } 601 602 603 /** 604 * hostapd_select_hw_mode - Select the hardware mode 605 * @iface: Pointer to interface data. 606 * Returns: 0 on success, < 0 on failure 607 * 608 * Sets up the hardware mode, channel, rates, and passive scanning 609 * based on the configuration. 610 */ 611 int hostapd_select_hw_mode(struct hostapd_iface *iface) 612 { 613 int i, j, ok; 614 615 if (iface->num_hw_features < 1) 616 return -1; 617 618 iface->current_mode = NULL; 619 for (i = 0; i < iface->num_hw_features; i++) { 620 struct hostapd_hw_modes *mode = &iface->hw_features[i]; 621 if (mode->mode == iface->conf->hw_mode) { 622 iface->current_mode = mode; 623 break; 624 } 625 } 626 627 if (iface->current_mode == NULL) { 628 wpa_printf(MSG_ERROR, "Hardware does not support configured " 629 "mode"); 630 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 631 HOSTAPD_LEVEL_WARNING, 632 "Hardware does not support configured mode " 633 "(%d)", (int) iface->conf->hw_mode); 634 return -2; 635 } 636 637 ok = 0; 638 for (j = 0; j < iface->current_mode->num_channels; j++) { 639 struct hostapd_channel_data *chan = 640 &iface->current_mode->channels[j]; 641 if (chan->chan == iface->conf->channel) { 642 if (chan->flag & HOSTAPD_CHAN_DISABLED) { 643 wpa_printf(MSG_ERROR, 644 "channel [%i] (%i) is disabled for " 645 "use in AP mode, flags: 0x%x", 646 j, chan->chan, chan->flag); 647 } else { 648 ok = 1; 649 break; 650 } 651 } 652 } 653 if (ok && iface->conf->secondary_channel) { 654 int sec_ok = 0; 655 int sec_chan = iface->conf->channel + 656 iface->conf->secondary_channel * 4; 657 for (j = 0; j < iface->current_mode->num_channels; j++) { 658 struct hostapd_channel_data *chan = 659 &iface->current_mode->channels[j]; 660 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 661 (chan->chan == sec_chan)) { 662 sec_ok = 1; 663 break; 664 } 665 } 666 if (!sec_ok) { 667 hostapd_logger(iface->bss[0], NULL, 668 HOSTAPD_MODULE_IEEE80211, 669 HOSTAPD_LEVEL_WARNING, 670 "Configured HT40 secondary channel " 671 "(%d) not found from the channel list " 672 "of current mode (%d) %s", 673 sec_chan, iface->current_mode->mode, 674 hostapd_hw_mode_txt( 675 iface->current_mode->mode)); 676 ok = 0; 677 } 678 } 679 if (iface->conf->channel == 0) { 680 /* TODO: could request a scan of neighboring BSSes and select 681 * the channel automatically */ 682 wpa_printf(MSG_ERROR, "Channel not configured " 683 "(hw_mode/channel in hostapd.conf)"); 684 return -3; 685 } 686 if (ok == 0 && iface->conf->channel != 0) { 687 hostapd_logger(iface->bss[0], NULL, 688 HOSTAPD_MODULE_IEEE80211, 689 HOSTAPD_LEVEL_WARNING, 690 "Configured channel (%d) not found from the " 691 "channel list of current mode (%d) %s", 692 iface->conf->channel, 693 iface->current_mode->mode, 694 hostapd_hw_mode_txt(iface->current_mode->mode)); 695 iface->current_mode = NULL; 696 } 697 698 if (iface->current_mode == NULL) { 699 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 700 HOSTAPD_LEVEL_WARNING, 701 "Hardware does not support configured channel"); 702 return -4; 703 } 704 705 return 0; 706 } 707 708 709 const char * hostapd_hw_mode_txt(int mode) 710 { 711 switch (mode) { 712 case HOSTAPD_MODE_IEEE80211A: 713 return "IEEE 802.11a"; 714 case HOSTAPD_MODE_IEEE80211B: 715 return "IEEE 802.11b"; 716 case HOSTAPD_MODE_IEEE80211G: 717 return "IEEE 802.11g"; 718 default: 719 return "UNKNOWN"; 720 } 721 } 722 723 724 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 725 { 726 int i; 727 728 if (!hapd->iface->current_mode) 729 return 0; 730 731 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 732 struct hostapd_channel_data *ch = 733 &hapd->iface->current_mode->channels[i]; 734 if (ch->chan == chan) 735 return ch->freq; 736 } 737 738 return 0; 739 } 740 741 742 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 743 { 744 int i; 745 746 if (!hapd->iface->current_mode) 747 return 0; 748 749 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 750 struct hostapd_channel_data *ch = 751 &hapd->iface->current_mode->channels[i]; 752 if (ch->freq == freq) 753 return ch->chan; 754 } 755 756 return 0; 757 } 758