18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / Hardware feature query and different modes 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2002-2003, Instant802 Networks, Inc. 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2005-2006, Devicescape Software, Inc. 504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi> 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 8fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * See README for more details. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h" 17cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#include "common/wpa_ctrl.h" 18ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#include "common/hw_features_common.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h" 22391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "acs.h" 237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "ieee802_11.h" 247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "beacon.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hw_features.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_hw_features) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hw_features == NULL) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_hw_features; i++) { 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features[i].channels); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features[i].rates); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 46051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic char * dfs_info(struct hostapd_channel_data *chan) 47051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 48051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt static char info[256]; 49051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt char *state; 50051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 51051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { 52051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_UNKNOWN: 53051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "unknown"; 54051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 55051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_USABLE: 56051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "usable"; 57051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 58051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_UNAVAILABLE: 59051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "unavailable"; 60051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 61051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_AVAILABLE: 62051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "available"; 63051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 64051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 65051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return ""; 66051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 67051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_snprintf(info, sizeof(info), " (DFS state = %s)", state); 68051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt info[sizeof(info) - 1] = '\0'; 69051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 70051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return info; 71051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 72051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 73051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 74051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_get_hw_features(struct hostapd_iface *iface) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = iface->bss[0]; 782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int i, j; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 num_modes, flags; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *modes; 81d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt u8 dfs_domain; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_none(hapd)) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 85d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, 86d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt &dfs_domain); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (modes == NULL) { 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Fetching hardware channel/rate support not " 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "supported."); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->hw_flags = flags; 96d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface->dfs_domain = dfs_domain; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->hw_features = modes; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->num_hw_features = num_modes; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_modes; i++) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *feature = &modes[i]; 104051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int dfs_enabled = hapd->iconf->ieee80211h && 105051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); 106051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* set flag for channels we can use in current regulatory 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * domain */ 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 0; j < feature->num_channels; j++) { 110051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int dfs = 0; 111051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disable all channels that are marked not to allow 1146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * to initiate radiation (a.k.a. passive scan and no 1156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * IBSS). 116051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Use radar channels only if the driver supports DFS. 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 118051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if ((feature->channels[j].flag & 119051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_RADAR) && dfs_enabled) { 120051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt dfs = 1; 121d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt } else if (((feature->channels[j].flag & 122d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt HOSTAPD_CHAN_RADAR) && 123d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt !(iface->drv_flags & 124d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || 125d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt (feature->channels[j].flag & 1266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt HOSTAPD_CHAN_NO_IR)) { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].flag |= 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_DISABLED; 129051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 130051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 133051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 135051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "chan=%d freq=%d MHz max_tx_power=%d dBm%s", 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->mode, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].chan, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].freq, 139051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt feature->channels[j].max_tx_power, 140051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt dfs ? dfs_info(&feature->channels[j]) : ""); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return 0; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint hostapd_prepare_rates(struct hostapd_iface *iface, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, num_basic_rates = 0; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_a[] = { 60, 120, 240, -1 }; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_b[] = { 10, 20, -1 }; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *basic_rates; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->conf->basic_rates) 1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt basic_rates = iface->conf->basic_rates; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else switch (mode->mode) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_a; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_b; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_g; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 169a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 170a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; /* No basic rates for 11ad */ 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i = 0; 1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (basic_rates[i] >= 0) 1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i++; 1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (i) 1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt i++; /* -1 termination */ 1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(iface->basic_rates); 1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->basic_rates = os_malloc(i * sizeof(int)); 1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->basic_rates) 1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(iface->current_rates); 1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates = 0; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->current_rates = 18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!iface->current_rates) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "table."); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < mode->num_rates; i++) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_rate_data *rate; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->conf->supported_rates && 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !hostapd_rate_found(iface->conf->supported_rates, 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates[i])) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rate = &iface->current_rates[iface->num_rates]; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate->rate = mode->rates[i]; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_rate_found(basic_rates, rate->rate)) { 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate->flags |= HOSTAPD_RATE_BASIC; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_basic_rates++; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates, rate->rate, rate->flags); 2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates++; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((iface->num_rates == 0 || num_basic_rates == 0) && 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rate sets (%d,%d).", 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates, num_basic_rates); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 230ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->conf->secondary_channel) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* HT40 not used */ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 235ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt pri_chan = iface->conf->channel; 236ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return allowed_ht40_channel_pair(iface->current_mode, pri_chan, 239ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->conf->secondary_channel > 0) { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel += 4; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = -1; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel -= 4; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = 1; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res) 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 258ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 259ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int res; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pri_chan = iface->conf->channel; 262b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 264ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 266d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (res == 2) { 267d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (iface->conf->no_pri_sec_switch) { 268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "Cannot switch PRI/SEC channels due to local constraint"); 270d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 271d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt ieee80211n_switch_pri_sec(iface); 272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 273d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2746dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 275ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return !!res; 2766dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt} 2776dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 2786dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res) 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 282ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 2836dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 284ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt pri_chan = iface->conf->channel; 285ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 287ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan, 288ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211n_check_scan(struct hostapd_iface *iface) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int oper40; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 29904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->scan_cb = NULL; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) { 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_setup_interface_complete(iface, 1); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(scan_res); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3157832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->secondary_ch = iface->conf->secondary_channel; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!oper40) { 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "channel pri=%d sec=%d based on overlapping BSSes", 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel + 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel * 4); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = 0; 3237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { 3247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt /* 3257832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * TODO: Could consider scheduling another scan to check 3267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * if channel width can be changed if no coex reports 3277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * are received from associating stations. 3287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt */ 3297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = ieee80211n_allowed_ht40_channel_pair(iface); 3337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (!res) { 3347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->secondary_channel = 0; 335ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 0; 336ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx = 0; 337d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface->conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; 338b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt res = 1; 3397832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_INFO, "Fallback to 20 MHz"); 3407832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 3417832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_setup_interface_complete(iface, !res); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, 34704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params *params) 34804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 34904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Scan only the affected frequency range */ 35004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int pri_freq, sec_freq; 35104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int affected_start, affected_end; 35204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int i, pos; 35304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_hw_modes *mode; 35404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 35504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->current_mode == NULL) 35604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 35704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 35804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 35904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->conf->secondary_channel > 0) 36004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sec_freq = pri_freq + 20; 36104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 36204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sec_freq = pri_freq - 20; 3634171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt /* 3644171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt * Note: Need to find the PRI channel also in cases where the affected 3654171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt * channel is the SEC channel of a 40 MHz BSS, so need to include the 3664171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt * scanning coverage here to be 40 MHz from the center frequency. 3674171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt */ 3684171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt affected_start = (pri_freq + sec_freq) / 2 - 40; 3694171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt affected_end = (pri_freq + sec_freq) / 2 + 40; 37004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 37104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt affected_start, affected_end); 37204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 37304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mode = iface->current_mode; 37461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 37504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (params->freqs == NULL) 37604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 37704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = 0; 37804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 37904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 38004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[i]; 38104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 38204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 38304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (chan->freq < affected_start || 38404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt chan->freq > affected_end) 38504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 38604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params->freqs[pos++] = chan->freq; 38704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 38804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 38904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 39004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 391cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, 392cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct wpa_driver_scan_params *params) 393cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{ 394cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* Scan only the affected frequency range */ 395cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int pri_freq; 396cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int affected_start, affected_end; 397cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int i, pos; 398cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_hw_modes *mode; 399cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 400cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->current_mode == NULL) 401cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return; 402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 403cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 404cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->secondary_channel > 0) { 405cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start = pri_freq - 10; 406cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_end = pri_freq + 30; 407cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else { 408cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start = pri_freq - 30; 409cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_end = pri_freq + 10; 410cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 411cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 412cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start, affected_end); 413cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 414cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 415cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 416cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (params->freqs == NULL) 417cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return; 418cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt pos = 0; 419cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 420cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 421cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[i]; 422cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 423cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt continue; 424cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (chan->freq < affected_start || 425cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt chan->freq > affected_end) 426cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt continue; 427cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt params->freqs[pos++] = chan->freq; 428cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 429cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt} 430cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 431cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 4327832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtstatic void ap_ht40_scan_retry(void *eloop_data, void *user_data) 4337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt{ 4347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#define HT2040_COEX_SCAN_RETRY 15 4357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct hostapd_iface *iface = eloop_data; 4367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct wpa_driver_scan_params params; 4377832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt int ret; 4387832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4397832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 4407832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 4417832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ieee80211n_scan_channels_2g4(iface, ¶ms); 4427832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt else 4437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ieee80211n_scan_channels_5g(iface, ¶ms); 4447832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4457832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret = hostapd_driver_scan(iface->bss[0], ¶ms); 4467832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries++; 4477832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_free(params.freqs); 4487832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4497832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == -EBUSY && 4507832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { 4517832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 4527832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", 4537832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret), iface->num_ht40_scan_tries); 4547832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 4557832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return; 4567832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 4577832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4587832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == 0) { 4597832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->scan_cb = ieee80211n_check_scan; 4607832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return; 4617832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 4627832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4637832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_DEBUG, 4647832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan in device, bringing up in HT20 mode"); 4657832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->secondary_channel = 0; 4667832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 4677832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt hostapd_setup_interface_complete(iface, 0); 4687832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt} 4697832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4707832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4717832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtvoid hostapd_stop_setup_timers(struct hostapd_iface *iface) 4727832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt{ 4737832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 4747832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt} 4757832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4767832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz(struct hostapd_iface *iface) 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params params; 4807832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt int ret; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 482d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* Check that HT40 is used and PRI / SEC switch is allowed */ 483d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch) 484d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 486cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "40 MHz channel"); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 49004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 49104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee80211n_scan_channels_2g4(iface, ¶ms); 492cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt else 493cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ieee80211n_scan_channels_5g(iface, ¶ms); 4947832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4957832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret = hostapd_driver_scan(iface->bss[0], ¶ms); 4967832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_free(params.freqs); 4977832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4987832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == -EBUSY) { 4997832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 5007832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", 5017832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret)); 5027832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries = 1; 5037832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 5047832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 5057832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return 1; 5067832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 5077832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 5087832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret < 0) { 5097832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 5107832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s)", 5117832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret)); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->scan_cb = ieee80211n_check_scan; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 hw = iface->current_mode->ht_capab; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 conf = iface->conf->ht_capab; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [LDPC]"); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 532dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt /* 533dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt * Driver ACS chosen channel may not be HT40 due to internal driver 534dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt * restrictions. 535dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt */ 536dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [HT40*]"); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (conf & HT_CAP_INFO_SMPS_MASK) { 5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_STATIC: 5456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { 5466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, 5476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "Driver does not support configured HT capability [SMPS-STATIC]"); 5486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 5496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DYNAMIC: 5526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { 5536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, 5546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "Driver does not support configured HT capability [SMPS-DYNAMIC]"); 5556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 5566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DISABLED: 5596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 5606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_GREEN_FIELD) && 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_GREEN_FIELD)) { 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [GF]"); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [SHORT-GI-20]"); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [SHORT-GI-40]"); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [TX-STBC]"); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hw & HT_CAP_INFO_RX_STBC_MASK)) { 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [RX-STBC*]"); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_DELAYED_BA) && 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_DELAYED_BA)) { 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [DELAYED-BA]"); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [MAX-AMSDU-7935]"); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [DSSS_CCK-40]"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [LSIG-TXOP-PROT]"); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 62968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#ifdef CONFIG_IEEE80211AC 63068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) 63168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 6322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt struct hostapd_hw_modes *mode = iface->current_mode; 6332f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt u32 hw = mode->vht_capab; 63468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u32 conf = iface->conf->vht_capab; 63568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 63668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", 63768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt hw, conf); 63868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (mode->mode == HOSTAPD_MODE_IEEE80211G && 6402f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt iface->conf->bss[0]->vendor_vht && 6412f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt mode->vht_capab == 0 && iface->hw_features) { 6422f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int i; 6432f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 6442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt for (i = 0; i < iface->num_hw_features; i++) { 6452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (iface->hw_features[i].mode == 6462f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt HOSTAPD_MODE_IEEE80211A) { 6472f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt mode = &iface->hw_features[i]; 6482f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt hw = mode->vht_capab; 6492f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_DEBUG, 6502f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt "update hw vht capab based on 5 GHz band: 0x%x", 6512f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt hw); 6522f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt break; 6532f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6542f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6552f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6562f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 657ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt return ieee80211ac_cap_check(hw, conf); 65868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 65968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif /* CONFIG_IEEE80211AC */ 66068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_check_ht_capab(struct hostapd_iface *iface) 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->conf->ieee80211n) 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 670d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 671d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B && 672d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G && 673d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) { 674d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 675d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "Disable HT capability [DSSS_CCK-40] on 5 GHz band"); 676d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ; 677d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 678d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ieee80211n_supported_ht_capab(iface)) 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 68168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#ifdef CONFIG_IEEE80211AC 68268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (!ieee80211ac_supported_vht_capab(iface)) 68368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 68468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif /* CONFIG_IEEE80211AC */ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ieee80211n_check_40mhz(iface); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ieee80211n_allowed_ht40_channel_pair(iface)) 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 696b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_is_usable_chan(struct hostapd_iface *iface, 697b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int channel, int primary) 698b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 699b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int i; 700b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct hostapd_channel_data *chan; 701b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7027a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt if (!iface->current_mode) 7037a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt return 0; 7047a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt 705b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 706b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt chan = &iface->current_mode->channels[i]; 707b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (chan->chan != channel) 708b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt continue; 709b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 710b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) 711b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 1; 712b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 713b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_printf(MSG_DEBUG, 7146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s", 715b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt primary ? "" : "Configured HT40 secondary ", 716b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt i, chan->chan, chan->flag, 7176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", 718b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); 719b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 720b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 721293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_printf(MSG_INFO, "Channel %d (%s) not allowed for AP mode", 722293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt channel, primary ? "primary" : "secondary"); 723b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 724b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 725b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 726b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 727b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_is_usable_chans(struct hostapd_iface *iface) 728b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 729d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int secondary_chan; 730d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 731b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) 732b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 733b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 734b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!iface->conf->secondary_channel) 735b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 1; 736b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 737d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (!iface->conf->ht40_plus_minus_allowed) 738d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return hostapd_is_usable_chan( 739d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface, iface->conf->channel + 740d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface->conf->secondary_channel * 4, 0); 741d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 742d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* Both HT40+ and HT40- are set, pick a valid secondary channel */ 743d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt secondary_chan = iface->conf->channel + 4; 744d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hostapd_is_usable_chan(iface, secondary_chan, 0)) { 745d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface->conf->secondary_channel = 1; 746d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return 1; 747d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 748d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 749d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt secondary_chan = iface->conf->channel - 4; 750d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (hostapd_is_usable_chan(iface, secondary_chan, 0)) { 751d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt iface->conf->secondary_channel = -1; 752d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return 1; 753d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 754d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 755d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return 0; 756b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 757b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 758b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 759b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic enum hostapd_chan_status 760b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidthostapd_check_chans(struct hostapd_iface *iface) 761b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 762b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (iface->conf->channel) { 763b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (hostapd_is_usable_chans(iface)) 764b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return HOSTAPD_CHAN_VALID; 765b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt else 766b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 767b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 768b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 769b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt /* 770391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The user set channel=0 or channel=acs_survey 771391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * which is used to trigger ACS. 772b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt */ 773391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 774391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (acs_init(iface)) { 775391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: 776391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_ACS; 777391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_VALID: 778391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 779391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 780391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 781391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 782b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 783b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 784b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 785b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic void hostapd_notify_bad_chans(struct hostapd_iface *iface) 786b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 7877a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt if (!iface->current_mode) { 7887a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 7897a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 7907a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt "Hardware does not support configured mode"); 7917a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt return; 7927a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt } 793b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, 794b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_MODULE_IEEE80211, 795b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 796b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "Configured channel (%d) not found from the " 797b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "channel list of current mode (%d) %s", 798b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt iface->conf->channel, 799b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt iface->current_mode->mode, 800b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_hw_mode_txt(iface->current_mode->mode)); 801b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 802b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 803b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "Hardware does not support configured channel"); 804b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 805b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 806b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 8074ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtint hostapd_acs_completed(struct hostapd_iface *iface, int err) 808391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 8094ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt int ret = -1; 8104ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 8114ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (err) 8124ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 813391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 814391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (hostapd_check_chans(iface)) { 815391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_VALID: 816cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, 817cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ACS_EVENT_COMPLETED "freq=%d channel=%d", 818cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_hw_get_freq(iface->bss[0], 819cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel), 820cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel); 821391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 822391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: 823391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); 824cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 825391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt hostapd_notify_bad_chans(iface); 8264ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 827391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 828391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 829391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS picked unusable channels"); 830cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 831391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt hostapd_notify_bad_chans(iface); 8324ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 833391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 834391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 835391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ret = hostapd_check_ht_capab(iface); 836391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (ret < 0) 8374ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 838391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (ret == 1) { 839391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); 840391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 841391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 842391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8434ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt ret = 0; 8444ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtout: 8454ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return hostapd_setup_interface_complete(iface, ret); 846391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 847391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 848391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_select_hw_mode - Select the hardware mode 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iface: Pointer to interface data. 85287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * Returns: 0 on success, < 0 on failure 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Sets up the hardware mode, channel, rates, and passive scanning 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * based on the configuration. 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_select_hw_mode(struct hostapd_iface *iface) 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 859b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int i; 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->num_hw_features < 1) 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 864f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || 865f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211n || iface->conf->ieee80211ac) && 866f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->channel == 14) { 867f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14"); 868f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 869f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211n = 0; 870f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211ac = 0; 871f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 872f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->current_mode = NULL; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < iface->num_hw_features; i++) { 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode = &iface->hw_features[i]; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->mode == iface->conf->hw_mode) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->current_mode = mode; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->current_mode == NULL) { 883b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) || 884b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) 885b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt { 886b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt wpa_printf(MSG_ERROR, 887b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt "Hardware does not support configured mode"); 888b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt hostapd_logger(iface->bss[0], NULL, 889b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt HOSTAPD_MODULE_IEEE80211, 890b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt HOSTAPD_LEVEL_WARNING, 891b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)", 892b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt (int) iface->conf->hw_mode); 893b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt return -2; 894b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt } 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 897b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt switch (hostapd_check_chans(iface)) { 898b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt case HOSTAPD_CHAN_VALID: 899b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 900391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ 901391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 902b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 903b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt default: 904b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_notify_bad_chans(iface); 90587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return -3; 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * hostapd_hw_mode_txt(int mode) 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (mode) { 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11a"; 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11b"; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11g"; 919a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 920a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return "IEEE 802.11ad"; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 929ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return hw_get_freq(hapd->iface->current_mode, chan); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 935d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int i, channel; 936d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt struct hostapd_hw_modes *mode; 937d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 938d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt channel = hw_get_chan(hapd->iface->current_mode, freq); 939d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (channel) 940d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return channel; 941d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /* Check other available modes since the channel list for the current 942d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * mode did not include the specified frequency. */ 943d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt for (i = 0; i < hapd->iface->num_hw_features; i++) { 944d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mode = &hapd->iface->hw_features[i]; 945d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt channel = hw_get_chan(mode, freq); 946d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (channel) 947d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return channel; 948d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 949d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return 0; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 951