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 software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "utils/includes.h" 12 13 #include "utils/common.h" 14 #include "utils/eloop.h" 15 #include "common/ieee802_11_defs.h" 16 #include "common/ieee802_11_common.h" 17 #include "common/wpa_ctrl.h" 18 #include "common/hw_features_common.h" 19 #include "hostapd.h" 20 #include "ap_config.h" 21 #include "ap_drv_ops.h" 22 #include "acs.h" 23 #include "ieee802_11.h" 24 #include "beacon.h" 25 #include "hw_features.h" 26 27 28 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 29 size_t num_hw_features) 30 { 31 size_t i; 32 33 if (hw_features == NULL) 34 return; 35 36 for (i = 0; i < num_hw_features; i++) { 37 os_free(hw_features[i].channels); 38 os_free(hw_features[i].rates); 39 } 40 41 os_free(hw_features); 42 } 43 44 45 #ifndef CONFIG_NO_STDOUT_DEBUG 46 static char * dfs_info(struct hostapd_channel_data *chan) 47 { 48 static char info[256]; 49 char *state; 50 51 switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { 52 case HOSTAPD_CHAN_DFS_UNKNOWN: 53 state = "unknown"; 54 break; 55 case HOSTAPD_CHAN_DFS_USABLE: 56 state = "usable"; 57 break; 58 case HOSTAPD_CHAN_DFS_UNAVAILABLE: 59 state = "unavailable"; 60 break; 61 case HOSTAPD_CHAN_DFS_AVAILABLE: 62 state = "available"; 63 break; 64 default: 65 return ""; 66 } 67 os_snprintf(info, sizeof(info), " (DFS state = %s)", state); 68 info[sizeof(info) - 1] = '\0'; 69 70 return info; 71 } 72 #endif /* CONFIG_NO_STDOUT_DEBUG */ 73 74 75 int hostapd_get_hw_features(struct hostapd_iface *iface) 76 { 77 struct hostapd_data *hapd = iface->bss[0]; 78 int i, j; 79 u16 num_modes, flags; 80 struct hostapd_hw_modes *modes; 81 u8 dfs_domain; 82 enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY; 83 bool is_6ghz = false; 84 bool orig_mode_valid = false; 85 86 if (hostapd_drv_none(hapd)) 87 return -1; 88 modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, 89 &dfs_domain); 90 if (modes == NULL) { 91 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 92 HOSTAPD_LEVEL_DEBUG, 93 "Fetching hardware channel/rate support not " 94 "supported."); 95 return -1; 96 } 97 98 iface->hw_flags = flags; 99 iface->dfs_domain = dfs_domain; 100 101 if (iface->current_mode) { 102 /* 103 * Received driver event CHANNEL_LIST_CHANGED when the current 104 * hw mode is valid. Clear iface->current_mode temporarily as 105 * the mode instance will be replaced with a new instance and 106 * the current pointer would be pointing to freed memory. 107 */ 108 orig_mode_valid = true; 109 mode = iface->current_mode->mode; 110 is_6ghz = iface->current_mode->is_6ghz; 111 iface->current_mode = NULL; 112 } 113 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 114 iface->hw_features = modes; 115 iface->num_hw_features = num_modes; 116 117 for (i = 0; i < num_modes; i++) { 118 struct hostapd_hw_modes *feature = &modes[i]; 119 int dfs_enabled = hapd->iconf->ieee80211h && 120 (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); 121 122 /* Restore orignal mode if possible */ 123 if (orig_mode_valid && feature->mode == mode && 124 feature->num_channels > 0 && 125 is_6ghz == is_6ghz_freq(feature->channels[0].freq)) 126 iface->current_mode = feature; 127 128 /* set flag for channels we can use in current regulatory 129 * domain */ 130 for (j = 0; j < feature->num_channels; j++) { 131 int dfs = 0; 132 133 /* 134 * Disable all channels that are marked not to allow 135 * to initiate radiation (a.k.a. passive scan and no 136 * IBSS). 137 * Use radar channels only if the driver supports DFS. 138 */ 139 if ((feature->channels[j].flag & 140 HOSTAPD_CHAN_RADAR) && dfs_enabled) { 141 dfs = 1; 142 } else if (((feature->channels[j].flag & 143 HOSTAPD_CHAN_RADAR) && 144 !(iface->drv_flags & 145 WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || 146 (feature->channels[j].flag & 147 HOSTAPD_CHAN_NO_IR)) { 148 feature->channels[j].flag |= 149 HOSTAPD_CHAN_DISABLED; 150 } 151 152 if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 153 continue; 154 155 wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 156 "chan=%d freq=%d MHz max_tx_power=%d dBm%s", 157 feature->mode, 158 feature->channels[j].chan, 159 feature->channels[j].freq, 160 feature->channels[j].max_tx_power, 161 dfs ? dfs_info(&feature->channels[j]) : ""); 162 } 163 } 164 165 if (orig_mode_valid && !iface->current_mode) { 166 wpa_printf(MSG_ERROR, 167 "%s: Could not update iface->current_mode", 168 __func__); 169 } 170 171 return 0; 172 } 173 174 175 int hostapd_prepare_rates(struct hostapd_iface *iface, 176 struct hostapd_hw_modes *mode) 177 { 178 int i, num_basic_rates = 0; 179 int basic_rates_a[] = { 60, 120, 240, -1 }; 180 int basic_rates_b[] = { 10, 20, -1 }; 181 int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 182 int *basic_rates; 183 184 if (iface->conf->basic_rates) 185 basic_rates = iface->conf->basic_rates; 186 else switch (mode->mode) { 187 case HOSTAPD_MODE_IEEE80211A: 188 basic_rates = basic_rates_a; 189 break; 190 case HOSTAPD_MODE_IEEE80211B: 191 basic_rates = basic_rates_b; 192 break; 193 case HOSTAPD_MODE_IEEE80211G: 194 basic_rates = basic_rates_g; 195 break; 196 case HOSTAPD_MODE_IEEE80211AD: 197 return 0; /* No basic rates for 11ad */ 198 default: 199 return -1; 200 } 201 202 i = 0; 203 while (basic_rates[i] >= 0) 204 i++; 205 if (i) 206 i++; /* -1 termination */ 207 os_free(iface->basic_rates); 208 iface->basic_rates = os_malloc(i * sizeof(int)); 209 if (iface->basic_rates) 210 os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 211 212 os_free(iface->current_rates); 213 iface->num_rates = 0; 214 215 iface->current_rates = 216 os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 217 if (!iface->current_rates) { 218 wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 219 "table."); 220 return -1; 221 } 222 223 for (i = 0; i < mode->num_rates; i++) { 224 struct hostapd_rate_data *rate; 225 226 if (iface->conf->supported_rates && 227 !hostapd_rate_found(iface->conf->supported_rates, 228 mode->rates[i])) 229 continue; 230 231 rate = &iface->current_rates[iface->num_rates]; 232 rate->rate = mode->rates[i]; 233 if (hostapd_rate_found(basic_rates, rate->rate)) { 234 rate->flags |= HOSTAPD_RATE_BASIC; 235 num_basic_rates++; 236 } 237 wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 238 iface->num_rates, rate->rate, rate->flags); 239 iface->num_rates++; 240 } 241 242 if ((iface->num_rates == 0 || num_basic_rates == 0) && 243 (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 244 wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 245 "rate sets (%d,%d).", 246 iface->num_rates, num_basic_rates); 247 return -1; 248 } 249 250 return 0; 251 } 252 253 254 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 255 { 256 int pri_freq, sec_freq; 257 struct hostapd_channel_data *p_chan, *s_chan; 258 259 pri_freq = iface->freq; 260 sec_freq = pri_freq + iface->conf->secondary_channel * 20; 261 262 if (!iface->current_mode) 263 return 0; 264 265 p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL, 266 iface->hw_features, 267 iface->num_hw_features); 268 269 s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL, 270 iface->hw_features, 271 iface->num_hw_features); 272 273 return allowed_ht40_channel_pair(iface->current_mode->mode, 274 p_chan, s_chan); 275 } 276 277 278 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 279 { 280 if (iface->conf->secondary_channel > 0) { 281 iface->conf->channel += 4; 282 iface->freq += 20; 283 iface->conf->secondary_channel = -1; 284 } else { 285 iface->conf->channel -= 4; 286 iface->freq -= 20; 287 iface->conf->secondary_channel = 1; 288 } 289 } 290 291 292 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 293 struct wpa_scan_results *scan_res) 294 { 295 unsigned int pri_freq, sec_freq; 296 int res; 297 struct hostapd_channel_data *pri_chan, *sec_chan; 298 299 pri_freq = iface->freq; 300 sec_freq = pri_freq + iface->conf->secondary_channel * 20; 301 302 if (!iface->current_mode) 303 return 0; 304 pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 305 NULL, iface->hw_features, 306 iface->num_hw_features); 307 sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 308 NULL, iface->hw_features, 309 iface->num_hw_features); 310 311 res = check_40mhz_5g(scan_res, pri_chan, sec_chan); 312 313 if (res == 2) { 314 if (iface->conf->no_pri_sec_switch) { 315 wpa_printf(MSG_DEBUG, 316 "Cannot switch PRI/SEC channels due to local constraint"); 317 } else { 318 ieee80211n_switch_pri_sec(iface); 319 } 320 } 321 322 return !!res; 323 } 324 325 326 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 327 struct wpa_scan_results *scan_res) 328 { 329 int pri_chan, sec_chan; 330 331 pri_chan = iface->conf->channel; 332 sec_chan = pri_chan + iface->conf->secondary_channel * 4; 333 334 return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan, 335 sec_chan); 336 } 337 338 339 static void ieee80211n_check_scan(struct hostapd_iface *iface) 340 { 341 struct wpa_scan_results *scan_res; 342 int oper40; 343 int res = 0; 344 345 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 346 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 347 348 iface->scan_cb = NULL; 349 350 scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 351 if (scan_res == NULL) { 352 hostapd_setup_interface_complete(iface, 1); 353 return; 354 } 355 356 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 357 oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 358 else 359 oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 360 wpa_scan_results_free(scan_res); 361 362 iface->secondary_ch = iface->conf->secondary_channel; 363 if (!oper40) { 364 wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 365 "channel pri=%d sec=%d based on overlapping BSSes", 366 iface->conf->channel, 367 iface->conf->channel + 368 iface->conf->secondary_channel * 4); 369 iface->conf->secondary_channel = 0; 370 if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { 371 /* 372 * TODO: Could consider scheduling another scan to check 373 * if channel width can be changed if no coex reports 374 * are received from associating stations. 375 */ 376 } 377 } 378 379 #ifdef CONFIG_IEEE80211AX 380 if (iface->conf->secondary_channel && 381 iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && 382 iface->conf->ieee80211ax) { 383 struct he_capabilities *he_cap; 384 385 he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP]; 386 if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & 387 HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) { 388 wpa_printf(MSG_DEBUG, 389 "HE: 40 MHz channel width is not supported in 2.4 GHz; clear secondary channel configuration"); 390 iface->conf->secondary_channel = 0; 391 } 392 } 393 #endif /* CONFIG_IEEE80211AX */ 394 395 if (iface->conf->secondary_channel) 396 res = ieee80211n_allowed_ht40_channel_pair(iface); 397 if (!res) { 398 iface->conf->secondary_channel = 0; 399 hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 0); 400 hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 0); 401 hostapd_set_oper_chwidth(iface->conf, CONF_OPER_CHWIDTH_USE_HT); 402 res = 1; 403 wpa_printf(MSG_INFO, "Fallback to 20 MHz"); 404 } 405 406 hostapd_setup_interface_complete(iface, !res); 407 } 408 409 410 static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, 411 struct wpa_driver_scan_params *params) 412 { 413 /* Scan only the affected frequency range */ 414 int pri_freq, sec_freq; 415 int affected_start, affected_end; 416 int i, pos; 417 struct hostapd_hw_modes *mode; 418 419 if (iface->current_mode == NULL) 420 return; 421 422 pri_freq = iface->freq; 423 if (iface->conf->secondary_channel > 0) 424 sec_freq = pri_freq + 20; 425 else 426 sec_freq = pri_freq - 20; 427 /* 428 * Note: Need to find the PRI channel also in cases where the affected 429 * channel is the SEC channel of a 40 MHz BSS, so need to include the 430 * scanning coverage here to be 40 MHz from the center frequency. 431 */ 432 affected_start = (pri_freq + sec_freq) / 2 - 40; 433 affected_end = (pri_freq + sec_freq) / 2 + 40; 434 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 435 affected_start, affected_end); 436 437 mode = iface->current_mode; 438 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 439 if (params->freqs == NULL) 440 return; 441 pos = 0; 442 443 for (i = 0; i < mode->num_channels; i++) { 444 struct hostapd_channel_data *chan = &mode->channels[i]; 445 if (chan->flag & HOSTAPD_CHAN_DISABLED) 446 continue; 447 if (chan->freq < affected_start || 448 chan->freq > affected_end) 449 continue; 450 params->freqs[pos++] = chan->freq; 451 } 452 } 453 454 455 static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, 456 struct wpa_driver_scan_params *params) 457 { 458 /* Scan only the affected frequency range */ 459 int pri_freq; 460 int affected_start, affected_end; 461 int i, pos; 462 struct hostapd_hw_modes *mode; 463 464 if (iface->current_mode == NULL) 465 return; 466 467 pri_freq = iface->freq; 468 if (iface->conf->secondary_channel > 0) { 469 affected_start = pri_freq - 10; 470 affected_end = pri_freq + 30; 471 } else { 472 affected_start = pri_freq - 30; 473 affected_end = pri_freq + 10; 474 } 475 wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 476 affected_start, affected_end); 477 478 mode = iface->current_mode; 479 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 480 if (params->freqs == NULL) 481 return; 482 pos = 0; 483 484 for (i = 0; i < mode->num_channels; i++) { 485 struct hostapd_channel_data *chan = &mode->channels[i]; 486 if (chan->flag & HOSTAPD_CHAN_DISABLED) 487 continue; 488 if (chan->freq < affected_start || 489 chan->freq > affected_end) 490 continue; 491 params->freqs[pos++] = chan->freq; 492 } 493 } 494 495 496 static void ap_ht40_scan_retry(void *eloop_data, void *user_data) 497 { 498 #define HT2040_COEX_SCAN_RETRY 15 499 struct hostapd_iface *iface = eloop_data; 500 struct wpa_driver_scan_params params; 501 int ret; 502 503 os_memset(¶ms, 0, sizeof(params)); 504 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 505 ieee80211n_scan_channels_2g4(iface, ¶ms); 506 else 507 ieee80211n_scan_channels_5g(iface, ¶ms); 508 509 params.link_id = -1; 510 #ifdef CONFIG_IEEE80211BE 511 if (iface->bss[0]->conf->mld_ap) 512 params.link_id = iface->bss[0]->mld_link_id; 513 #endif /* CONFIG_IEEE80211BE */ 514 515 ret = hostapd_driver_scan(iface->bss[0], ¶ms); 516 iface->num_ht40_scan_tries++; 517 os_free(params.freqs); 518 519 if (ret == -EBUSY && 520 iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { 521 wpa_printf(MSG_ERROR, 522 "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", 523 ret, strerror(-ret), iface->num_ht40_scan_tries); 524 eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 525 return; 526 } 527 528 if (ret == 0) { 529 iface->scan_cb = ieee80211n_check_scan; 530 iface->bss[0]->scan_cookie = params.scan_cookie; 531 return; 532 } 533 534 wpa_printf(MSG_DEBUG, 535 "Failed to request a scan in device, bringing up in HT20 mode"); 536 iface->conf->secondary_channel = 0; 537 iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 538 hostapd_setup_interface_complete(iface, 0); 539 } 540 541 542 void hostapd_stop_setup_timers(struct hostapd_iface *iface) 543 { 544 eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 545 } 546 547 548 static int ieee80211n_check_40mhz(struct hostapd_iface *iface) 549 { 550 struct wpa_driver_scan_params params; 551 int ret; 552 553 /* Check that HT40 is used and PRI / SEC switch is allowed */ 554 if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch) 555 return 0; 556 557 hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); 558 wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 559 "40 MHz channel"); 560 os_memset(¶ms, 0, sizeof(params)); 561 if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 562 ieee80211n_scan_channels_2g4(iface, ¶ms); 563 else 564 ieee80211n_scan_channels_5g(iface, ¶ms); 565 566 params.link_id = -1; 567 #ifdef CONFIG_IEEE80211BE 568 if (iface->bss[0]->conf->mld_ap) 569 params.link_id = iface->bss[0]->mld_link_id; 570 #endif /* CONFIG_IEEE80211BE */ 571 ret = hostapd_driver_scan(iface->bss[0], ¶ms); 572 os_free(params.freqs); 573 574 if (ret == -EBUSY) { 575 wpa_printf(MSG_ERROR, 576 "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", 577 ret, strerror(-ret)); 578 iface->num_ht40_scan_tries = 1; 579 eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 580 eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 581 return 1; 582 } 583 584 if (ret < 0) { 585 wpa_printf(MSG_ERROR, 586 "Failed to request a scan of neighboring BSSes ret=%d (%s)", 587 ret, strerror(-ret)); 588 return -1; 589 } 590 591 iface->scan_cb = ieee80211n_check_scan; 592 iface->bss[0]->scan_cookie = params.scan_cookie; 593 return 1; 594 } 595 596 597 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 598 { 599 u16 hw = iface->current_mode->ht_capab; 600 u16 conf = iface->conf->ht_capab; 601 602 if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 603 !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 604 wpa_printf(MSG_ERROR, "Driver does not support configured " 605 "HT capability [LDPC]"); 606 return 0; 607 } 608 609 /* 610 * Driver ACS chosen channel may not be HT40 due to internal driver 611 * restrictions. 612 */ 613 if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 614 !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 615 wpa_printf(MSG_ERROR, "Driver does not support configured " 616 "HT capability [HT40*]"); 617 return 0; 618 } 619 620 if ((conf & HT_CAP_INFO_GREEN_FIELD) && 621 !(hw & HT_CAP_INFO_GREEN_FIELD)) { 622 wpa_printf(MSG_ERROR, "Driver does not support configured " 623 "HT capability [GF]"); 624 return 0; 625 } 626 627 if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 628 !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 629 wpa_printf(MSG_ERROR, "Driver does not support configured " 630 "HT capability [SHORT-GI-20]"); 631 return 0; 632 } 633 634 if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 635 !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 636 wpa_printf(MSG_ERROR, "Driver does not support configured " 637 "HT capability [SHORT-GI-40]"); 638 return 0; 639 } 640 641 if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 642 wpa_printf(MSG_ERROR, "Driver does not support configured " 643 "HT capability [TX-STBC]"); 644 return 0; 645 } 646 647 if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 648 (hw & HT_CAP_INFO_RX_STBC_MASK)) { 649 wpa_printf(MSG_ERROR, "Driver does not support configured " 650 "HT capability [RX-STBC*]"); 651 return 0; 652 } 653 654 if ((conf & HT_CAP_INFO_DELAYED_BA) && 655 !(hw & HT_CAP_INFO_DELAYED_BA)) { 656 wpa_printf(MSG_ERROR, "Driver does not support configured " 657 "HT capability [DELAYED-BA]"); 658 return 0; 659 } 660 661 if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 662 !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 663 wpa_printf(MSG_ERROR, "Driver does not support configured " 664 "HT capability [MAX-AMSDU-7935]"); 665 return 0; 666 } 667 668 if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 669 !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 670 wpa_printf(MSG_ERROR, "Driver does not support configured " 671 "HT capability [DSSS_CCK-40]"); 672 return 0; 673 } 674 675 if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 676 !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 677 wpa_printf(MSG_ERROR, "Driver does not support configured " 678 "HT capability [LSIG-TXOP-PROT]"); 679 return 0; 680 } 681 682 return 1; 683 } 684 685 686 #ifdef CONFIG_IEEE80211AC 687 static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) 688 { 689 struct hostapd_hw_modes *mode = iface->current_mode; 690 u32 hw = mode->vht_capab; 691 u32 conf = iface->conf->vht_capab; 692 693 wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", 694 hw, conf); 695 696 if (mode->mode == HOSTAPD_MODE_IEEE80211G && 697 iface->conf->bss[0]->vendor_vht && 698 mode->vht_capab == 0 && iface->hw_features) { 699 int i; 700 701 for (i = 0; i < iface->num_hw_features; i++) { 702 if (iface->hw_features[i].mode == 703 HOSTAPD_MODE_IEEE80211A) { 704 mode = &iface->hw_features[i]; 705 hw = mode->vht_capab; 706 wpa_printf(MSG_DEBUG, 707 "update hw vht capab based on 5 GHz band: 0x%x", 708 hw); 709 break; 710 } 711 } 712 } 713 714 return ieee80211ac_cap_check(hw, conf); 715 } 716 #endif /* CONFIG_IEEE80211AC */ 717 718 719 #ifdef CONFIG_IEEE80211AX 720 static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface) 721 { 722 return 1; 723 } 724 #endif /* CONFIG_IEEE80211AX */ 725 726 727 int hostapd_check_ht_capab(struct hostapd_iface *iface) 728 { 729 int ret; 730 731 if (is_6ghz_freq(iface->freq)) 732 return 0; 733 if (!iface->conf->ieee80211n) 734 return 0; 735 736 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B && 737 iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G && 738 (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) { 739 wpa_printf(MSG_DEBUG, 740 "Disable HT capability [DSSS_CCK-40] on 5 GHz band"); 741 iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ; 742 } 743 744 if (!ieee80211n_supported_ht_capab(iface)) 745 return -1; 746 #ifdef CONFIG_IEEE80211AX 747 if (iface->conf->ieee80211ax && 748 !ieee80211ax_supported_he_capab(iface)) 749 return -1; 750 #endif /* CONFIG_IEEE80211AX */ 751 #ifdef CONFIG_IEEE80211AC 752 if (iface->conf->ieee80211ac && 753 !ieee80211ac_supported_vht_capab(iface)) 754 return -1; 755 #endif /* CONFIG_IEEE80211AC */ 756 ret = ieee80211n_check_40mhz(iface); 757 if (ret) 758 return ret; 759 if (!ieee80211n_allowed_ht40_channel_pair(iface)) 760 return -1; 761 762 return 0; 763 } 764 765 766 int hostapd_check_edmg_capab(struct hostapd_iface *iface) 767 { 768 struct hostapd_hw_modes *mode = iface->hw_features; 769 struct ieee80211_edmg_config edmg; 770 771 if (!iface->conf->enable_edmg) 772 return 0; 773 774 hostapd_encode_edmg_chan(iface->conf->enable_edmg, 775 iface->conf->edmg_channel, 776 iface->conf->channel, 777 &edmg); 778 779 if (mode->edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg)) 780 return 0; 781 782 wpa_printf(MSG_WARNING, "Requested EDMG configuration is not valid"); 783 wpa_printf(MSG_INFO, "EDMG capab: channels 0x%x, bw_config %d", 784 mode->edmg.channels, mode->edmg.bw_config); 785 wpa_printf(MSG_INFO, 786 "Requested EDMG configuration: channels 0x%x, bw_config %d", 787 edmg.channels, edmg.bw_config); 788 return -1; 789 } 790 791 792 int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface) 793 { 794 #ifdef CONFIG_IEEE80211AX 795 struct he_capabilities *he_cap; 796 u16 hw; 797 798 if (!iface->current_mode || !is_6ghz_freq(iface->freq)) 799 return 0; 800 801 he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP]; 802 hw = he_cap->he_6ghz_capa; 803 if (iface->conf->he_6ghz_max_mpdu > 804 ((hw & HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK) >> 805 HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT)) { 806 wpa_printf(MSG_ERROR, 807 "The driver does not support the configured HE 6 GHz Max MPDU length"); 808 return -1; 809 } 810 811 if (iface->conf->he_6ghz_max_ampdu_len_exp > 812 ((hw & HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK) >> 813 HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT)) { 814 wpa_printf(MSG_ERROR, 815 "The driver does not support the configured HE 6 GHz Max AMPDU Length Exponent"); 816 return -1; 817 } 818 819 if (iface->conf->he_6ghz_rx_ant_pat && 820 !(hw & HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS)) { 821 wpa_printf(MSG_ERROR, 822 "The driver does not support the configured HE 6 GHz Rx Antenna Pattern"); 823 return -1; 824 } 825 826 if (iface->conf->he_6ghz_tx_ant_pat && 827 !(hw & HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS)) { 828 wpa_printf(MSG_ERROR, 829 "The driver does not support the configured HE 6 GHz Tx Antenna Pattern"); 830 return -1; 831 } 832 #endif /* CONFIG_IEEE80211AX */ 833 return 0; 834 } 835 836 837 /* Returns: 838 * 1 = usable 839 * 0 = not usable 840 * -1 = not currently usable due to 6 GHz NO-IR 841 */ 842 static int hostapd_is_usable_chan(struct hostapd_iface *iface, 843 int frequency, int primary) 844 { 845 struct hostapd_channel_data *chan; 846 847 if (!iface->current_mode) 848 return 0; 849 850 chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL, 851 iface->hw_features, iface->num_hw_features); 852 if (!chan) 853 return 0; 854 855 if ((primary && chan_pri_allowed(chan)) || 856 (!primary && !(chan->flag & HOSTAPD_CHAN_DISABLED))) 857 return 1; 858 859 wpa_printf(MSG_INFO, 860 "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s", 861 frequency, primary ? "primary" : "secondary", 862 chan->flag, 863 chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", 864 chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); 865 866 if (is_6ghz_freq(chan->freq) && (chan->flag & HOSTAPD_CHAN_NO_IR)) 867 return -1; 868 869 return 0; 870 } 871 872 873 static int hostapd_is_usable_edmg(struct hostapd_iface *iface) 874 { 875 int i, contiguous = 0; 876 int num_of_enabled = 0; 877 int max_contiguous = 0; 878 int err; 879 struct ieee80211_edmg_config edmg; 880 struct hostapd_channel_data *pri_chan; 881 882 if (!iface->conf->enable_edmg) 883 return 1; 884 885 if (!iface->current_mode) 886 return 0; 887 pri_chan = hw_get_channel_freq(iface->current_mode->mode, 888 iface->freq, NULL, 889 iface->hw_features, 890 iface->num_hw_features); 891 if (!pri_chan) 892 return 0; 893 hostapd_encode_edmg_chan(iface->conf->enable_edmg, 894 iface->conf->edmg_channel, 895 pri_chan->chan, 896 &edmg); 897 if (!(edmg.channels & BIT(pri_chan->chan - 1))) 898 return 0; 899 900 /* 60 GHz channels 1..6 */ 901 for (i = 0; i < 6; i++) { 902 int freq = 56160 + 2160 * (i + 1); 903 904 if (edmg.channels & BIT(i)) { 905 contiguous++; 906 num_of_enabled++; 907 } else { 908 contiguous = 0; 909 continue; 910 } 911 912 /* P802.11ay defines that the total number of subfields 913 * set to one does not exceed 4. 914 */ 915 if (num_of_enabled > 4) 916 return 0; 917 918 err = hostapd_is_usable_chan(iface, freq, 1); 919 if (err <= 0) 920 return err; 921 922 if (contiguous > max_contiguous) 923 max_contiguous = contiguous; 924 } 925 926 /* Check if the EDMG configuration is valid under the limitations 927 * of P802.11ay. 928 */ 929 /* check bw_config against contiguous EDMG channels */ 930 switch (edmg.bw_config) { 931 case EDMG_BW_CONFIG_4: 932 if (!max_contiguous) 933 return 0; 934 break; 935 case EDMG_BW_CONFIG_5: 936 if (max_contiguous < 2) 937 return 0; 938 break; 939 default: 940 return 0; 941 } 942 943 return 1; 944 } 945 946 947 static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface) 948 { 949 #ifdef CONFIG_IEEE80211BE 950 struct hostapd_config *conf = iface->conf; 951 u16 bw; 952 u8 start_chan; 953 954 if (!conf->punct_bitmap) 955 return true; 956 957 if (!conf->ieee80211be) { 958 wpa_printf(MSG_ERROR, 959 "Currently RU puncturing is supported only if ieee80211be is enabled"); 960 return false; 961 } 962 963 if (iface->freq >= 2412 && iface->freq <= 2484) { 964 wpa_printf(MSG_ERROR, 965 "RU puncturing not supported in 2.4 GHz"); 966 return false; 967 } 968 969 /* 970 * In the 6 GHz band, eht_oper_chwidth is ignored. Use operating class 971 * to determine channel width. 972 */ 973 if (conf->op_class == 137) { 974 bw = 320; 975 start_chan = conf->eht_oper_centr_freq_seg0_idx - 30; 976 } else { 977 switch (conf->eht_oper_chwidth) { 978 case 0: 979 wpa_printf(MSG_ERROR, 980 "RU puncturing is supported only in 80 MHz and 160 MHz"); 981 return false; 982 case 1: 983 bw = 80; 984 start_chan = conf->eht_oper_centr_freq_seg0_idx - 6; 985 break; 986 case 2: 987 bw = 160; 988 start_chan = conf->eht_oper_centr_freq_seg0_idx - 14; 989 break; 990 default: 991 return false; 992 } 993 } 994 995 if (!is_punct_bitmap_valid(bw, (conf->channel - start_chan) / 4, 996 conf->punct_bitmap)) { 997 wpa_printf(MSG_ERROR, "Invalid puncturing bitmap"); 998 return false; 999 } 1000 #endif /* CONFIG_IEEE80211BE */ 1001 1002 return true; 1003 } 1004 1005 1006 /* Returns: 1007 * 1 = usable 1008 * 0 = not usable 1009 * -1 = not currently usable due to 6 GHz NO-IR 1010 */ 1011 static int hostapd_is_usable_chans(struct hostapd_iface *iface) 1012 { 1013 int secondary_freq; 1014 struct hostapd_channel_data *pri_chan; 1015 int err, err2; 1016 1017 if (!iface->current_mode) 1018 return 0; 1019 pri_chan = hw_get_channel_freq(iface->current_mode->mode, 1020 iface->freq, NULL, 1021 iface->hw_features, 1022 iface->num_hw_features); 1023 if (!pri_chan) { 1024 wpa_printf(MSG_ERROR, "Primary frequency not present"); 1025 return 0; 1026 } 1027 1028 err = hostapd_is_usable_chan(iface, pri_chan->freq, 1); 1029 if (err <= 0) { 1030 wpa_printf(MSG_ERROR, "Primary frequency not allowed"); 1031 return err; 1032 } 1033 err = hostapd_is_usable_edmg(iface); 1034 if (err <= 0) 1035 return err; 1036 1037 if (!hostapd_is_usable_punct_bitmap(iface)) 1038 return 0; 1039 1040 if (!iface->conf->secondary_channel) 1041 return 1; 1042 1043 err = hostapd_is_usable_chan(iface, iface->freq + 1044 iface->conf->secondary_channel * 20, 0); 1045 if (err > 0) { 1046 if (iface->conf->secondary_channel == 1 && 1047 (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) 1048 return 1; 1049 if (iface->conf->secondary_channel == -1 && 1050 (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) 1051 return 1; 1052 } 1053 if (!iface->conf->ht40_plus_minus_allowed) 1054 return err; 1055 1056 /* Both HT40+ and HT40- are set, pick a valid secondary channel */ 1057 secondary_freq = iface->freq + 20; 1058 err2 = hostapd_is_usable_chan(iface, secondary_freq, 0); 1059 if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) { 1060 iface->conf->secondary_channel = 1; 1061 return 1; 1062 } 1063 1064 secondary_freq = iface->freq - 20; 1065 err2 = hostapd_is_usable_chan(iface, secondary_freq, 0); 1066 if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) { 1067 iface->conf->secondary_channel = -1; 1068 return 1; 1069 } 1070 1071 return err; 1072 } 1073 1074 1075 static bool skip_mode(struct hostapd_iface *iface, 1076 struct hostapd_hw_modes *mode) 1077 { 1078 int chan; 1079 1080 if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan)) 1081 return true; 1082 1083 if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 && 1084 !mode->is_6ghz) 1085 return true; 1086 1087 return false; 1088 } 1089 1090 1091 int hostapd_determine_mode(struct hostapd_iface *iface) 1092 { 1093 int i; 1094 enum hostapd_hw_mode target_mode; 1095 1096 if (iface->current_mode || 1097 iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY) 1098 return 0; 1099 1100 if (iface->freq < 4000) 1101 target_mode = HOSTAPD_MODE_IEEE80211G; 1102 else if (iface->freq > 50000) 1103 target_mode = HOSTAPD_MODE_IEEE80211AD; 1104 else 1105 target_mode = HOSTAPD_MODE_IEEE80211A; 1106 1107 for (i = 0; i < iface->num_hw_features; i++) { 1108 struct hostapd_hw_modes *mode; 1109 1110 mode = &iface->hw_features[i]; 1111 if (mode->mode == target_mode) { 1112 if (skip_mode(iface, mode)) 1113 continue; 1114 1115 iface->current_mode = mode; 1116 iface->conf->hw_mode = mode->mode; 1117 break; 1118 } 1119 } 1120 1121 if (!iface->current_mode) { 1122 wpa_printf(MSG_ERROR, "ACS/CSA: Cannot decide mode"); 1123 return -1; 1124 } 1125 return 0; 1126 } 1127 1128 1129 static enum hostapd_chan_status 1130 hostapd_check_chans(struct hostapd_iface *iface) 1131 { 1132 if (iface->freq) { 1133 int err; 1134 1135 hostapd_determine_mode(iface); 1136 1137 err = hostapd_is_usable_chans(iface); 1138 if (err <= 0) { 1139 if (!err) 1140 return HOSTAPD_CHAN_INVALID; 1141 return HOSTAPD_CHAN_INVALID_NO_IR; 1142 } 1143 return HOSTAPD_CHAN_VALID; 1144 } 1145 1146 /* 1147 * The user set channel=0 or channel=acs_survey 1148 * which is used to trigger ACS. 1149 */ 1150 1151 switch (acs_init(iface)) { 1152 case HOSTAPD_CHAN_ACS: 1153 return HOSTAPD_CHAN_ACS; 1154 case HOSTAPD_CHAN_INVALID_NO_IR: 1155 return HOSTAPD_CHAN_INVALID_NO_IR; 1156 case HOSTAPD_CHAN_VALID: 1157 case HOSTAPD_CHAN_INVALID: 1158 default: 1159 return HOSTAPD_CHAN_INVALID; 1160 } 1161 } 1162 1163 1164 static void hostapd_notify_bad_chans(struct hostapd_iface *iface) 1165 { 1166 if (!iface->current_mode) { 1167 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 1168 HOSTAPD_LEVEL_WARNING, 1169 "Hardware does not support configured mode"); 1170 return; 1171 } 1172 hostapd_logger(iface->bss[0], NULL, 1173 HOSTAPD_MODULE_IEEE80211, 1174 HOSTAPD_LEVEL_WARNING, 1175 "Configured channel (%d) or frequency (%d) (secondary_channel=%d) not found from the channel list of the current mode (%d) %s", 1176 iface->conf->channel, 1177 iface->freq, iface->conf->secondary_channel, 1178 iface->current_mode->mode, 1179 hostapd_hw_mode_txt(iface->current_mode->mode)); 1180 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 1181 HOSTAPD_LEVEL_WARNING, 1182 "Hardware does not support configured channel"); 1183 } 1184 1185 1186 int hostapd_acs_completed(struct hostapd_iface *iface, int err) 1187 { 1188 int ret = -1; 1189 1190 if (err) 1191 goto out; 1192 1193 switch (hostapd_check_chans(iface)) { 1194 case HOSTAPD_CHAN_VALID: 1195 iface->is_no_ir = false; 1196 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, 1197 ACS_EVENT_COMPLETED "freq=%d channel=%d", 1198 iface->freq, iface->conf->channel); 1199 break; 1200 case HOSTAPD_CHAN_ACS: 1201 wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); 1202 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 1203 hostapd_notify_bad_chans(iface); 1204 goto out; 1205 case HOSTAPD_CHAN_INVALID_NO_IR: 1206 iface->is_no_ir = true; 1207 /* fall through */ 1208 case HOSTAPD_CHAN_INVALID: 1209 default: 1210 wpa_printf(MSG_ERROR, "ACS picked unusable channels"); 1211 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 1212 hostapd_notify_bad_chans(iface); 1213 goto out; 1214 } 1215 1216 ret = hostapd_check_ht_capab(iface); 1217 if (ret < 0) 1218 goto out; 1219 if (ret == 1) { 1220 wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); 1221 return 0; 1222 } 1223 1224 ret = 0; 1225 out: 1226 return hostapd_setup_interface_complete(iface, ret); 1227 } 1228 1229 1230 /** 1231 * hostapd_csa_update_hwmode - Update hardware mode 1232 * @iface: Pointer to interface data. 1233 * Returns: 0 on success, < 0 on failure 1234 * 1235 * Update hardware mode when the operating channel changed because of CSA. 1236 */ 1237 int hostapd_csa_update_hwmode(struct hostapd_iface *iface) 1238 { 1239 if (!iface || !iface->conf) 1240 return -1; 1241 1242 iface->current_mode = NULL; 1243 iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; 1244 1245 return hostapd_determine_mode(iface); 1246 } 1247 1248 1249 /** 1250 * hostapd_select_hw_mode - Select the hardware mode 1251 * @iface: Pointer to interface data. 1252 * Returns: 0 on success, < 0 on failure 1253 * 1254 * Sets up the hardware mode, channel, rates, and passive scanning 1255 * based on the configuration. 1256 */ 1257 int hostapd_select_hw_mode(struct hostapd_iface *iface) 1258 { 1259 int i; 1260 1261 if (iface->num_hw_features < 1) 1262 return -1; 1263 1264 if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || 1265 iface->conf->ieee80211n || iface->conf->ieee80211ac || 1266 iface->conf->ieee80211ax || iface->conf->ieee80211be) && 1267 iface->conf->channel == 14) { 1268 wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE/EHT on channel 14"); 1269 iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 1270 iface->conf->ieee80211n = 0; 1271 iface->conf->ieee80211ac = 0; 1272 iface->conf->ieee80211ax = 0; 1273 iface->conf->ieee80211be = 0; 1274 } 1275 1276 iface->current_mode = NULL; 1277 for (i = 0; i < iface->num_hw_features; i++) { 1278 struct hostapd_hw_modes *mode = &iface->hw_features[i]; 1279 1280 if (mode->mode == iface->conf->hw_mode) { 1281 if (skip_mode(iface, mode)) 1282 continue; 1283 1284 iface->current_mode = mode; 1285 break; 1286 } 1287 } 1288 1289 if (iface->current_mode == NULL) { 1290 if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 1291 (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) { 1292 wpa_printf(MSG_DEBUG, 1293 "Using offloaded hw_mode=any ACS"); 1294 } else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 1295 iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) { 1296 wpa_printf(MSG_DEBUG, 1297 "Using internal ACS for hw_mode=any"); 1298 } else { 1299 wpa_printf(MSG_ERROR, 1300 "Hardware does not support configured mode"); 1301 hostapd_logger(iface->bss[0], NULL, 1302 HOSTAPD_MODULE_IEEE80211, 1303 HOSTAPD_LEVEL_WARNING, 1304 "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)", 1305 (int) iface->conf->hw_mode); 1306 return -2; 1307 } 1308 } 1309 1310 switch (hostapd_check_chans(iface)) { 1311 case HOSTAPD_CHAN_VALID: 1312 iface->is_no_ir = false; 1313 return 0; 1314 case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ 1315 return 1; 1316 case HOSTAPD_CHAN_INVALID_NO_IR: 1317 iface->is_no_ir = true; 1318 /* fall through */ 1319 case HOSTAPD_CHAN_INVALID: 1320 default: 1321 hostapd_notify_bad_chans(iface); 1322 return -3; 1323 } 1324 } 1325 1326 1327 const char * hostapd_hw_mode_txt(int mode) 1328 { 1329 switch (mode) { 1330 case HOSTAPD_MODE_IEEE80211A: 1331 return "IEEE 802.11a"; 1332 case HOSTAPD_MODE_IEEE80211B: 1333 return "IEEE 802.11b"; 1334 case HOSTAPD_MODE_IEEE80211G: 1335 return "IEEE 802.11g"; 1336 case HOSTAPD_MODE_IEEE80211AD: 1337 return "IEEE 802.11ad"; 1338 default: 1339 return "UNKNOWN"; 1340 } 1341 } 1342 1343 1344 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 1345 { 1346 return hw_get_freq(hapd->iface->current_mode, chan); 1347 } 1348 1349 1350 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 1351 { 1352 int i, channel; 1353 struct hostapd_hw_modes *mode; 1354 1355 if (hapd->iface->current_mode) { 1356 channel = hw_get_chan(hapd->iface->current_mode->mode, freq, 1357 hapd->iface->hw_features, 1358 hapd->iface->num_hw_features); 1359 if (channel) 1360 return channel; 1361 } 1362 1363 /* Check other available modes since the channel list for the current 1364 * mode did not include the specified frequency. */ 1365 if (!hapd->iface->hw_features) 1366 return 0; 1367 for (i = 0; i < hapd->iface->num_hw_features; i++) { 1368 mode = &hapd->iface->hw_features[i]; 1369 channel = hw_get_chan(mode->mode, freq, 1370 hapd->iface->hw_features, 1371 hapd->iface->num_hw_features); 1372 if (channel) 1373 return channel; 1374 } 1375 return 0; 1376 } 1377 1378 1379 int hostapd_hw_skip_mode(struct hostapd_iface *iface, 1380 struct hostapd_hw_modes *mode) 1381 { 1382 int i; 1383 1384 if (iface->current_mode) 1385 return mode != iface->current_mode; 1386 if (mode->mode != HOSTAPD_MODE_IEEE80211B) 1387 return 0; 1388 for (i = 0; i < iface->num_hw_features; i++) { 1389 if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G) 1390 return 1; 1391 } 1392 return 0; 1393 } 1394