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-2012, 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_iface *iface, 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 (iface->conf->basic_rates) 114 basic_rates = iface->conf->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 i = 0; 130 while (basic_rates[i] >= 0) 131 i++; 132 if (i) 133 i++; /* -1 termination */ 134 os_free(iface->basic_rates); 135 iface->basic_rates = os_malloc(i * sizeof(int)); 136 if (iface->basic_rates) 137 os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 138 139 os_free(iface->current_rates); 140 iface->num_rates = 0; 141 142 iface->current_rates = 143 os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 144 if (!iface->current_rates) { 145 wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 146 "table."); 147 return -1; 148 } 149 150 for (i = 0; i < mode->num_rates; i++) { 151 struct hostapd_rate_data *rate; 152 153 if (iface->conf->supported_rates && 154 !hostapd_rate_found(iface->conf->supported_rates, 155 mode->rates[i])) 156 continue; 157 158 rate = &iface->current_rates[iface->num_rates]; 159 rate->rate = mode->rates[i]; 160 if (hostapd_rate_found(basic_rates, rate->rate)) { 161 rate->flags |= HOSTAPD_RATE_BASIC; 162 num_basic_rates++; 163 } 164 wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 165 iface->num_rates, rate->rate, rate->flags); 166 iface->num_rates++; 167 } 168 169 if ((iface->num_rates == 0 || num_basic_rates == 0) && 170 (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 171 wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 172 "rate sets (%d,%d).", 173 iface->num_rates, num_basic_rates); 174 return -1; 175 } 176 177 return 0; 178 } 179 180 181 #ifdef CONFIG_IEEE80211N 182 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 183 { 184 int sec_chan, ok, j, first; 185 int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 186 184, 192 }; 187 size_t k; 188 189 if (!iface->conf->secondary_channel) 190 return 1; /* HT40 not used */ 191 192 sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; 193 wpa_printf(MSG_DEBUG, "HT40: control channel: %d " 194 "secondary channel: %d", 195 iface->conf->channel, sec_chan); 196 197 /* Verify that HT40 secondary channel is an allowed 20 MHz 198 * channel */ 199 ok = 0; 200 for (j = 0; j < iface->current_mode->num_channels; j++) { 201 struct hostapd_channel_data *chan = 202 &iface->current_mode->channels[j]; 203 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 204 chan->chan == sec_chan) { 205 ok = 1; 206 break; 207 } 208 } 209 if (!ok) { 210 wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", 211 sec_chan); 212 return 0; 213 } 214 215 /* 216 * Verify that HT40 primary,secondary channel pair is allowed per 217 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since 218 * 2.4 GHz rules allow all cases where the secondary channel fits into 219 * the list of allowed channels (already checked above). 220 */ 221 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 222 return 1; 223 224 if (iface->conf->secondary_channel > 0) 225 first = iface->conf->channel; 226 else 227 first = sec_chan; 228 229 ok = 0; 230 for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) { 231 if (first == allowed[k]) { 232 ok = 1; 233 break; 234 } 235 } 236 if (!ok) { 237 wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", 238 iface->conf->channel, 239 iface->conf->secondary_channel); 240 return 0; 241 } 242 243 return 1; 244 } 245 246 247 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 248 { 249 if (iface->conf->secondary_channel > 0) { 250 iface->conf->channel += 4; 251 iface->conf->secondary_channel = -1; 252 } else { 253 iface->conf->channel -= 4; 254 iface->conf->secondary_channel = 1; 255 } 256 } 257 258 259 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, 260 int *pri_chan, int *sec_chan) 261 { 262 struct ieee80211_ht_operation *oper; 263 struct ieee802_11_elems elems; 264 265 *pri_chan = *sec_chan = 0; 266 267 ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); 268 if (elems.ht_operation && 269 elems.ht_operation_len >= sizeof(*oper)) { 270 oper = (struct ieee80211_ht_operation *) elems.ht_operation; 271 *pri_chan = oper->control_chan; 272 if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { 273 int sec = oper->ht_param & 274 HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; 275 if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) 276 *sec_chan = *pri_chan + 4; 277 else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) 278 *sec_chan = *pri_chan - 4; 279 } 280 } 281 } 282 283 284 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 285 struct wpa_scan_results *scan_res) 286 { 287 int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; 288 int bss_pri_chan, bss_sec_chan; 289 size_t i; 290 int match; 291 292 pri_chan = iface->conf->channel; 293 sec_chan = iface->conf->secondary_channel * 4; 294 pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); 295 if (iface->conf->secondary_channel > 0) 296 sec_freq = pri_freq + 20; 297 else 298 sec_freq = pri_freq - 20; 299 300 /* 301 * Switch PRI/SEC channels if Beacons were detected on selected SEC 302 * channel, but not on selected PRI channel. 303 */ 304 pri_bss = sec_bss = 0; 305 for (i = 0; i < scan_res->num; i++) { 306 struct wpa_scan_res *bss = scan_res->res[i]; 307 if (bss->freq == pri_freq) 308 pri_bss++; 309 else if (bss->freq == sec_freq) 310 sec_bss++; 311 } 312 if (sec_bss && !pri_bss) { 313 wpa_printf(MSG_INFO, "Switch own primary and secondary " 314 "channel to get secondary channel with no Beacons " 315 "from other BSSes"); 316 ieee80211n_switch_pri_sec(iface); 317 } 318 319 /* 320 * Match PRI/SEC channel with any existing HT40 BSS on the same 321 * channels that we are about to use (if already mixed order in 322 * existing BSSes, use own preference). 323 */ 324 match = 0; 325 for (i = 0; i < scan_res->num; i++) { 326 struct wpa_scan_res *bss = scan_res->res[i]; 327 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); 328 if (pri_chan == bss_pri_chan && 329 sec_chan == bss_sec_chan) { 330 match = 1; 331 break; 332 } 333 } 334 if (!match) { 335 for (i = 0; i < scan_res->num; i++) { 336 struct wpa_scan_res *bss = scan_res->res[i]; 337 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, 338 &bss_sec_chan); 339 if (pri_chan == bss_sec_chan && 340 sec_chan == bss_pri_chan) { 341 wpa_printf(MSG_INFO, "Switch own primary and " 342 "secondary channel due to BSS " 343 "overlap with " MACSTR, 344 MAC2STR(bss->bssid)); 345 ieee80211n_switch_pri_sec(iface); 346 break; 347 } 348 } 349 } 350 351 return 1; 352 } 353 354 355 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 356 struct wpa_scan_results *scan_res) 357 { 358 int pri_freq, sec_freq; 359 int affected_start, affected_end; 360 size_t i; 361 362 pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 363 if (iface->conf->secondary_channel > 0) 364 sec_freq = pri_freq + 20; 365 else 366 sec_freq = pri_freq - 20; 367 affected_start = (pri_freq + sec_freq) / 2 - 25; 368 affected_end = (pri_freq + sec_freq) / 2 + 25; 369 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 370 affected_start, affected_end); 371 for (i = 0; i < scan_res->num; i++) { 372 struct wpa_scan_res *bss = scan_res->res[i]; 373 int pri = bss->freq; 374 int sec = pri; 375 int sec_chan, pri_chan; 376 377 ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); 378 379 if (sec_chan) { 380 if (sec_chan < pri_chan) 381 sec = pri - 20; 382 else 383 sec = pri + 20; 384 } 385 386 if ((pri < affected_start || pri > affected_end) && 387 (sec < affected_start || sec > affected_end)) 388 continue; /* not within affected channel range */ 389 390 wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR 391 " freq=%d pri=%d sec=%d", 392 MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); 393 394 if (sec_chan) { 395 if (pri_freq != pri || sec_freq != sec) { 396 wpa_printf(MSG_DEBUG, "40 MHz pri/sec " 397 "mismatch with BSS " MACSTR 398 " <%d,%d> (chan=%d%c) vs. <%d,%d>", 399 MAC2STR(bss->bssid), 400 pri, sec, pri_chan, 401 sec > pri ? '+' : '-', 402 pri_freq, sec_freq); 403 return 0; 404 } 405 } 406 407 /* TODO: 40 MHz intolerant */ 408 } 409 410 return 1; 411 } 412 413 414 static void ieee80211n_check_scan(struct hostapd_iface *iface) 415 { 416 struct wpa_scan_results *scan_res; 417 int oper40; 418 int res; 419 420 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 421 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 422 423 iface->scan_cb = NULL; 424 425 scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 426 if (scan_res == NULL) { 427 hostapd_setup_interface_complete(iface, 1); 428 return; 429 } 430 431 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 432 oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 433 else 434 oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 435 wpa_scan_results_free(scan_res); 436 437 if (!oper40) { 438 wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 439 "channel pri=%d sec=%d based on overlapping BSSes", 440 iface->conf->channel, 441 iface->conf->channel + 442 iface->conf->secondary_channel * 4); 443 iface->conf->secondary_channel = 0; 444 iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 445 } 446 447 res = ieee80211n_allowed_ht40_channel_pair(iface); 448 hostapd_setup_interface_complete(iface, !res); 449 } 450 451 452 static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, 453 struct wpa_driver_scan_params *params) 454 { 455 /* Scan only the affected frequency range */ 456 int pri_freq, sec_freq; 457 int affected_start, affected_end; 458 int i, pos; 459 struct hostapd_hw_modes *mode; 460 461 if (iface->current_mode == NULL) 462 return; 463 464 pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 465 if (iface->conf->secondary_channel > 0) 466 sec_freq = pri_freq + 20; 467 else 468 sec_freq = pri_freq - 20; 469 affected_start = (pri_freq + sec_freq) / 2 - 25; 470 affected_end = (pri_freq + sec_freq) / 2 + 25; 471 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 472 affected_start, affected_end); 473 474 mode = iface->current_mode; 475 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 476 if (params->freqs == NULL) 477 return; 478 pos = 0; 479 480 for (i = 0; i < mode->num_channels; i++) { 481 struct hostapd_channel_data *chan = &mode->channels[i]; 482 if (chan->flag & HOSTAPD_CHAN_DISABLED) 483 continue; 484 if (chan->freq < affected_start || 485 chan->freq > affected_end) 486 continue; 487 params->freqs[pos++] = chan->freq; 488 } 489 } 490 491 492 static int ieee80211n_check_40mhz(struct hostapd_iface *iface) 493 { 494 struct wpa_driver_scan_params params; 495 496 if (!iface->conf->secondary_channel) 497 return 0; /* HT40 not used */ 498 499 wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 500 "40 MHz channel"); 501 os_memset(¶ms, 0, sizeof(params)); 502 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 503 ieee80211n_scan_channels_2g4(iface, ¶ms); 504 if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { 505 wpa_printf(MSG_ERROR, "Failed to request a scan of " 506 "neighboring BSSes"); 507 os_free(params.freqs); 508 return -1; 509 } 510 os_free(params.freqs); 511 512 iface->scan_cb = ieee80211n_check_scan; 513 return 1; 514 } 515 516 517 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 518 { 519 u16 hw = iface->current_mode->ht_capab; 520 u16 conf = iface->conf->ht_capab; 521 522 if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 523 !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 524 wpa_printf(MSG_ERROR, "Driver does not support configured " 525 "HT capability [LDPC]"); 526 return 0; 527 } 528 529 if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 530 !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 531 wpa_printf(MSG_ERROR, "Driver does not support configured " 532 "HT capability [HT40*]"); 533 return 0; 534 } 535 536 if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) && 537 (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) { 538 wpa_printf(MSG_ERROR, "Driver does not support configured " 539 "HT capability [SMPS-*]"); 540 return 0; 541 } 542 543 if ((conf & HT_CAP_INFO_GREEN_FIELD) && 544 !(hw & HT_CAP_INFO_GREEN_FIELD)) { 545 wpa_printf(MSG_ERROR, "Driver does not support configured " 546 "HT capability [GF]"); 547 return 0; 548 } 549 550 if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 551 !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 552 wpa_printf(MSG_ERROR, "Driver does not support configured " 553 "HT capability [SHORT-GI-20]"); 554 return 0; 555 } 556 557 if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 558 !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 559 wpa_printf(MSG_ERROR, "Driver does not support configured " 560 "HT capability [SHORT-GI-40]"); 561 return 0; 562 } 563 564 if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 565 wpa_printf(MSG_ERROR, "Driver does not support configured " 566 "HT capability [TX-STBC]"); 567 return 0; 568 } 569 570 if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 571 (hw & HT_CAP_INFO_RX_STBC_MASK)) { 572 wpa_printf(MSG_ERROR, "Driver does not support configured " 573 "HT capability [RX-STBC*]"); 574 return 0; 575 } 576 577 if ((conf & HT_CAP_INFO_DELAYED_BA) && 578 !(hw & HT_CAP_INFO_DELAYED_BA)) { 579 wpa_printf(MSG_ERROR, "Driver does not support configured " 580 "HT capability [DELAYED-BA]"); 581 return 0; 582 } 583 584 if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 585 !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 586 wpa_printf(MSG_ERROR, "Driver does not support configured " 587 "HT capability [MAX-AMSDU-7935]"); 588 return 0; 589 } 590 591 if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 592 !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 593 wpa_printf(MSG_ERROR, "Driver does not support configured " 594 "HT capability [DSSS_CCK-40]"); 595 return 0; 596 } 597 598 if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) { 599 wpa_printf(MSG_ERROR, "Driver does not support configured " 600 "HT capability [PSMP]"); 601 return 0; 602 } 603 604 if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 605 !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 606 wpa_printf(MSG_ERROR, "Driver does not support configured " 607 "HT capability [LSIG-TXOP-PROT]"); 608 return 0; 609 } 610 611 return 1; 612 } 613 614 #endif /* CONFIG_IEEE80211N */ 615 616 617 int hostapd_check_ht_capab(struct hostapd_iface *iface) 618 { 619 #ifdef CONFIG_IEEE80211N 620 int ret; 621 if (!iface->conf->ieee80211n) 622 return 0; 623 if (!ieee80211n_supported_ht_capab(iface)) 624 return -1; 625 ret = ieee80211n_check_40mhz(iface); 626 if (ret) 627 return ret; 628 if (!ieee80211n_allowed_ht40_channel_pair(iface)) 629 return -1; 630 #endif /* CONFIG_IEEE80211N */ 631 632 return 0; 633 } 634 635 636 /** 637 * hostapd_select_hw_mode - Select the hardware mode 638 * @iface: Pointer to interface data. 639 * Returns: 0 on success, < 0 on failure 640 * 641 * Sets up the hardware mode, channel, rates, and passive scanning 642 * based on the configuration. 643 */ 644 int hostapd_select_hw_mode(struct hostapd_iface *iface) 645 { 646 int i, j, ok; 647 648 if (iface->num_hw_features < 1) 649 return -1; 650 651 iface->current_mode = NULL; 652 for (i = 0; i < iface->num_hw_features; i++) { 653 struct hostapd_hw_modes *mode = &iface->hw_features[i]; 654 if (mode->mode == iface->conf->hw_mode) { 655 iface->current_mode = mode; 656 break; 657 } 658 } 659 660 if (iface->current_mode == NULL) { 661 wpa_printf(MSG_ERROR, "Hardware does not support configured " 662 "mode"); 663 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 664 HOSTAPD_LEVEL_WARNING, 665 "Hardware does not support configured mode " 666 "(%d) (hw_mode in hostapd.conf)", 667 (int) iface->conf->hw_mode); 668 return -2; 669 } 670 671 ok = 0; 672 for (j = 0; j < iface->current_mode->num_channels; j++) { 673 struct hostapd_channel_data *chan = 674 &iface->current_mode->channels[j]; 675 if (chan->chan == iface->conf->channel) { 676 if (chan->flag & HOSTAPD_CHAN_DISABLED) { 677 wpa_printf(MSG_ERROR, 678 "channel [%i] (%i) is disabled for " 679 "use in AP mode, flags: 0x%x%s%s%s", 680 j, chan->chan, chan->flag, 681 chan->flag & HOSTAPD_CHAN_NO_IBSS ? 682 " NO-IBSS" : "", 683 chan->flag & 684 HOSTAPD_CHAN_PASSIVE_SCAN ? 685 " PASSIVE-SCAN" : "", 686 chan->flag & HOSTAPD_CHAN_RADAR ? 687 " RADAR" : ""); 688 } else { 689 ok = 1; 690 break; 691 } 692 } 693 } 694 if (ok && iface->conf->secondary_channel) { 695 int sec_ok = 0; 696 int sec_chan = iface->conf->channel + 697 iface->conf->secondary_channel * 4; 698 for (j = 0; j < iface->current_mode->num_channels; j++) { 699 struct hostapd_channel_data *chan = 700 &iface->current_mode->channels[j]; 701 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 702 (chan->chan == sec_chan)) { 703 sec_ok = 1; 704 break; 705 } 706 } 707 if (!sec_ok) { 708 hostapd_logger(iface->bss[0], NULL, 709 HOSTAPD_MODULE_IEEE80211, 710 HOSTAPD_LEVEL_WARNING, 711 "Configured HT40 secondary channel " 712 "(%d) not found from the channel list " 713 "of current mode (%d) %s", 714 sec_chan, iface->current_mode->mode, 715 hostapd_hw_mode_txt( 716 iface->current_mode->mode)); 717 ok = 0; 718 } 719 } 720 if (iface->conf->channel == 0) { 721 /* TODO: could request a scan of neighboring BSSes and select 722 * the channel automatically */ 723 wpa_printf(MSG_ERROR, "Channel not configured " 724 "(hw_mode/channel in hostapd.conf)"); 725 return -3; 726 } 727 if (ok == 0 && iface->conf->channel != 0) { 728 hostapd_logger(iface->bss[0], NULL, 729 HOSTAPD_MODULE_IEEE80211, 730 HOSTAPD_LEVEL_WARNING, 731 "Configured channel (%d) not found from the " 732 "channel list of current mode (%d) %s", 733 iface->conf->channel, 734 iface->current_mode->mode, 735 hostapd_hw_mode_txt(iface->current_mode->mode)); 736 iface->current_mode = NULL; 737 } 738 739 if (iface->current_mode == NULL) { 740 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 741 HOSTAPD_LEVEL_WARNING, 742 "Hardware does not support configured channel"); 743 return -4; 744 } 745 746 return 0; 747 } 748 749 750 const char * hostapd_hw_mode_txt(int mode) 751 { 752 switch (mode) { 753 case HOSTAPD_MODE_IEEE80211A: 754 return "IEEE 802.11a"; 755 case HOSTAPD_MODE_IEEE80211B: 756 return "IEEE 802.11b"; 757 case HOSTAPD_MODE_IEEE80211G: 758 return "IEEE 802.11g"; 759 default: 760 return "UNKNOWN"; 761 } 762 } 763 764 765 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 766 { 767 int i; 768 769 if (!hapd->iface->current_mode) 770 return 0; 771 772 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 773 struct hostapd_channel_data *ch = 774 &hapd->iface->current_mode->channels[i]; 775 if (ch->chan == chan) 776 return ch->freq; 777 } 778 779 return 0; 780 } 781 782 783 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 784 { 785 int i; 786 787 if (!hapd->iface->current_mode) 788 return 0; 789 790 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 791 struct hostapd_channel_data *ch = 792 &hapd->iface->current_mode->channels[i]; 793 if (ch->freq == freq) 794 return ch->chan; 795 } 796 797 return 0; 798 } 799