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