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 "acs.h" 28#include "hw_features.h" 29 30 31void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 32 size_t num_hw_features) 33{ 34 size_t i; 35 36 if (hw_features == NULL) 37 return; 38 39 for (i = 0; i < num_hw_features; i++) { 40 os_free(hw_features[i].channels); 41 os_free(hw_features[i].rates); 42 } 43 44 os_free(hw_features); 45} 46 47 48int hostapd_get_hw_features(struct hostapd_iface *iface) 49{ 50 struct hostapd_data *hapd = iface->bss[0]; 51 int ret = 0, i, j; 52 u16 num_modes, flags; 53 struct hostapd_hw_modes *modes; 54 55 if (hostapd_drv_none(hapd)) 56 return -1; 57 modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); 58 if (modes == NULL) { 59 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 60 HOSTAPD_LEVEL_DEBUG, 61 "Fetching hardware channel/rate support not " 62 "supported."); 63 return -1; 64 } 65 66 iface->hw_flags = flags; 67 68 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 69 iface->hw_features = modes; 70 iface->num_hw_features = num_modes; 71 72 for (i = 0; i < num_modes; i++) { 73 struct hostapd_hw_modes *feature = &modes[i]; 74 /* set flag for channels we can use in current regulatory 75 * domain */ 76 for (j = 0; j < feature->num_channels; j++) { 77 /* 78 * Disable all channels that are marked not to allow 79 * IBSS operation or active scanning. In addition, 80 * disable all channels that require radar detection, 81 * since that (in addition to full DFS) is not yet 82 * supported. 83 */ 84 if (feature->channels[j].flag & 85 (HOSTAPD_CHAN_NO_IBSS | 86 HOSTAPD_CHAN_PASSIVE_SCAN | 87 HOSTAPD_CHAN_RADAR)) 88 feature->channels[j].flag |= 89 HOSTAPD_CHAN_DISABLED; 90 if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 91 continue; 92 wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 93 "chan=%d freq=%d MHz max_tx_power=%d dBm", 94 feature->mode, 95 feature->channels[j].chan, 96 feature->channels[j].freq, 97 feature->channels[j].max_tx_power); 98 } 99 } 100 101 return ret; 102} 103 104 105int hostapd_prepare_rates(struct hostapd_iface *iface, 106 struct hostapd_hw_modes *mode) 107{ 108 int i, num_basic_rates = 0; 109 int basic_rates_a[] = { 60, 120, 240, -1 }; 110 int basic_rates_b[] = { 10, 20, -1 }; 111 int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 112 int *basic_rates; 113 114 if (iface->conf->basic_rates) 115 basic_rates = iface->conf->basic_rates; 116 else switch (mode->mode) { 117 case HOSTAPD_MODE_IEEE80211A: 118 basic_rates = basic_rates_a; 119 break; 120 case HOSTAPD_MODE_IEEE80211B: 121 basic_rates = basic_rates_b; 122 break; 123 case HOSTAPD_MODE_IEEE80211G: 124 basic_rates = basic_rates_g; 125 break; 126 case HOSTAPD_MODE_IEEE80211AD: 127 return 0; /* No basic rates for 11ad */ 128 default: 129 return -1; 130 } 131 132 i = 0; 133 while (basic_rates[i] >= 0) 134 i++; 135 if (i) 136 i++; /* -1 termination */ 137 os_free(iface->basic_rates); 138 iface->basic_rates = os_malloc(i * sizeof(int)); 139 if (iface->basic_rates) 140 os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 141 142 os_free(iface->current_rates); 143 iface->num_rates = 0; 144 145 iface->current_rates = 146 os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 147 if (!iface->current_rates) { 148 wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 149 "table."); 150 return -1; 151 } 152 153 for (i = 0; i < mode->num_rates; i++) { 154 struct hostapd_rate_data *rate; 155 156 if (iface->conf->supported_rates && 157 !hostapd_rate_found(iface->conf->supported_rates, 158 mode->rates[i])) 159 continue; 160 161 rate = &iface->current_rates[iface->num_rates]; 162 rate->rate = mode->rates[i]; 163 if (hostapd_rate_found(basic_rates, rate->rate)) { 164 rate->flags |= HOSTAPD_RATE_BASIC; 165 num_basic_rates++; 166 } 167 wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 168 iface->num_rates, rate->rate, rate->flags); 169 iface->num_rates++; 170 } 171 172 if ((iface->num_rates == 0 || num_basic_rates == 0) && 173 (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 174 wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 175 "rate sets (%d,%d).", 176 iface->num_rates, num_basic_rates); 177 return -1; 178 } 179 180 return 0; 181} 182 183 184#ifdef CONFIG_IEEE80211N 185static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 186{ 187 int sec_chan, ok, j, first; 188 int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 189 184, 192 }; 190 size_t k; 191 192 if (!iface->conf->secondary_channel) 193 return 1; /* HT40 not used */ 194 195 sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; 196 wpa_printf(MSG_DEBUG, "HT40: control channel: %d " 197 "secondary channel: %d", 198 iface->conf->channel, sec_chan); 199 200 /* Verify that HT40 secondary channel is an allowed 20 MHz 201 * channel */ 202 ok = 0; 203 for (j = 0; j < iface->current_mode->num_channels; j++) { 204 struct hostapd_channel_data *chan = 205 &iface->current_mode->channels[j]; 206 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 207 chan->chan == sec_chan) { 208 ok = 1; 209 break; 210 } 211 } 212 if (!ok) { 213 wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", 214 sec_chan); 215 return 0; 216 } 217 218 /* 219 * Verify that HT40 primary,secondary channel pair is allowed per 220 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since 221 * 2.4 GHz rules allow all cases where the secondary channel fits into 222 * the list of allowed channels (already checked above). 223 */ 224 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 225 return 1; 226 227 if (iface->conf->secondary_channel > 0) 228 first = iface->conf->channel; 229 else 230 first = sec_chan; 231 232 ok = 0; 233 for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) { 234 if (first == allowed[k]) { 235 ok = 1; 236 break; 237 } 238 } 239 if (!ok) { 240 wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", 241 iface->conf->channel, 242 iface->conf->secondary_channel); 243 return 0; 244 } 245 246 return 1; 247} 248 249 250static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 251{ 252 if (iface->conf->secondary_channel > 0) { 253 iface->conf->channel += 4; 254 iface->conf->secondary_channel = -1; 255 } else { 256 iface->conf->channel -= 4; 257 iface->conf->secondary_channel = 1; 258 } 259} 260 261 262static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, 263 int *pri_chan, int *sec_chan) 264{ 265 struct ieee80211_ht_operation *oper; 266 struct ieee802_11_elems elems; 267 268 *pri_chan = *sec_chan = 0; 269 270 ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); 271 if (elems.ht_operation && 272 elems.ht_operation_len >= sizeof(*oper)) { 273 oper = (struct ieee80211_ht_operation *) elems.ht_operation; 274 *pri_chan = oper->control_chan; 275 if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { 276 int sec = oper->ht_param & 277 HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; 278 if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) 279 *sec_chan = *pri_chan + 4; 280 else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) 281 *sec_chan = *pri_chan - 4; 282 } 283 } 284} 285 286 287static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 288 struct wpa_scan_results *scan_res) 289{ 290 int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; 291 int bss_pri_chan, bss_sec_chan; 292 size_t i; 293 int match; 294 295 pri_chan = iface->conf->channel; 296 sec_chan = iface->conf->secondary_channel * 4; 297 pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); 298 if (iface->conf->secondary_channel > 0) 299 sec_freq = pri_freq + 20; 300 else 301 sec_freq = pri_freq - 20; 302 303 /* 304 * Switch PRI/SEC channels if Beacons were detected on selected SEC 305 * channel, but not on selected PRI channel. 306 */ 307 pri_bss = sec_bss = 0; 308 for (i = 0; i < scan_res->num; i++) { 309 struct wpa_scan_res *bss = scan_res->res[i]; 310 if (bss->freq == pri_freq) 311 pri_bss++; 312 else if (bss->freq == sec_freq) 313 sec_bss++; 314 } 315 if (sec_bss && !pri_bss) { 316 wpa_printf(MSG_INFO, "Switch own primary and secondary " 317 "channel to get secondary channel with no Beacons " 318 "from other BSSes"); 319 ieee80211n_switch_pri_sec(iface); 320 } 321 322 /* 323 * Match PRI/SEC channel with any existing HT40 BSS on the same 324 * channels that we are about to use (if already mixed order in 325 * existing BSSes, use own preference). 326 */ 327 match = 0; 328 for (i = 0; i < scan_res->num; i++) { 329 struct wpa_scan_res *bss = scan_res->res[i]; 330 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); 331 if (pri_chan == bss_pri_chan && 332 sec_chan == bss_sec_chan) { 333 match = 1; 334 break; 335 } 336 } 337 if (!match) { 338 for (i = 0; i < scan_res->num; i++) { 339 struct wpa_scan_res *bss = scan_res->res[i]; 340 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, 341 &bss_sec_chan); 342 if (pri_chan == bss_sec_chan && 343 sec_chan == bss_pri_chan) { 344 wpa_printf(MSG_INFO, "Switch own primary and " 345 "secondary channel due to BSS " 346 "overlap with " MACSTR, 347 MAC2STR(bss->bssid)); 348 ieee80211n_switch_pri_sec(iface); 349 break; 350 } 351 } 352 } 353 354 return 1; 355} 356 357 358static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 359 struct wpa_scan_results *scan_res) 360{ 361 int pri_freq, sec_freq; 362 int affected_start, affected_end; 363 size_t i; 364 365 pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 366 if (iface->conf->secondary_channel > 0) 367 sec_freq = pri_freq + 20; 368 else 369 sec_freq = pri_freq - 20; 370 affected_start = (pri_freq + sec_freq) / 2 - 25; 371 affected_end = (pri_freq + sec_freq) / 2 + 25; 372 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 373 affected_start, affected_end); 374 for (i = 0; i < scan_res->num; i++) { 375 struct wpa_scan_res *bss = scan_res->res[i]; 376 int pri = bss->freq; 377 int sec = pri; 378 int sec_chan, pri_chan; 379 380 ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); 381 382 if (sec_chan) { 383 if (sec_chan < pri_chan) 384 sec = pri - 20; 385 else 386 sec = pri + 20; 387 } 388 389 if ((pri < affected_start || pri > affected_end) && 390 (sec < affected_start || sec > affected_end)) 391 continue; /* not within affected channel range */ 392 393 wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR 394 " freq=%d pri=%d sec=%d", 395 MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); 396 397 if (sec_chan) { 398 if (pri_freq != pri || sec_freq != sec) { 399 wpa_printf(MSG_DEBUG, "40 MHz pri/sec " 400 "mismatch with BSS " MACSTR 401 " <%d,%d> (chan=%d%c) vs. <%d,%d>", 402 MAC2STR(bss->bssid), 403 pri, sec, pri_chan, 404 sec > pri ? '+' : '-', 405 pri_freq, sec_freq); 406 return 0; 407 } 408 } 409 410 /* TODO: 40 MHz intolerant */ 411 } 412 413 return 1; 414} 415 416 417static void ieee80211n_check_scan(struct hostapd_iface *iface) 418{ 419 struct wpa_scan_results *scan_res; 420 int oper40; 421 int res; 422 423 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 424 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 425 426 iface->scan_cb = NULL; 427 428 scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 429 if (scan_res == NULL) { 430 hostapd_setup_interface_complete(iface, 1); 431 return; 432 } 433 434 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 435 oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 436 else 437 oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 438 wpa_scan_results_free(scan_res); 439 440 if (!oper40) { 441 wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 442 "channel pri=%d sec=%d based on overlapping BSSes", 443 iface->conf->channel, 444 iface->conf->channel + 445 iface->conf->secondary_channel * 4); 446 iface->conf->secondary_channel = 0; 447 } 448 449 res = ieee80211n_allowed_ht40_channel_pair(iface); 450 hostapd_setup_interface_complete(iface, !res); 451} 452 453 454static 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 494static 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 519static 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 619int 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 638static int hostapd_is_usable_chan(struct hostapd_iface *iface, 639 int channel, int primary) 640{ 641 int i; 642 struct hostapd_channel_data *chan; 643 644 for (i = 0; i < iface->current_mode->num_channels; i++) { 645 chan = &iface->current_mode->channels[i]; 646 if (chan->chan != channel) 647 continue; 648 649 if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) 650 return 1; 651 652 wpa_printf(MSG_DEBUG, 653 "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s%s", 654 primary ? "" : "Configured HT40 secondary ", 655 i, chan->chan, chan->flag, 656 chan->flag & HOSTAPD_CHAN_NO_IBSS ? " NO-IBSS" : "", 657 chan->flag & HOSTAPD_CHAN_PASSIVE_SCAN ? 658 " PASSIVE-SCAN" : "", 659 chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); 660 } 661 662 return 0; 663} 664 665 666static int hostapd_is_usable_chans(struct hostapd_iface *iface) 667{ 668 if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) 669 return 0; 670 671 if (!iface->conf->secondary_channel) 672 return 1; 673 674 return hostapd_is_usable_chan(iface, iface->conf->channel + 675 iface->conf->secondary_channel * 4, 0); 676} 677 678 679static enum hostapd_chan_status 680hostapd_check_chans(struct hostapd_iface *iface) 681{ 682 if (iface->conf->channel) { 683 if (hostapd_is_usable_chans(iface)) 684 return HOSTAPD_CHAN_VALID; 685 else 686 return HOSTAPD_CHAN_INVALID; 687 } 688 689 /* 690 * The user set channel=0 or channel=acs_survey 691 * which is used to trigger ACS. 692 */ 693 694 switch (acs_init(iface)) { 695 case HOSTAPD_CHAN_ACS: 696 return HOSTAPD_CHAN_ACS; 697 case HOSTAPD_CHAN_VALID: 698 case HOSTAPD_CHAN_INVALID: 699 default: 700 return HOSTAPD_CHAN_INVALID; 701 } 702} 703 704 705static void hostapd_notify_bad_chans(struct hostapd_iface *iface) 706{ 707 hostapd_logger(iface->bss[0], NULL, 708 HOSTAPD_MODULE_IEEE80211, 709 HOSTAPD_LEVEL_WARNING, 710 "Configured channel (%d) not found from the " 711 "channel list of current mode (%d) %s", 712 iface->conf->channel, 713 iface->current_mode->mode, 714 hostapd_hw_mode_txt(iface->current_mode->mode)); 715 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 716 HOSTAPD_LEVEL_WARNING, 717 "Hardware does not support configured channel"); 718} 719 720 721int hostapd_acs_completed(struct hostapd_iface *iface) 722{ 723 int ret; 724 725 switch (hostapd_check_chans(iface)) { 726 case HOSTAPD_CHAN_VALID: 727 break; 728 case HOSTAPD_CHAN_ACS: 729 wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); 730 hostapd_notify_bad_chans(iface); 731 return -1; 732 case HOSTAPD_CHAN_INVALID: 733 default: 734 wpa_printf(MSG_ERROR, "ACS picked unusable channels"); 735 hostapd_notify_bad_chans(iface); 736 return -1; 737 } 738 739 ret = hostapd_check_ht_capab(iface); 740 if (ret < 0) 741 return -1; 742 if (ret == 1) { 743 wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); 744 return 0; 745 } 746 747 return hostapd_setup_interface_complete(iface, 0); 748} 749 750 751/** 752 * hostapd_select_hw_mode - Select the hardware mode 753 * @iface: Pointer to interface data. 754 * Returns: 0 on success, < 0 on failure 755 * 756 * Sets up the hardware mode, channel, rates, and passive scanning 757 * based on the configuration. 758 */ 759int hostapd_select_hw_mode(struct hostapd_iface *iface) 760{ 761 int i; 762 763 if (iface->num_hw_features < 1) 764 return -1; 765 766 iface->current_mode = NULL; 767 for (i = 0; i < iface->num_hw_features; i++) { 768 struct hostapd_hw_modes *mode = &iface->hw_features[i]; 769 if (mode->mode == iface->conf->hw_mode) { 770 iface->current_mode = mode; 771 break; 772 } 773 } 774 775 if (iface->current_mode == NULL) { 776 wpa_printf(MSG_ERROR, "Hardware does not support configured " 777 "mode"); 778 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 779 HOSTAPD_LEVEL_WARNING, 780 "Hardware does not support configured mode " 781 "(%d) (hw_mode in hostapd.conf)", 782 (int) iface->conf->hw_mode); 783 return -2; 784 } 785 786 switch (hostapd_check_chans(iface)) { 787 case HOSTAPD_CHAN_VALID: 788 return 0; 789 case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ 790 return 1; 791 case HOSTAPD_CHAN_INVALID: 792 default: 793 hostapd_notify_bad_chans(iface); 794 return -3; 795 } 796 797 return 0; 798} 799 800 801const char * hostapd_hw_mode_txt(int mode) 802{ 803 switch (mode) { 804 case HOSTAPD_MODE_IEEE80211A: 805 return "IEEE 802.11a"; 806 case HOSTAPD_MODE_IEEE80211B: 807 return "IEEE 802.11b"; 808 case HOSTAPD_MODE_IEEE80211G: 809 return "IEEE 802.11g"; 810 case HOSTAPD_MODE_IEEE80211AD: 811 return "IEEE 802.11ad"; 812 default: 813 return "UNKNOWN"; 814 } 815} 816 817 818int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 819{ 820 int i; 821 822 if (!hapd->iface->current_mode) 823 return 0; 824 825 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 826 struct hostapd_channel_data *ch = 827 &hapd->iface->current_mode->channels[i]; 828 if (ch->chan == chan) 829 return ch->freq; 830 } 831 832 return 0; 833} 834 835 836int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 837{ 838 int i; 839 840 if (!hapd->iface->current_mode) 841 return 0; 842 843 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 844 struct hostapd_channel_data *ch = 845 &hapd->iface->current_mode->channels[i]; 846 if (ch->freq == freq) 847 return ch->chan; 848 } 849 850 return 0; 851} 852