1214501Srpaulo/* 2214501Srpaulo * hostapd - Driver operations 3214501Srpaulo * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#include "utils/common.h" 12214501Srpaulo#include "common/ieee802_11_defs.h" 13281806Srpaulo#include "common/hw_features_common.h" 14252726Srpaulo#include "wps/wps.h" 15252726Srpaulo#include "p2p/p2p.h" 16214501Srpaulo#include "hostapd.h" 17214501Srpaulo#include "ieee802_11.h" 18214501Srpaulo#include "sta_info.h" 19214501Srpaulo#include "ap_config.h" 20252726Srpaulo#include "p2p_hostapd.h" 21252726Srpaulo#include "hs20.h" 22346981Scy#include "wpa_auth.h" 23214501Srpaulo#include "ap_drv_ops.h" 24214501Srpaulo 25214501Srpaulo 26252726Srpaulou32 hostapd_sta_flags_to_drv(u32 flags) 27214501Srpaulo{ 28214501Srpaulo int res = 0; 29214501Srpaulo if (flags & WLAN_STA_AUTHORIZED) 30214501Srpaulo res |= WPA_STA_AUTHORIZED; 31214501Srpaulo if (flags & WLAN_STA_WMM) 32214501Srpaulo res |= WPA_STA_WMM; 33214501Srpaulo if (flags & WLAN_STA_SHORT_PREAMBLE) 34214501Srpaulo res |= WPA_STA_SHORT_PREAMBLE; 35214501Srpaulo if (flags & WLAN_STA_MFP) 36214501Srpaulo res |= WPA_STA_MFP; 37337817Scy if (flags & WLAN_STA_AUTH) 38337817Scy res |= WPA_STA_AUTHENTICATED; 39337817Scy if (flags & WLAN_STA_ASSOC) 40337817Scy res |= WPA_STA_ASSOCIATED; 41214501Srpaulo return res; 42214501Srpaulo} 43214501Srpaulo 44214501Srpaulo 45337817Scystatic int add_buf(struct wpabuf **dst, const struct wpabuf *src) 46337817Scy{ 47337817Scy if (!src) 48337817Scy return 0; 49337817Scy if (wpabuf_resize(dst, wpabuf_len(src)) != 0) 50337817Scy return -1; 51337817Scy wpabuf_put_buf(*dst, src); 52337817Scy return 0; 53337817Scy} 54337817Scy 55337817Scy 56337817Scystatic int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len) 57337817Scy{ 58337817Scy if (!data || !len) 59337817Scy return 0; 60337817Scy if (wpabuf_resize(dst, len) != 0) 61337817Scy return -1; 62337817Scy wpabuf_put_data(*dst, data, len); 63337817Scy return 0; 64337817Scy} 65337817Scy 66337817Scy 67252726Srpauloint hostapd_build_ap_extra_ies(struct hostapd_data *hapd, 68252726Srpaulo struct wpabuf **beacon_ret, 69252726Srpaulo struct wpabuf **proberesp_ret, 70252726Srpaulo struct wpabuf **assocresp_ret) 71214501Srpaulo{ 72252726Srpaulo struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; 73252726Srpaulo u8 buf[200], *pos; 74214501Srpaulo 75252726Srpaulo *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; 76214501Srpaulo 77252726Srpaulo pos = buf; 78252726Srpaulo pos = hostapd_eid_time_adv(hapd, pos); 79337817Scy if (add_buf_data(&beacon, buf, pos - buf) < 0) 80337817Scy goto fail; 81252726Srpaulo pos = hostapd_eid_time_zone(hapd, pos); 82337817Scy if (add_buf_data(&proberesp, buf, pos - buf) < 0) 83337817Scy goto fail; 84214501Srpaulo 85252726Srpaulo pos = buf; 86252726Srpaulo pos = hostapd_eid_ext_capab(hapd, pos); 87337817Scy if (add_buf_data(&assocresp, buf, pos - buf) < 0) 88337817Scy goto fail; 89252726Srpaulo pos = hostapd_eid_interworking(hapd, pos); 90252726Srpaulo pos = hostapd_eid_adv_proto(hapd, pos); 91252726Srpaulo pos = hostapd_eid_roaming_consortium(hapd, pos); 92337817Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 93337817Scy add_buf_data(&proberesp, buf, pos - buf) < 0) 94337817Scy goto fail; 95214501Srpaulo 96289549Srpaulo#ifdef CONFIG_FST 97337817Scy if (add_buf(&beacon, hapd->iface->fst_ies) < 0 || 98337817Scy add_buf(&proberesp, hapd->iface->fst_ies) < 0 || 99337817Scy add_buf(&assocresp, hapd->iface->fst_ies) < 0) 100337817Scy goto fail; 101289549Srpaulo#endif /* CONFIG_FST */ 102289549Srpaulo 103346981Scy#ifdef CONFIG_FILS 104346981Scy pos = hostapd_eid_fils_indic(hapd, buf, 0); 105346981Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 106346981Scy add_buf_data(&proberesp, buf, pos - buf) < 0) 107346981Scy goto fail; 108346981Scy#endif /* CONFIG_FILS */ 109346981Scy 110337817Scy if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 || 111337817Scy add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0) 112337817Scy goto fail; 113252726Srpaulo 114252726Srpaulo#ifdef CONFIG_P2P 115337817Scy if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 || 116337817Scy add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0) 117337817Scy goto fail; 118252726Srpaulo#endif /* CONFIG_P2P */ 119252726Srpaulo 120252726Srpaulo#ifdef CONFIG_P2P_MANAGER 121252726Srpaulo if (hapd->conf->p2p & P2P_MANAGE) { 122252726Srpaulo if (wpabuf_resize(&beacon, 100) == 0) { 123252726Srpaulo u8 *start, *p; 124252726Srpaulo start = wpabuf_put(beacon, 0); 125252726Srpaulo p = hostapd_eid_p2p_manage(hapd, start); 126252726Srpaulo wpabuf_put(beacon, p - start); 127252726Srpaulo } 128252726Srpaulo 129252726Srpaulo if (wpabuf_resize(&proberesp, 100) == 0) { 130252726Srpaulo u8 *start, *p; 131252726Srpaulo start = wpabuf_put(proberesp, 0); 132252726Srpaulo p = hostapd_eid_p2p_manage(hapd, start); 133252726Srpaulo wpabuf_put(proberesp, p - start); 134252726Srpaulo } 135252726Srpaulo } 136252726Srpaulo#endif /* CONFIG_P2P_MANAGER */ 137252726Srpaulo 138281806Srpaulo#ifdef CONFIG_WPS 139252726Srpaulo if (hapd->conf->wps_state) { 140252726Srpaulo struct wpabuf *a = wps_build_assoc_resp_ie(); 141337817Scy add_buf(&assocresp, a); 142252726Srpaulo wpabuf_free(a); 143252726Srpaulo } 144281806Srpaulo#endif /* CONFIG_WPS */ 145252726Srpaulo 146252726Srpaulo#ifdef CONFIG_P2P_MANAGER 147252726Srpaulo if (hapd->conf->p2p & P2P_MANAGE) { 148252726Srpaulo if (wpabuf_resize(&assocresp, 100) == 0) { 149252726Srpaulo u8 *start, *p; 150252726Srpaulo start = wpabuf_put(assocresp, 0); 151252726Srpaulo p = hostapd_eid_p2p_manage(hapd, start); 152252726Srpaulo wpabuf_put(assocresp, p - start); 153252726Srpaulo } 154252726Srpaulo } 155252726Srpaulo#endif /* CONFIG_P2P_MANAGER */ 156252726Srpaulo 157252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY 158252726Srpaulo if (hapd->p2p_group) { 159252726Srpaulo struct wpabuf *a; 160252726Srpaulo a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); 161337817Scy add_buf(&assocresp, a); 162252726Srpaulo wpabuf_free(a); 163252726Srpaulo } 164252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */ 165252726Srpaulo 166252726Srpaulo#ifdef CONFIG_HS20 167337817Scy pos = hostapd_eid_hs20_indication(hapd, buf); 168337817Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 169337817Scy add_buf_data(&proberesp, buf, pos - buf) < 0) 170337817Scy goto fail; 171252726Srpaulo 172281806Srpaulo pos = hostapd_eid_osen(hapd, buf); 173337817Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 174337817Scy add_buf_data(&proberesp, buf, pos - buf) < 0) 175337817Scy goto fail; 176337817Scy#endif /* CONFIG_HS20 */ 177281806Srpaulo 178337817Scy#ifdef CONFIG_MBO 179346981Scy if (hapd->conf->mbo_enabled || 180346981Scy OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { 181337817Scy pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); 182337817Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 183337817Scy add_buf_data(&proberesp, buf, pos - buf) < 0 || 184337817Scy add_buf_data(&assocresp, buf, pos - buf) < 0) 185281806Srpaulo goto fail; 186281806Srpaulo } 187337817Scy#endif /* CONFIG_MBO */ 188252726Srpaulo 189346981Scy#ifdef CONFIG_OWE 190346981Scy pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf)); 191346981Scy if (add_buf_data(&beacon, buf, pos - buf) < 0 || 192346981Scy add_buf_data(&proberesp, buf, pos - buf) < 0) 193346981Scy goto fail; 194346981Scy#endif /* CONFIG_OWE */ 195346981Scy 196337817Scy add_buf(&beacon, hapd->conf->vendor_elements); 197337817Scy add_buf(&proberesp, hapd->conf->vendor_elements); 198337817Scy add_buf(&assocresp, hapd->conf->assocresp_elements); 199281806Srpaulo 200252726Srpaulo *beacon_ret = beacon; 201252726Srpaulo *proberesp_ret = proberesp; 202252726Srpaulo *assocresp_ret = assocresp; 203252726Srpaulo 204252726Srpaulo return 0; 205252726Srpaulo 206252726Srpaulofail: 207252726Srpaulo wpabuf_free(beacon); 208252726Srpaulo wpabuf_free(proberesp); 209252726Srpaulo wpabuf_free(assocresp); 210252726Srpaulo return -1; 211214501Srpaulo} 212214501Srpaulo 213214501Srpaulo 214252726Srpaulovoid hostapd_free_ap_extra_ies(struct hostapd_data *hapd, 215252726Srpaulo struct wpabuf *beacon, 216252726Srpaulo struct wpabuf *proberesp, 217252726Srpaulo struct wpabuf *assocresp) 218214501Srpaulo{ 219252726Srpaulo wpabuf_free(beacon); 220252726Srpaulo wpabuf_free(proberesp); 221252726Srpaulo wpabuf_free(assocresp); 222214501Srpaulo} 223214501Srpaulo 224214501Srpaulo 225289549Srpauloint hostapd_reset_ap_wps_ie(struct hostapd_data *hapd) 226289549Srpaulo{ 227289549Srpaulo if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) 228289549Srpaulo return 0; 229289549Srpaulo 230289549Srpaulo return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL); 231289549Srpaulo} 232289549Srpaulo 233289549Srpaulo 234252726Srpauloint hostapd_set_ap_wps_ie(struct hostapd_data *hapd) 235214501Srpaulo{ 236252726Srpaulo struct wpabuf *beacon, *proberesp, *assocresp; 237252726Srpaulo int ret; 238252726Srpaulo 239252726Srpaulo if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) 240214501Srpaulo return 0; 241252726Srpaulo 242252726Srpaulo if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < 243252726Srpaulo 0) 244252726Srpaulo return -1; 245252726Srpaulo 246252726Srpaulo ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, 247252726Srpaulo assocresp); 248252726Srpaulo 249252726Srpaulo hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); 250252726Srpaulo 251252726Srpaulo return ret; 252214501Srpaulo} 253214501Srpaulo 254214501Srpaulo 255252726Srpauloint hostapd_set_authorized(struct hostapd_data *hapd, 256252726Srpaulo struct sta_info *sta, int authorized) 257214501Srpaulo{ 258214501Srpaulo if (authorized) { 259214501Srpaulo return hostapd_sta_set_flags(hapd, sta->addr, 260214501Srpaulo hostapd_sta_flags_to_drv( 261214501Srpaulo sta->flags), 262214501Srpaulo WPA_STA_AUTHORIZED, ~0); 263214501Srpaulo } 264214501Srpaulo 265214501Srpaulo return hostapd_sta_set_flags(hapd, sta->addr, 266214501Srpaulo hostapd_sta_flags_to_drv(sta->flags), 267214501Srpaulo 0, ~WPA_STA_AUTHORIZED); 268214501Srpaulo} 269214501Srpaulo 270214501Srpaulo 271252726Srpauloint hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) 272214501Srpaulo{ 273214501Srpaulo int set_flags, total_flags, flags_and, flags_or; 274214501Srpaulo total_flags = hostapd_sta_flags_to_drv(sta->flags); 275214501Srpaulo set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP; 276214501Srpaulo if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || 277214501Srpaulo sta->auth_alg == WLAN_AUTH_FT) && 278214501Srpaulo sta->flags & WLAN_STA_AUTHORIZED) 279214501Srpaulo set_flags |= WPA_STA_AUTHORIZED; 280214501Srpaulo flags_or = total_flags & set_flags; 281214501Srpaulo flags_and = total_flags | ~set_flags; 282214501Srpaulo return hostapd_sta_set_flags(hapd, sta->addr, total_flags, 283214501Srpaulo flags_or, flags_and); 284214501Srpaulo} 285214501Srpaulo 286214501Srpaulo 287252726Srpauloint hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, 288252726Srpaulo int enabled) 289214501Srpaulo{ 290214501Srpaulo struct wpa_bss_params params; 291214501Srpaulo os_memset(¶ms, 0, sizeof(params)); 292214501Srpaulo params.ifname = ifname; 293214501Srpaulo params.enabled = enabled; 294214501Srpaulo if (enabled) { 295214501Srpaulo params.wpa = hapd->conf->wpa; 296214501Srpaulo params.ieee802_1x = hapd->conf->ieee802_1x; 297214501Srpaulo params.wpa_group = hapd->conf->wpa_group; 298289549Srpaulo if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == 299289549Srpaulo (WPA_PROTO_WPA | WPA_PROTO_RSN)) 300289549Srpaulo params.wpa_pairwise = hapd->conf->wpa_pairwise | 301289549Srpaulo hapd->conf->rsn_pairwise; 302289549Srpaulo else if (hapd->conf->wpa & WPA_PROTO_RSN) 303289549Srpaulo params.wpa_pairwise = hapd->conf->rsn_pairwise; 304289549Srpaulo else if (hapd->conf->wpa & WPA_PROTO_WPA) 305289549Srpaulo params.wpa_pairwise = hapd->conf->wpa_pairwise; 306214501Srpaulo params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; 307214501Srpaulo params.rsn_preauth = hapd->conf->rsn_preauth; 308252726Srpaulo#ifdef CONFIG_IEEE80211W 309252726Srpaulo params.ieee80211w = hapd->conf->ieee80211w; 310252726Srpaulo#endif /* CONFIG_IEEE80211W */ 311214501Srpaulo } 312214501Srpaulo return hostapd_set_ieee8021x(hapd, ¶ms); 313214501Srpaulo} 314214501Srpaulo 315214501Srpaulo 316252726Srpauloint hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) 317214501Srpaulo{ 318214501Srpaulo char force_ifname[IFNAMSIZ]; 319214501Srpaulo u8 if_addr[ETH_ALEN]; 320252726Srpaulo return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, 321281806Srpaulo NULL, NULL, force_ifname, if_addr, NULL, 0); 322214501Srpaulo} 323214501Srpaulo 324252726Srpaulo 325252726Srpauloint hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) 326214501Srpaulo{ 327214501Srpaulo return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); 328214501Srpaulo} 329214501Srpaulo 330214501Srpaulo 331281806Srpauloint hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, 332281806Srpaulo const u8 *addr, int aid, int val) 333214501Srpaulo{ 334252726Srpaulo const char *bridge = NULL; 335252726Srpaulo 336214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) 337281806Srpaulo return -1; 338252726Srpaulo if (hapd->conf->wds_bridge[0]) 339252726Srpaulo bridge = hapd->conf->wds_bridge; 340252726Srpaulo else if (hapd->conf->bridge[0]) 341252726Srpaulo bridge = hapd->conf->bridge; 342252726Srpaulo return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, 343281806Srpaulo bridge, ifname_wds); 344214501Srpaulo} 345214501Srpaulo 346214501Srpaulo 347252726Srpauloint hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, 348252726Srpaulo u16 auth_alg) 349214501Srpaulo{ 350252726Srpaulo if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) 351214501Srpaulo return 0; 352252726Srpaulo return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); 353214501Srpaulo} 354214501Srpaulo 355214501Srpaulo 356252726Srpauloint hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, 357252726Srpaulo u16 seq, u16 status, const u8 *ie, size_t len) 358214501Srpaulo{ 359346981Scy struct wpa_driver_sta_auth_params params; 360346981Scy#ifdef CONFIG_FILS 361346981Scy struct sta_info *sta; 362346981Scy#endif /* CONFIG_FILS */ 363346981Scy 364252726Srpaulo if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) 365214501Srpaulo return 0; 366346981Scy 367346981Scy os_memset(¶ms, 0, sizeof(params)); 368346981Scy 369346981Scy#ifdef CONFIG_FILS 370346981Scy sta = ap_get_sta(hapd, addr); 371346981Scy if (!sta) { 372346981Scy wpa_printf(MSG_DEBUG, "Station " MACSTR 373346981Scy " not found for sta_auth processing", 374346981Scy MAC2STR(addr)); 375346981Scy return 0; 376346981Scy } 377346981Scy 378346981Scy if (sta->auth_alg == WLAN_AUTH_FILS_SK || 379346981Scy sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || 380346981Scy sta->auth_alg == WLAN_AUTH_FILS_PK) { 381346981Scy params.fils_auth = 1; 382346981Scy wpa_auth_get_fils_aead_params(sta->wpa_sm, params.fils_anonce, 383346981Scy params.fils_snonce, 384346981Scy params.fils_kek, 385346981Scy ¶ms.fils_kek_len); 386346981Scy } 387346981Scy#endif /* CONFIG_FILS */ 388346981Scy 389346981Scy params.own_addr = hapd->own_addr; 390346981Scy params.addr = addr; 391346981Scy params.seq = seq; 392346981Scy params.status = status; 393346981Scy params.ie = ie; 394346981Scy params.len = len; 395346981Scy 396346981Scy return hapd->driver->sta_auth(hapd->drv_priv, ¶ms); 397214501Srpaulo} 398214501Srpaulo 399214501Srpaulo 400252726Srpauloint hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, 401252726Srpaulo int reassoc, u16 status, const u8 *ie, size_t len) 402214501Srpaulo{ 403252726Srpaulo if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL) 404214501Srpaulo return 0; 405252726Srpaulo return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr, 406252726Srpaulo reassoc, status, ie, len); 407214501Srpaulo} 408214501Srpaulo 409214501Srpaulo 410252726Srpauloint hostapd_sta_add(struct hostapd_data *hapd, 411252726Srpaulo const u8 *addr, u16 aid, u16 capability, 412252726Srpaulo const u8 *supp_rates, size_t supp_rates_len, 413252726Srpaulo u16 listen_interval, 414252726Srpaulo const struct ieee80211_ht_capabilities *ht_capab, 415281806Srpaulo const struct ieee80211_vht_capabilities *vht_capab, 416351611Scy const struct ieee80211_he_capabilities *he_capab, 417351611Scy size_t he_capab_len, 418337817Scy u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, 419337817Scy int set) 420214501Srpaulo{ 421214501Srpaulo struct hostapd_sta_add_params params; 422214501Srpaulo 423214501Srpaulo if (hapd->driver == NULL) 424214501Srpaulo return 0; 425214501Srpaulo if (hapd->driver->sta_add == NULL) 426214501Srpaulo return 0; 427214501Srpaulo 428214501Srpaulo os_memset(¶ms, 0, sizeof(params)); 429214501Srpaulo params.addr = addr; 430214501Srpaulo params.aid = aid; 431214501Srpaulo params.capability = capability; 432214501Srpaulo params.supp_rates = supp_rates; 433214501Srpaulo params.supp_rates_len = supp_rates_len; 434214501Srpaulo params.listen_interval = listen_interval; 435214501Srpaulo params.ht_capabilities = ht_capab; 436281806Srpaulo params.vht_capabilities = vht_capab; 437351611Scy params.he_capab = he_capab; 438351611Scy params.he_capab_len = he_capab_len; 439281806Srpaulo params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); 440281806Srpaulo params.vht_opmode = vht_opmode; 441252726Srpaulo params.flags = hostapd_sta_flags_to_drv(flags); 442252726Srpaulo params.qosinfo = qosinfo; 443337817Scy params.support_p2p_ps = supp_p2p_ps; 444337817Scy params.set = set; 445214501Srpaulo return hapd->driver->sta_add(hapd->drv_priv, ¶ms); 446214501Srpaulo} 447214501Srpaulo 448214501Srpaulo 449252726Srpauloint hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, 450252726Srpaulo u8 *tspec_ie, size_t tspec_ielen) 451214501Srpaulo{ 452252726Srpaulo if (hapd->driver == NULL || hapd->driver->add_tspec == NULL) 453214501Srpaulo return 0; 454252726Srpaulo return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie, 455252726Srpaulo tspec_ielen); 456214501Srpaulo} 457214501Srpaulo 458214501Srpaulo 459214501Srpauloint hostapd_set_privacy(struct hostapd_data *hapd, int enabled) 460214501Srpaulo{ 461214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) 462214501Srpaulo return 0; 463214501Srpaulo return hapd->driver->set_privacy(hapd->drv_priv, enabled); 464214501Srpaulo} 465214501Srpaulo 466214501Srpaulo 467214501Srpauloint hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, 468214501Srpaulo size_t elem_len) 469214501Srpaulo{ 470214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) 471214501Srpaulo return 0; 472214501Srpaulo return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); 473214501Srpaulo} 474214501Srpaulo 475214501Srpaulo 476214501Srpauloint hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) 477214501Srpaulo{ 478214501Srpaulo if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) 479214501Srpaulo return 0; 480214501Srpaulo return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); 481214501Srpaulo} 482214501Srpaulo 483214501Srpaulo 484214501Srpauloint hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) 485214501Srpaulo{ 486214501Srpaulo if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) 487214501Srpaulo return 0; 488214501Srpaulo return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); 489214501Srpaulo} 490214501Srpaulo 491214501Srpaulo 492214501Srpauloint hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, 493214501Srpaulo const char *ifname, const u8 *addr, void *bss_ctx, 494252726Srpaulo void **drv_priv, char *force_ifname, u8 *if_addr, 495281806Srpaulo const char *bridge, int use_existing) 496214501Srpaulo{ 497214501Srpaulo if (hapd->driver == NULL || hapd->driver->if_add == NULL) 498214501Srpaulo return -1; 499214501Srpaulo return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, 500252726Srpaulo bss_ctx, drv_priv, force_ifname, if_addr, 501337817Scy bridge, use_existing, 1); 502214501Srpaulo} 503214501Srpaulo 504214501Srpaulo 505214501Srpauloint hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, 506214501Srpaulo const char *ifname) 507214501Srpaulo{ 508281806Srpaulo if (hapd->driver == NULL || hapd->drv_priv == NULL || 509281806Srpaulo hapd->driver->if_remove == NULL) 510214501Srpaulo return -1; 511214501Srpaulo return hapd->driver->if_remove(hapd->drv_priv, type, ifname); 512214501Srpaulo} 513214501Srpaulo 514214501Srpaulo 515214501Srpauloint hostapd_set_ieee8021x(struct hostapd_data *hapd, 516214501Srpaulo struct wpa_bss_params *params) 517214501Srpaulo{ 518214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) 519214501Srpaulo return 0; 520214501Srpaulo return hapd->driver->set_ieee8021x(hapd->drv_priv, params); 521214501Srpaulo} 522214501Srpaulo 523214501Srpaulo 524214501Srpauloint hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, 525214501Srpaulo const u8 *addr, int idx, u8 *seq) 526214501Srpaulo{ 527214501Srpaulo if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) 528214501Srpaulo return 0; 529214501Srpaulo return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, 530214501Srpaulo seq); 531214501Srpaulo} 532214501Srpaulo 533214501Srpaulo 534214501Srpauloint hostapd_flush(struct hostapd_data *hapd) 535214501Srpaulo{ 536214501Srpaulo if (hapd->driver == NULL || hapd->driver->flush == NULL) 537214501Srpaulo return 0; 538214501Srpaulo return hapd->driver->flush(hapd->drv_priv); 539214501Srpaulo} 540214501Srpaulo 541214501Srpaulo 542281806Srpauloint hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, 543281806Srpaulo int freq, int channel, int ht_enabled, int vht_enabled, 544351611Scy int he_enabled, 545351611Scy int sec_channel_offset, int oper_chwidth, 546281806Srpaulo int center_segment0, int center_segment1) 547214501Srpaulo{ 548214501Srpaulo struct hostapd_freq_params data; 549351611Scy struct hostapd_hw_modes *cmode = hapd->iface->current_mode; 550281806Srpaulo 551281806Srpaulo if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, 552351611Scy vht_enabled, he_enabled, sec_channel_offset, 553351611Scy oper_chwidth, 554281806Srpaulo center_segment0, center_segment1, 555351611Scy cmode ? cmode->vht_capab : 0, 556351611Scy cmode ? 557351611Scy &cmode->he_capab[IEEE80211_MODE_AP] : NULL)) 558281806Srpaulo return -1; 559281806Srpaulo 560214501Srpaulo if (hapd->driver == NULL) 561214501Srpaulo return 0; 562214501Srpaulo if (hapd->driver->set_freq == NULL) 563214501Srpaulo return 0; 564214501Srpaulo return hapd->driver->set_freq(hapd->drv_priv, &data); 565214501Srpaulo} 566214501Srpaulo 567214501Srpauloint hostapd_set_rts(struct hostapd_data *hapd, int rts) 568214501Srpaulo{ 569214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_rts == NULL) 570214501Srpaulo return 0; 571214501Srpaulo return hapd->driver->set_rts(hapd->drv_priv, rts); 572214501Srpaulo} 573214501Srpaulo 574214501Srpaulo 575214501Srpauloint hostapd_set_frag(struct hostapd_data *hapd, int frag) 576214501Srpaulo{ 577214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_frag == NULL) 578214501Srpaulo return 0; 579214501Srpaulo return hapd->driver->set_frag(hapd->drv_priv, frag); 580214501Srpaulo} 581214501Srpaulo 582214501Srpaulo 583214501Srpauloint hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, 584214501Srpaulo int total_flags, int flags_or, int flags_and) 585214501Srpaulo{ 586214501Srpaulo if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) 587214501Srpaulo return 0; 588214501Srpaulo return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, 589214501Srpaulo flags_or, flags_and); 590214501Srpaulo} 591214501Srpaulo 592214501Srpaulo 593351611Scyint hostapd_sta_set_airtime_weight(struct hostapd_data *hapd, const u8 *addr, 594351611Scy unsigned int weight) 595351611Scy{ 596351611Scy if (!hapd->driver || !hapd->driver->sta_set_airtime_weight) 597351611Scy return 0; 598351611Scy return hapd->driver->sta_set_airtime_weight(hapd->drv_priv, addr, 599351611Scy weight); 600351611Scy} 601351611Scy 602351611Scy 603214501Srpauloint hostapd_set_country(struct hostapd_data *hapd, const char *country) 604214501Srpaulo{ 605214501Srpaulo if (hapd->driver == NULL || 606214501Srpaulo hapd->driver->set_country == NULL) 607214501Srpaulo return 0; 608214501Srpaulo return hapd->driver->set_country(hapd->drv_priv, country); 609214501Srpaulo} 610214501Srpaulo 611214501Srpaulo 612214501Srpauloint hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, 613214501Srpaulo int cw_min, int cw_max, int burst_time) 614214501Srpaulo{ 615214501Srpaulo if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) 616214501Srpaulo return 0; 617214501Srpaulo return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, 618214501Srpaulo cw_min, cw_max, burst_time); 619214501Srpaulo} 620214501Srpaulo 621214501Srpaulo 622214501Srpaulostruct hostapd_hw_modes * 623214501Srpaulohostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, 624346981Scy u16 *flags, u8 *dfs_domain) 625214501Srpaulo{ 626214501Srpaulo if (hapd->driver == NULL || 627214501Srpaulo hapd->driver->get_hw_feature_data == NULL) 628214501Srpaulo return NULL; 629214501Srpaulo return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, 630346981Scy flags, dfs_domain); 631214501Srpaulo} 632214501Srpaulo 633214501Srpaulo 634214501Srpauloint hostapd_driver_commit(struct hostapd_data *hapd) 635214501Srpaulo{ 636214501Srpaulo if (hapd->driver == NULL || hapd->driver->commit == NULL) 637214501Srpaulo return 0; 638214501Srpaulo return hapd->driver->commit(hapd->drv_priv); 639214501Srpaulo} 640214501Srpaulo 641214501Srpaulo 642214501Srpauloint hostapd_drv_none(struct hostapd_data *hapd) 643214501Srpaulo{ 644214501Srpaulo return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; 645214501Srpaulo} 646214501Srpaulo 647214501Srpaulo 648214501Srpauloint hostapd_driver_scan(struct hostapd_data *hapd, 649214501Srpaulo struct wpa_driver_scan_params *params) 650214501Srpaulo{ 651214501Srpaulo if (hapd->driver && hapd->driver->scan2) 652214501Srpaulo return hapd->driver->scan2(hapd->drv_priv, params); 653214501Srpaulo return -1; 654214501Srpaulo} 655214501Srpaulo 656214501Srpaulo 657214501Srpaulostruct wpa_scan_results * hostapd_driver_get_scan_results( 658214501Srpaulo struct hostapd_data *hapd) 659214501Srpaulo{ 660214501Srpaulo if (hapd->driver && hapd->driver->get_scan_results2) 661214501Srpaulo return hapd->driver->get_scan_results2(hapd->drv_priv); 662214501Srpaulo return NULL; 663214501Srpaulo} 664252726Srpaulo 665252726Srpaulo 666252726Srpauloint hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, 667252726Srpaulo int duration) 668252726Srpaulo{ 669252726Srpaulo if (hapd->driver && hapd->driver->set_noa) 670252726Srpaulo return hapd->driver->set_noa(hapd->drv_priv, count, start, 671252726Srpaulo duration); 672252726Srpaulo return -1; 673252726Srpaulo} 674252726Srpaulo 675252726Srpaulo 676252726Srpauloint hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, 677252726Srpaulo enum wpa_alg alg, const u8 *addr, 678252726Srpaulo int key_idx, int set_tx, 679252726Srpaulo const u8 *seq, size_t seq_len, 680252726Srpaulo const u8 *key, size_t key_len) 681252726Srpaulo{ 682252726Srpaulo if (hapd->driver == NULL || hapd->driver->set_key == NULL) 683252726Srpaulo return 0; 684252726Srpaulo return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, 685252726Srpaulo key_idx, set_tx, seq, seq_len, key, 686252726Srpaulo key_len); 687252726Srpaulo} 688252726Srpaulo 689252726Srpaulo 690252726Srpauloint hostapd_drv_send_mlme(struct hostapd_data *hapd, 691252726Srpaulo const void *msg, size_t len, int noack) 692252726Srpaulo{ 693337817Scy if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) 694337817Scy return 0; 695337817Scy return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, 696337817Scy NULL, 0); 697337817Scy} 698337817Scy 699337817Scy 700337817Scyint hostapd_drv_send_mlme_csa(struct hostapd_data *hapd, 701337817Scy const void *msg, size_t len, int noack, 702337817Scy const u16 *csa_offs, size_t csa_offs_len) 703337817Scy{ 704252726Srpaulo if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) 705252726Srpaulo return 0; 706337817Scy return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, 707337817Scy csa_offs, csa_offs_len); 708252726Srpaulo} 709252726Srpaulo 710252726Srpaulo 711252726Srpauloint hostapd_drv_sta_deauth(struct hostapd_data *hapd, 712252726Srpaulo const u8 *addr, int reason) 713252726Srpaulo{ 714337817Scy if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv) 715252726Srpaulo return 0; 716252726Srpaulo return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, 717252726Srpaulo reason); 718252726Srpaulo} 719252726Srpaulo 720252726Srpaulo 721252726Srpauloint hostapd_drv_sta_disassoc(struct hostapd_data *hapd, 722252726Srpaulo const u8 *addr, int reason) 723252726Srpaulo{ 724337817Scy if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv) 725252726Srpaulo return 0; 726252726Srpaulo return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, 727252726Srpaulo reason); 728252726Srpaulo} 729252726Srpaulo 730252726Srpaulo 731252726Srpauloint hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, 732252726Srpaulo const u8 *peer, u8 *buf, u16 *buf_len) 733252726Srpaulo{ 734252726Srpaulo if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) 735281806Srpaulo return -1; 736252726Srpaulo return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, 737252726Srpaulo buf_len); 738252726Srpaulo} 739252726Srpaulo 740252726Srpaulo 741252726Srpauloint hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, 742252726Srpaulo unsigned int wait, const u8 *dst, const u8 *data, 743252726Srpaulo size_t len) 744252726Srpaulo{ 745337817Scy const u8 *bssid; 746337817Scy const u8 wildcard_bssid[ETH_ALEN] = { 747337817Scy 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 748337817Scy }; 749337817Scy 750337817Scy if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv) 751337817Scy return 0; 752337817Scy bssid = hapd->own_addr; 753337817Scy if (!is_multicast_ether_addr(dst) && 754337817Scy len > 0 && data[0] == WLAN_ACTION_PUBLIC) { 755337817Scy struct sta_info *sta; 756337817Scy 757337817Scy /* 758337817Scy * Public Action frames to a STA that is not a member of the BSS 759337817Scy * shall use wildcard BSSID value. 760337817Scy */ 761337817Scy sta = ap_get_sta(hapd, dst); 762337817Scy if (!sta || !(sta->flags & WLAN_STA_ASSOC)) 763337817Scy bssid = wildcard_bssid; 764346981Scy } else if (is_broadcast_ether_addr(dst) && 765346981Scy len > 0 && data[0] == WLAN_ACTION_PUBLIC) { 766346981Scy /* 767346981Scy * The only current use case of Public Action frames with 768346981Scy * broadcast destination address is DPP PKEX. That case is 769346981Scy * directing all devices and not just the STAs within the BSS, 770346981Scy * so have to use the wildcard BSSID value. 771346981Scy */ 772346981Scy bssid = wildcard_bssid; 773337817Scy } 774337817Scy return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, 775337817Scy hapd->own_addr, bssid, data, len, 0); 776337817Scy} 777337817Scy 778337817Scy 779337817Scyint hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd, 780337817Scy unsigned int freq, 781337817Scy unsigned int wait, const u8 *dst, 782337817Scy const u8 *data, size_t len) 783337817Scy{ 784252726Srpaulo if (hapd->driver == NULL || hapd->driver->send_action == NULL) 785252726Srpaulo return 0; 786252726Srpaulo return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, 787252726Srpaulo hapd->own_addr, hapd->own_addr, data, 788252726Srpaulo len, 0); 789252726Srpaulo} 790281806Srpaulo 791281806Srpaulo 792281806Srpauloint hostapd_start_dfs_cac(struct hostapd_iface *iface, 793281806Srpaulo enum hostapd_hw_mode mode, int freq, 794281806Srpaulo int channel, int ht_enabled, int vht_enabled, 795351611Scy int he_enabled, 796351611Scy int sec_channel_offset, int oper_chwidth, 797281806Srpaulo int center_segment0, int center_segment1) 798281806Srpaulo{ 799281806Srpaulo struct hostapd_data *hapd = iface->bss[0]; 800281806Srpaulo struct hostapd_freq_params data; 801281806Srpaulo int res; 802351611Scy struct hostapd_hw_modes *cmode = iface->current_mode; 803281806Srpaulo 804351611Scy if (!hapd->driver || !hapd->driver->start_dfs_cac || !cmode) 805281806Srpaulo return 0; 806281806Srpaulo 807281806Srpaulo if (!iface->conf->ieee80211h) { 808281806Srpaulo wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " 809281806Srpaulo "is not enabled"); 810281806Srpaulo return -1; 811281806Srpaulo } 812281806Srpaulo 813281806Srpaulo if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, 814351611Scy vht_enabled, he_enabled, sec_channel_offset, 815351611Scy oper_chwidth, center_segment0, 816281806Srpaulo center_segment1, 817351611Scy cmode->vht_capab, 818351611Scy &cmode->he_capab[IEEE80211_MODE_AP])) { 819281806Srpaulo wpa_printf(MSG_ERROR, "Can't set freq params"); 820281806Srpaulo return -1; 821281806Srpaulo } 822281806Srpaulo 823281806Srpaulo res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); 824281806Srpaulo if (!res) { 825281806Srpaulo iface->cac_started = 1; 826281806Srpaulo os_get_reltime(&iface->dfs_cac_start); 827281806Srpaulo } 828281806Srpaulo 829281806Srpaulo return res; 830281806Srpaulo} 831281806Srpaulo 832281806Srpaulo 833281806Srpauloint hostapd_drv_set_qos_map(struct hostapd_data *hapd, 834281806Srpaulo const u8 *qos_map_set, u8 qos_map_set_len) 835281806Srpaulo{ 836337817Scy if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv) 837281806Srpaulo return 0; 838281806Srpaulo return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, 839281806Srpaulo qos_map_set_len); 840281806Srpaulo} 841281806Srpaulo 842281806Srpaulo 843289549Srpaulostatic void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, 844289549Srpaulo struct hostapd_hw_modes *mode, 845289549Srpaulo int acs_ch_list_all, 846289549Srpaulo int **freq_list) 847289549Srpaulo{ 848289549Srpaulo int i; 849289549Srpaulo 850289549Srpaulo for (i = 0; i < mode->num_channels; i++) { 851289549Srpaulo struct hostapd_channel_data *chan = &mode->channels[i]; 852289549Srpaulo 853289549Srpaulo if ((acs_ch_list_all || 854289549Srpaulo freq_range_list_includes(&hapd->iface->conf->acs_ch_list, 855289549Srpaulo chan->chan)) && 856346981Scy !(chan->flag & HOSTAPD_CHAN_DISABLED) && 857346981Scy !(hapd->iface->conf->acs_exclude_dfs && 858346981Scy (chan->flag & HOSTAPD_CHAN_RADAR))) 859289549Srpaulo int_array_add_unique(freq_list, chan->freq); 860289549Srpaulo } 861289549Srpaulo} 862289549Srpaulo 863289549Srpaulo 864337817Scyvoid hostapd_get_ext_capa(struct hostapd_iface *iface) 865337817Scy{ 866337817Scy struct hostapd_data *hapd = iface->bss[0]; 867337817Scy 868337817Scy if (!hapd->driver || !hapd->driver->get_ext_capab) 869337817Scy return; 870337817Scy 871337817Scy hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS, 872337817Scy &iface->extended_capa, 873337817Scy &iface->extended_capa_mask, 874337817Scy &iface->extended_capa_len); 875337817Scy} 876337817Scy 877337817Scy 878281806Srpauloint hostapd_drv_do_acs(struct hostapd_data *hapd) 879281806Srpaulo{ 880281806Srpaulo struct drv_acs_params params; 881289549Srpaulo int ret, i, acs_ch_list_all = 0; 882289549Srpaulo u8 *channels = NULL; 883289549Srpaulo unsigned int num_channels = 0; 884289549Srpaulo struct hostapd_hw_modes *mode; 885289549Srpaulo int *freq_list = NULL; 886281806Srpaulo 887281806Srpaulo if (hapd->driver == NULL || hapd->driver->do_acs == NULL) 888281806Srpaulo return 0; 889289549Srpaulo 890281806Srpaulo os_memset(¶ms, 0, sizeof(params)); 891281806Srpaulo params.hw_mode = hapd->iface->conf->hw_mode; 892289549Srpaulo 893289549Srpaulo /* 894289549Srpaulo * If no chanlist config parameter is provided, include all enabled 895289549Srpaulo * channels of the selected hw_mode. 896289549Srpaulo */ 897289549Srpaulo if (!hapd->iface->conf->acs_ch_list.num) 898289549Srpaulo acs_ch_list_all = 1; 899289549Srpaulo 900289549Srpaulo mode = hapd->iface->current_mode; 901289549Srpaulo if (mode) { 902289549Srpaulo channels = os_malloc(mode->num_channels); 903289549Srpaulo if (channels == NULL) 904289549Srpaulo return -1; 905289549Srpaulo 906289549Srpaulo for (i = 0; i < mode->num_channels; i++) { 907289549Srpaulo struct hostapd_channel_data *chan = &mode->channels[i]; 908289549Srpaulo if (!acs_ch_list_all && 909289549Srpaulo !freq_range_list_includes( 910289549Srpaulo &hapd->iface->conf->acs_ch_list, 911289549Srpaulo chan->chan)) 912289549Srpaulo continue; 913346981Scy if (hapd->iface->conf->acs_exclude_dfs && 914346981Scy (chan->flag & HOSTAPD_CHAN_RADAR)) 915346981Scy continue; 916289549Srpaulo if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { 917289549Srpaulo channels[num_channels++] = chan->chan; 918289549Srpaulo int_array_add_unique(&freq_list, chan->freq); 919289549Srpaulo } 920289549Srpaulo } 921289549Srpaulo } else { 922289549Srpaulo for (i = 0; i < hapd->iface->num_hw_features; i++) { 923289549Srpaulo mode = &hapd->iface->hw_features[i]; 924289549Srpaulo hostapd_get_hw_mode_any_channels(hapd, mode, 925289549Srpaulo acs_ch_list_all, 926289549Srpaulo &freq_list); 927289549Srpaulo } 928289549Srpaulo } 929289549Srpaulo 930289549Srpaulo params.ch_list = channels; 931289549Srpaulo params.ch_list_len = num_channels; 932289549Srpaulo params.freq_list = freq_list; 933289549Srpaulo 934281806Srpaulo params.ht_enabled = !!(hapd->iface->conf->ieee80211n); 935281806Srpaulo params.ht40_enabled = !!(hapd->iface->conf->ht_capab & 936281806Srpaulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); 937289549Srpaulo params.vht_enabled = !!(hapd->iface->conf->ieee80211ac); 938289549Srpaulo params.ch_width = 20; 939289549Srpaulo if (hapd->iface->conf->ieee80211n && params.ht40_enabled) 940289549Srpaulo params.ch_width = 40; 941289549Srpaulo 942351611Scy /* Note: VHT20 is defined by combination of ht_capab & oper_chwidth 943289549Srpaulo */ 944351611Scy if ((hapd->iface->conf->ieee80211ax || 945351611Scy hapd->iface->conf->ieee80211ac) && 946351611Scy params.ht40_enabled) { 947351611Scy u8 oper_chwidth = hostapd_get_oper_chwidth(hapd->iface->conf); 948351611Scy 949351611Scy if (oper_chwidth == CHANWIDTH_80MHZ) 950289549Srpaulo params.ch_width = 80; 951351611Scy else if (oper_chwidth == CHANWIDTH_160MHZ || 952351611Scy oper_chwidth == CHANWIDTH_80P80MHZ) 953289549Srpaulo params.ch_width = 160; 954289549Srpaulo } 955289549Srpaulo 956289549Srpaulo ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms); 957289549Srpaulo os_free(channels); 958289549Srpaulo 959289549Srpaulo return ret; 960281806Srpaulo} 961351611Scy 962351611Scy 963351611Scyint hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, 964351611Scy u16 reason_code, const u8 *ie, size_t ielen) 965351611Scy{ 966351611Scy if (!hapd->driver || !hapd->driver->update_dh_ie || !hapd->drv_priv) 967351611Scy return 0; 968351611Scy return hapd->driver->update_dh_ie(hapd->drv_priv, peer, reason_code, 969351611Scy ie, ielen); 970351611Scy} 971