1e28a4053SRui Paulo /* 2e28a4053SRui Paulo * hostapd - Driver operations 3e28a4053SRui Paulo * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi> 4e28a4053SRui Paulo * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 7e28a4053SRui Paulo */ 8e28a4053SRui Paulo 9e28a4053SRui Paulo #include "utils/includes.h" 10e28a4053SRui Paulo 11e28a4053SRui Paulo #include "utils/common.h" 12e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 13c1d255d3SCy Schubert #include "common/ieee802_11_common.h" 145b9c547cSRui Paulo #include "common/hw_features_common.h" 15f05cddf9SRui Paulo #include "wps/wps.h" 16f05cddf9SRui Paulo #include "p2p/p2p.h" 17e28a4053SRui Paulo #include "hostapd.h" 18e28a4053SRui Paulo #include "ieee802_11.h" 19e28a4053SRui Paulo #include "sta_info.h" 20e28a4053SRui Paulo #include "ap_config.h" 21f05cddf9SRui Paulo #include "p2p_hostapd.h" 22f05cddf9SRui Paulo #include "hs20.h" 2385732ac8SCy Schubert #include "wpa_auth.h" 24e28a4053SRui Paulo #include "ap_drv_ops.h" 25e28a4053SRui Paulo 26e28a4053SRui Paulo 27f05cddf9SRui Paulo u32 hostapd_sta_flags_to_drv(u32 flags) 28e28a4053SRui Paulo { 29e28a4053SRui Paulo int res = 0; 30e28a4053SRui Paulo if (flags & WLAN_STA_AUTHORIZED) 31e28a4053SRui Paulo res |= WPA_STA_AUTHORIZED; 32e28a4053SRui Paulo if (flags & WLAN_STA_WMM) 33e28a4053SRui Paulo res |= WPA_STA_WMM; 34e28a4053SRui Paulo if (flags & WLAN_STA_SHORT_PREAMBLE) 35e28a4053SRui Paulo res |= WPA_STA_SHORT_PREAMBLE; 36e28a4053SRui Paulo if (flags & WLAN_STA_MFP) 37e28a4053SRui Paulo res |= WPA_STA_MFP; 38780fb4a2SCy Schubert if (flags & WLAN_STA_AUTH) 39780fb4a2SCy Schubert res |= WPA_STA_AUTHENTICATED; 40780fb4a2SCy Schubert if (flags & WLAN_STA_ASSOC) 41780fb4a2SCy Schubert res |= WPA_STA_ASSOCIATED; 42e28a4053SRui Paulo return res; 43e28a4053SRui Paulo } 44e28a4053SRui Paulo 45e28a4053SRui Paulo 46780fb4a2SCy Schubert static int add_buf(struct wpabuf **dst, const struct wpabuf *src) 47780fb4a2SCy Schubert { 48780fb4a2SCy Schubert if (!src) 49780fb4a2SCy Schubert return 0; 50780fb4a2SCy Schubert if (wpabuf_resize(dst, wpabuf_len(src)) != 0) 51780fb4a2SCy Schubert return -1; 52780fb4a2SCy Schubert wpabuf_put_buf(*dst, src); 53780fb4a2SCy Schubert return 0; 54780fb4a2SCy Schubert } 55780fb4a2SCy Schubert 56780fb4a2SCy Schubert 57780fb4a2SCy Schubert static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len) 58780fb4a2SCy Schubert { 59780fb4a2SCy Schubert if (!data || !len) 60780fb4a2SCy Schubert return 0; 61780fb4a2SCy Schubert if (wpabuf_resize(dst, len) != 0) 62780fb4a2SCy Schubert return -1; 63780fb4a2SCy Schubert wpabuf_put_data(*dst, data, len); 64780fb4a2SCy Schubert return 0; 65780fb4a2SCy Schubert } 66780fb4a2SCy Schubert 67780fb4a2SCy Schubert 68f05cddf9SRui Paulo int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, 69f05cddf9SRui Paulo struct wpabuf **beacon_ret, 70f05cddf9SRui Paulo struct wpabuf **proberesp_ret, 71f05cddf9SRui Paulo struct wpabuf **assocresp_ret) 72e28a4053SRui Paulo { 73f05cddf9SRui Paulo struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; 74f05cddf9SRui Paulo u8 buf[200], *pos; 75f05cddf9SRui Paulo 76f05cddf9SRui Paulo *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; 77f05cddf9SRui Paulo 78*a90b9d01SCy Schubert #ifdef NEED_AP_MLME 79*a90b9d01SCy Schubert pos = buf; 80*a90b9d01SCy Schubert pos = hostapd_eid_rm_enabled_capab(hapd, pos, sizeof(buf)); 81*a90b9d01SCy Schubert if (add_buf_data(&assocresp, buf, pos - buf) < 0 || 82*a90b9d01SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 83*a90b9d01SCy Schubert goto fail; 84*a90b9d01SCy Schubert #endif /* NEED_AP_MLME */ 85*a90b9d01SCy Schubert 86f05cddf9SRui Paulo pos = buf; 87f05cddf9SRui Paulo pos = hostapd_eid_time_adv(hapd, pos); 88780fb4a2SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0) 89f05cddf9SRui Paulo goto fail; 90f05cddf9SRui Paulo pos = hostapd_eid_time_zone(hapd, pos); 91780fb4a2SCy Schubert if (add_buf_data(&proberesp, buf, pos - buf) < 0) 92f05cddf9SRui Paulo goto fail; 93f05cddf9SRui Paulo 94f05cddf9SRui Paulo pos = buf; 95*a90b9d01SCy Schubert pos = hostapd_eid_ext_capab(hapd, pos, false); 96780fb4a2SCy Schubert if (add_buf_data(&assocresp, buf, pos - buf) < 0) 97f05cddf9SRui Paulo goto fail; 98f05cddf9SRui Paulo pos = hostapd_eid_interworking(hapd, pos); 99f05cddf9SRui Paulo pos = hostapd_eid_adv_proto(hapd, pos); 100f05cddf9SRui Paulo pos = hostapd_eid_roaming_consortium(hapd, pos); 101780fb4a2SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 102780fb4a2SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 103f05cddf9SRui Paulo goto fail; 104f05cddf9SRui Paulo 105325151a3SRui Paulo #ifdef CONFIG_FST 106780fb4a2SCy Schubert if (add_buf(&beacon, hapd->iface->fst_ies) < 0 || 107780fb4a2SCy Schubert add_buf(&proberesp, hapd->iface->fst_ies) < 0 || 108780fb4a2SCy Schubert add_buf(&assocresp, hapd->iface->fst_ies) < 0) 109325151a3SRui Paulo goto fail; 110325151a3SRui Paulo #endif /* CONFIG_FST */ 111325151a3SRui Paulo 11285732ac8SCy Schubert #ifdef CONFIG_FILS 11385732ac8SCy Schubert pos = hostapd_eid_fils_indic(hapd, buf, 0); 11485732ac8SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 11585732ac8SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 11685732ac8SCy Schubert goto fail; 11785732ac8SCy Schubert #endif /* CONFIG_FILS */ 11885732ac8SCy Schubert 119c1d255d3SCy Schubert pos = hostapd_eid_rsnxe(hapd, buf, sizeof(buf)); 120c1d255d3SCy Schubert if (add_buf_data(&assocresp, buf, pos - buf) < 0) 121c1d255d3SCy Schubert goto fail; 122c1d255d3SCy Schubert 123780fb4a2SCy Schubert if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 || 124780fb4a2SCy Schubert add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0) 125f05cddf9SRui Paulo goto fail; 126f05cddf9SRui Paulo 127f05cddf9SRui Paulo #ifdef CONFIG_P2P 128780fb4a2SCy Schubert if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 || 129780fb4a2SCy Schubert add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0) 130f05cddf9SRui Paulo goto fail; 131f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 132f05cddf9SRui Paulo 133f05cddf9SRui Paulo #ifdef CONFIG_P2P_MANAGER 134f05cddf9SRui Paulo if (hapd->conf->p2p & P2P_MANAGE) { 135f05cddf9SRui Paulo if (wpabuf_resize(&beacon, 100) == 0) { 136f05cddf9SRui Paulo u8 *start, *p; 137f05cddf9SRui Paulo start = wpabuf_put(beacon, 0); 138f05cddf9SRui Paulo p = hostapd_eid_p2p_manage(hapd, start); 139f05cddf9SRui Paulo wpabuf_put(beacon, p - start); 140f05cddf9SRui Paulo } 141f05cddf9SRui Paulo 142f05cddf9SRui Paulo if (wpabuf_resize(&proberesp, 100) == 0) { 143f05cddf9SRui Paulo u8 *start, *p; 144f05cddf9SRui Paulo start = wpabuf_put(proberesp, 0); 145f05cddf9SRui Paulo p = hostapd_eid_p2p_manage(hapd, start); 146f05cddf9SRui Paulo wpabuf_put(proberesp, p - start); 147f05cddf9SRui Paulo } 148f05cddf9SRui Paulo } 149f05cddf9SRui Paulo #endif /* CONFIG_P2P_MANAGER */ 150f05cddf9SRui Paulo 1515b9c547cSRui Paulo #ifdef CONFIG_WPS 152f05cddf9SRui Paulo if (hapd->conf->wps_state) { 153f05cddf9SRui Paulo struct wpabuf *a = wps_build_assoc_resp_ie(); 154780fb4a2SCy Schubert add_buf(&assocresp, a); 155f05cddf9SRui Paulo wpabuf_free(a); 156f05cddf9SRui Paulo } 1575b9c547cSRui Paulo #endif /* CONFIG_WPS */ 158f05cddf9SRui Paulo 159f05cddf9SRui Paulo #ifdef CONFIG_P2P_MANAGER 160f05cddf9SRui Paulo if (hapd->conf->p2p & P2P_MANAGE) { 161f05cddf9SRui Paulo if (wpabuf_resize(&assocresp, 100) == 0) { 162f05cddf9SRui Paulo u8 *start, *p; 163f05cddf9SRui Paulo start = wpabuf_put(assocresp, 0); 164f05cddf9SRui Paulo p = hostapd_eid_p2p_manage(hapd, start); 165f05cddf9SRui Paulo wpabuf_put(assocresp, p - start); 166f05cddf9SRui Paulo } 167f05cddf9SRui Paulo } 168f05cddf9SRui Paulo #endif /* CONFIG_P2P_MANAGER */ 169f05cddf9SRui Paulo 170f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY 171f05cddf9SRui Paulo if (hapd->p2p_group) { 172f05cddf9SRui Paulo struct wpabuf *a; 173f05cddf9SRui Paulo a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); 174780fb4a2SCy Schubert add_buf(&assocresp, a); 175f05cddf9SRui Paulo wpabuf_free(a); 176f05cddf9SRui Paulo } 177f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */ 178f05cddf9SRui Paulo 179f05cddf9SRui Paulo #ifdef CONFIG_HS20 180780fb4a2SCy Schubert pos = hostapd_eid_hs20_indication(hapd, buf); 181780fb4a2SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 182780fb4a2SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 183f05cddf9SRui Paulo goto fail; 1845b9c547cSRui Paulo 1855b9c547cSRui Paulo pos = hostapd_eid_osen(hapd, buf); 186780fb4a2SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 187780fb4a2SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 1885b9c547cSRui Paulo goto fail; 189f05cddf9SRui Paulo #endif /* CONFIG_HS20 */ 190f05cddf9SRui Paulo 191780fb4a2SCy Schubert #ifdef CONFIG_MBO 19285732ac8SCy Schubert if (hapd->conf->mbo_enabled || 19385732ac8SCy Schubert OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { 194780fb4a2SCy Schubert pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); 195780fb4a2SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 196780fb4a2SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0 || 197780fb4a2SCy Schubert add_buf_data(&assocresp, buf, pos - buf) < 0) 198780fb4a2SCy Schubert goto fail; 1995b9c547cSRui Paulo } 200780fb4a2SCy Schubert #endif /* CONFIG_MBO */ 201780fb4a2SCy Schubert 20285732ac8SCy Schubert #ifdef CONFIG_OWE 20385732ac8SCy Schubert pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf)); 20485732ac8SCy Schubert if (add_buf_data(&beacon, buf, pos - buf) < 0 || 20585732ac8SCy Schubert add_buf_data(&proberesp, buf, pos - buf) < 0) 20685732ac8SCy Schubert goto fail; 20785732ac8SCy Schubert #endif /* CONFIG_OWE */ 20885732ac8SCy Schubert 209780fb4a2SCy Schubert add_buf(&beacon, hapd->conf->vendor_elements); 210780fb4a2SCy Schubert add_buf(&proberesp, hapd->conf->vendor_elements); 211*a90b9d01SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 212*a90b9d01SCy Schubert add_buf(&proberesp, hapd->conf->presp_elements); 213*a90b9d01SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 214780fb4a2SCy Schubert add_buf(&assocresp, hapd->conf->assocresp_elements); 2155b9c547cSRui Paulo 216f05cddf9SRui Paulo *beacon_ret = beacon; 217f05cddf9SRui Paulo *proberesp_ret = proberesp; 218f05cddf9SRui Paulo *assocresp_ret = assocresp; 219f05cddf9SRui Paulo 220f05cddf9SRui Paulo return 0; 221f05cddf9SRui Paulo 222f05cddf9SRui Paulo fail: 223f05cddf9SRui Paulo wpabuf_free(beacon); 224f05cddf9SRui Paulo wpabuf_free(proberesp); 225f05cddf9SRui Paulo wpabuf_free(assocresp); 226f05cddf9SRui Paulo return -1; 227f05cddf9SRui Paulo } 228f05cddf9SRui Paulo 229f05cddf9SRui Paulo 230f05cddf9SRui Paulo void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, 231f05cddf9SRui Paulo struct wpabuf *beacon, 232f05cddf9SRui Paulo struct wpabuf *proberesp, 233f05cddf9SRui Paulo struct wpabuf *assocresp) 234f05cddf9SRui Paulo { 235f05cddf9SRui Paulo wpabuf_free(beacon); 236f05cddf9SRui Paulo wpabuf_free(proberesp); 237f05cddf9SRui Paulo wpabuf_free(assocresp); 238f05cddf9SRui Paulo } 239f05cddf9SRui Paulo 240f05cddf9SRui Paulo 241325151a3SRui Paulo int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd) 242325151a3SRui Paulo { 243325151a3SRui Paulo if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) 244325151a3SRui Paulo return 0; 245325151a3SRui Paulo 246325151a3SRui Paulo return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL); 247325151a3SRui Paulo } 248325151a3SRui Paulo 249325151a3SRui Paulo 250f05cddf9SRui Paulo int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) 251f05cddf9SRui Paulo { 252f05cddf9SRui Paulo struct wpabuf *beacon, *proberesp, *assocresp; 253e28a4053SRui Paulo int ret; 254e28a4053SRui Paulo 255e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) 256e28a4053SRui Paulo return 0; 257e28a4053SRui Paulo 258f05cddf9SRui Paulo if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < 259f05cddf9SRui Paulo 0) 260f05cddf9SRui Paulo return -1; 261e28a4053SRui Paulo 262f05cddf9SRui Paulo ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, 263f05cddf9SRui Paulo assocresp); 264f05cddf9SRui Paulo 265f05cddf9SRui Paulo hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); 266e28a4053SRui Paulo 267e28a4053SRui Paulo return ret; 268e28a4053SRui Paulo } 269e28a4053SRui Paulo 270e28a4053SRui Paulo 271*a90b9d01SCy Schubert bool hostapd_sta_is_link_sta(struct hostapd_data *hapd, 272*a90b9d01SCy Schubert struct sta_info *sta) 273*a90b9d01SCy Schubert { 274*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 275*a90b9d01SCy Schubert if (ap_sta_is_mld(hapd, sta) && 276*a90b9d01SCy Schubert sta->mld_assoc_link_id != hapd->mld_link_id) 277*a90b9d01SCy Schubert return true; 278*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 279*a90b9d01SCy Schubert 280*a90b9d01SCy Schubert return false; 281*a90b9d01SCy Schubert } 282*a90b9d01SCy Schubert 283*a90b9d01SCy Schubert 284f05cddf9SRui Paulo int hostapd_set_authorized(struct hostapd_data *hapd, 285e28a4053SRui Paulo struct sta_info *sta, int authorized) 286e28a4053SRui Paulo { 287*a90b9d01SCy Schubert /* 288*a90b9d01SCy Schubert * The WPA_STA_AUTHORIZED flag is relevant only for the MLD station and 289*a90b9d01SCy Schubert * not to the link stations (as the authorization is done between the 290*a90b9d01SCy Schubert * MLD peers). Thus, do not propagate the change to the driver for the 291*a90b9d01SCy Schubert * link stations. 292*a90b9d01SCy Schubert */ 293*a90b9d01SCy Schubert if (hostapd_sta_is_link_sta(hapd, sta)) { 294*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, 295*a90b9d01SCy Schubert "%s: Do not update link station flags (" MACSTR ")", 296*a90b9d01SCy Schubert __func__, MAC2STR(sta->addr)); 297*a90b9d01SCy Schubert return 0; 298*a90b9d01SCy Schubert } 299*a90b9d01SCy Schubert 300e28a4053SRui Paulo if (authorized) { 301e28a4053SRui Paulo return hostapd_sta_set_flags(hapd, sta->addr, 302e28a4053SRui Paulo hostapd_sta_flags_to_drv( 303e28a4053SRui Paulo sta->flags), 304e28a4053SRui Paulo WPA_STA_AUTHORIZED, ~0); 305e28a4053SRui Paulo } 306e28a4053SRui Paulo 307e28a4053SRui Paulo return hostapd_sta_set_flags(hapd, sta->addr, 308e28a4053SRui Paulo hostapd_sta_flags_to_drv(sta->flags), 309e28a4053SRui Paulo 0, ~WPA_STA_AUTHORIZED); 310e28a4053SRui Paulo } 311e28a4053SRui Paulo 312e28a4053SRui Paulo 313f05cddf9SRui Paulo int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) 314e28a4053SRui Paulo { 315e28a4053SRui Paulo int set_flags, total_flags, flags_and, flags_or; 316e28a4053SRui Paulo total_flags = hostapd_sta_flags_to_drv(sta->flags); 317*a90b9d01SCy Schubert set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP | 318*a90b9d01SCy Schubert WPA_STA_AUTHORIZED; 319*a90b9d01SCy Schubert 320*a90b9d01SCy Schubert /* 321*a90b9d01SCy Schubert * All the station flags other than WPA_STA_SHORT_PREAMBLE are relevant 322*a90b9d01SCy Schubert * only for the MLD station and not to the link stations (as these flags 323*a90b9d01SCy Schubert * are related to the MLD state and not the link state). As for the 324*a90b9d01SCy Schubert * WPA_STA_SHORT_PREAMBLE, since the station is an EHT station, it must 325*a90b9d01SCy Schubert * support short preamble. Thus, do not propagate the change to the 326*a90b9d01SCy Schubert * driver for the link stations. 327*a90b9d01SCy Schubert */ 328*a90b9d01SCy Schubert if (hostapd_sta_is_link_sta(hapd, sta)) { 329*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, 330*a90b9d01SCy Schubert "%s: Do not update link station flags (" MACSTR ")", 331*a90b9d01SCy Schubert __func__, MAC2STR(sta->addr)); 332*a90b9d01SCy Schubert return 0; 333*a90b9d01SCy Schubert } 334*a90b9d01SCy Schubert 335e28a4053SRui Paulo flags_or = total_flags & set_flags; 336e28a4053SRui Paulo flags_and = total_flags | ~set_flags; 337e28a4053SRui Paulo return hostapd_sta_set_flags(hapd, sta->addr, total_flags, 338e28a4053SRui Paulo flags_or, flags_and); 339e28a4053SRui Paulo } 340e28a4053SRui Paulo 341e28a4053SRui Paulo 342f05cddf9SRui Paulo int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, 343f05cddf9SRui Paulo int enabled) 344e28a4053SRui Paulo { 345e28a4053SRui Paulo struct wpa_bss_params params; 346e28a4053SRui Paulo os_memset(¶ms, 0, sizeof(params)); 347e28a4053SRui Paulo params.ifname = ifname; 348e28a4053SRui Paulo params.enabled = enabled; 349e28a4053SRui Paulo if (enabled) { 350e28a4053SRui Paulo params.wpa = hapd->conf->wpa; 351e28a4053SRui Paulo params.ieee802_1x = hapd->conf->ieee802_1x; 352e28a4053SRui Paulo params.wpa_group = hapd->conf->wpa_group; 353325151a3SRui Paulo if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == 354325151a3SRui Paulo (WPA_PROTO_WPA | WPA_PROTO_RSN)) 3555b9c547cSRui Paulo params.wpa_pairwise = hapd->conf->wpa_pairwise | 3565b9c547cSRui Paulo hapd->conf->rsn_pairwise; 357325151a3SRui Paulo else if (hapd->conf->wpa & WPA_PROTO_RSN) 358325151a3SRui Paulo params.wpa_pairwise = hapd->conf->rsn_pairwise; 359325151a3SRui Paulo else if (hapd->conf->wpa & WPA_PROTO_WPA) 360325151a3SRui Paulo params.wpa_pairwise = hapd->conf->wpa_pairwise; 361e28a4053SRui Paulo params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; 362e28a4053SRui Paulo params.rsn_preauth = hapd->conf->rsn_preauth; 363f05cddf9SRui Paulo params.ieee80211w = hapd->conf->ieee80211w; 364e28a4053SRui Paulo } 365e28a4053SRui Paulo return hostapd_set_ieee8021x(hapd, ¶ms); 366e28a4053SRui Paulo } 367e28a4053SRui Paulo 368e28a4053SRui Paulo 369f05cddf9SRui Paulo int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) 370e28a4053SRui Paulo { 371e28a4053SRui Paulo char force_ifname[IFNAMSIZ]; 372e28a4053SRui Paulo u8 if_addr[ETH_ALEN]; 373f05cddf9SRui Paulo return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, 3745b9c547cSRui Paulo NULL, NULL, force_ifname, if_addr, NULL, 0); 375e28a4053SRui Paulo } 376e28a4053SRui Paulo 377f05cddf9SRui Paulo 378f05cddf9SRui Paulo int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) 379e28a4053SRui Paulo { 380e28a4053SRui Paulo return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); 381e28a4053SRui Paulo } 382e28a4053SRui Paulo 383e28a4053SRui Paulo 3845b9c547cSRui Paulo int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, 3855b9c547cSRui Paulo const u8 *addr, int aid, int val) 386e28a4053SRui Paulo { 387f05cddf9SRui Paulo const char *bridge = NULL; 388f05cddf9SRui Paulo 389e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) 3905b9c547cSRui Paulo return -1; 391f05cddf9SRui Paulo if (hapd->conf->wds_bridge[0]) 392f05cddf9SRui Paulo bridge = hapd->conf->wds_bridge; 393f05cddf9SRui Paulo else if (hapd->conf->bridge[0]) 394f05cddf9SRui Paulo bridge = hapd->conf->bridge; 395f05cddf9SRui Paulo return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, 3965b9c547cSRui Paulo bridge, ifname_wds); 397e28a4053SRui Paulo } 398e28a4053SRui Paulo 399e28a4053SRui Paulo 400f05cddf9SRui Paulo int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, 401f05cddf9SRui Paulo u16 auth_alg) 402e28a4053SRui Paulo { 403f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) 404c1d255d3SCy Schubert return -EOPNOTSUPP; 405f05cddf9SRui Paulo return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); 406e28a4053SRui Paulo } 407e28a4053SRui Paulo 408e28a4053SRui Paulo 409f05cddf9SRui Paulo int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, 410f05cddf9SRui Paulo u16 seq, u16 status, const u8 *ie, size_t len) 411e28a4053SRui Paulo { 41285732ac8SCy Schubert struct wpa_driver_sta_auth_params params; 41385732ac8SCy Schubert #ifdef CONFIG_FILS 41485732ac8SCy Schubert struct sta_info *sta; 41585732ac8SCy Schubert #endif /* CONFIG_FILS */ 41685732ac8SCy Schubert 417f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) 418e28a4053SRui Paulo return 0; 41985732ac8SCy Schubert 42085732ac8SCy Schubert os_memset(¶ms, 0, sizeof(params)); 42185732ac8SCy Schubert 42285732ac8SCy Schubert #ifdef CONFIG_FILS 42385732ac8SCy Schubert sta = ap_get_sta(hapd, addr); 42485732ac8SCy Schubert if (!sta) { 42585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "Station " MACSTR 42685732ac8SCy Schubert " not found for sta_auth processing", 42785732ac8SCy Schubert MAC2STR(addr)); 42885732ac8SCy Schubert return 0; 42985732ac8SCy Schubert } 43085732ac8SCy Schubert 43185732ac8SCy Schubert if (sta->auth_alg == WLAN_AUTH_FILS_SK || 43285732ac8SCy Schubert sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || 43385732ac8SCy Schubert sta->auth_alg == WLAN_AUTH_FILS_PK) { 43485732ac8SCy Schubert params.fils_auth = 1; 43585732ac8SCy Schubert wpa_auth_get_fils_aead_params(sta->wpa_sm, params.fils_anonce, 43685732ac8SCy Schubert params.fils_snonce, 43785732ac8SCy Schubert params.fils_kek, 43885732ac8SCy Schubert ¶ms.fils_kek_len); 43985732ac8SCy Schubert } 44085732ac8SCy Schubert #endif /* CONFIG_FILS */ 44185732ac8SCy Schubert 44285732ac8SCy Schubert params.own_addr = hapd->own_addr; 44385732ac8SCy Schubert params.addr = addr; 44485732ac8SCy Schubert params.seq = seq; 44585732ac8SCy Schubert params.status = status; 44685732ac8SCy Schubert params.ie = ie; 44785732ac8SCy Schubert params.len = len; 44885732ac8SCy Schubert 44985732ac8SCy Schubert return hapd->driver->sta_auth(hapd->drv_priv, ¶ms); 450e28a4053SRui Paulo } 451e28a4053SRui Paulo 452e28a4053SRui Paulo 453f05cddf9SRui Paulo int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, 454f05cddf9SRui Paulo int reassoc, u16 status, const u8 *ie, size_t len) 455e28a4053SRui Paulo { 456f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL) 457e28a4053SRui Paulo return 0; 458f05cddf9SRui Paulo return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr, 459f05cddf9SRui Paulo reassoc, status, ie, len); 460e28a4053SRui Paulo } 461e28a4053SRui Paulo 462e28a4053SRui Paulo 463f05cddf9SRui Paulo int hostapd_sta_add(struct hostapd_data *hapd, 464e28a4053SRui Paulo const u8 *addr, u16 aid, u16 capability, 465e28a4053SRui Paulo const u8 *supp_rates, size_t supp_rates_len, 466e28a4053SRui Paulo u16 listen_interval, 467f05cddf9SRui Paulo const struct ieee80211_ht_capabilities *ht_capab, 4685b9c547cSRui Paulo const struct ieee80211_vht_capabilities *vht_capab, 469206b73d0SCy Schubert const struct ieee80211_he_capabilities *he_capab, 470206b73d0SCy Schubert size_t he_capab_len, 471*a90b9d01SCy Schubert const struct ieee80211_eht_capabilities *eht_capab, 472*a90b9d01SCy Schubert size_t eht_capab_len, 473c1d255d3SCy Schubert const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, 474780fb4a2SCy Schubert u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, 475*a90b9d01SCy Schubert int set, const u8 *link_addr, bool mld_link_sta) 476e28a4053SRui Paulo { 477e28a4053SRui Paulo struct hostapd_sta_add_params params; 478e28a4053SRui Paulo 479e28a4053SRui Paulo if (hapd->driver == NULL) 480e28a4053SRui Paulo return 0; 481e28a4053SRui Paulo if (hapd->driver->sta_add == NULL) 482e28a4053SRui Paulo return 0; 483e28a4053SRui Paulo 484e28a4053SRui Paulo os_memset(¶ms, 0, sizeof(params)); 485e28a4053SRui Paulo params.addr = addr; 486e28a4053SRui Paulo params.aid = aid; 487e28a4053SRui Paulo params.capability = capability; 488e28a4053SRui Paulo params.supp_rates = supp_rates; 489e28a4053SRui Paulo params.supp_rates_len = supp_rates_len; 490e28a4053SRui Paulo params.listen_interval = listen_interval; 491e28a4053SRui Paulo params.ht_capabilities = ht_capab; 4925b9c547cSRui Paulo params.vht_capabilities = vht_capab; 493206b73d0SCy Schubert params.he_capab = he_capab; 494206b73d0SCy Schubert params.he_capab_len = he_capab_len; 495*a90b9d01SCy Schubert params.eht_capab = eht_capab; 496*a90b9d01SCy Schubert params.eht_capab_len = eht_capab_len; 497c1d255d3SCy Schubert params.he_6ghz_capab = he_6ghz_capab; 4985b9c547cSRui Paulo params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); 4995b9c547cSRui Paulo params.vht_opmode = vht_opmode; 500f05cddf9SRui Paulo params.flags = hostapd_sta_flags_to_drv(flags); 501f05cddf9SRui Paulo params.qosinfo = qosinfo; 502780fb4a2SCy Schubert params.support_p2p_ps = supp_p2p_ps; 503780fb4a2SCy Schubert params.set = set; 504*a90b9d01SCy Schubert params.mld_link_id = -1; 505*a90b9d01SCy Schubert 506*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 507*a90b9d01SCy Schubert /* 508*a90b9d01SCy Schubert * An AP MLD needs to always specify to what link the station needs 509*a90b9d01SCy Schubert * to be added. 510*a90b9d01SCy Schubert */ 511*a90b9d01SCy Schubert if (hapd->conf->mld_ap) { 512*a90b9d01SCy Schubert params.mld_link_id = hapd->mld_link_id; 513*a90b9d01SCy Schubert params.mld_link_addr = link_addr; 514*a90b9d01SCy Schubert params.mld_link_sta = mld_link_sta; 515*a90b9d01SCy Schubert } 516*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 517*a90b9d01SCy Schubert 518e28a4053SRui Paulo return hapd->driver->sta_add(hapd->drv_priv, ¶ms); 519e28a4053SRui Paulo } 520e28a4053SRui Paulo 521e28a4053SRui Paulo 522f05cddf9SRui Paulo int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, 523f05cddf9SRui Paulo u8 *tspec_ie, size_t tspec_ielen) 524e28a4053SRui Paulo { 525f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->add_tspec == NULL) 526e28a4053SRui Paulo return 0; 527f05cddf9SRui Paulo return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie, 528f05cddf9SRui Paulo tspec_ielen); 529e28a4053SRui Paulo } 530e28a4053SRui Paulo 531e28a4053SRui Paulo 532e28a4053SRui Paulo int hostapd_set_privacy(struct hostapd_data *hapd, int enabled) 533e28a4053SRui Paulo { 534e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) 535e28a4053SRui Paulo return 0; 536e28a4053SRui Paulo return hapd->driver->set_privacy(hapd->drv_priv, enabled); 537e28a4053SRui Paulo } 538e28a4053SRui Paulo 539e28a4053SRui Paulo 540e28a4053SRui Paulo int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, 541e28a4053SRui Paulo size_t elem_len) 542e28a4053SRui Paulo { 543e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) 544e28a4053SRui Paulo return 0; 545e28a4053SRui Paulo return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); 546e28a4053SRui Paulo } 547e28a4053SRui Paulo 548e28a4053SRui Paulo 549e28a4053SRui Paulo int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) 550e28a4053SRui Paulo { 551e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) 552e28a4053SRui Paulo return 0; 553e28a4053SRui Paulo return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); 554e28a4053SRui Paulo } 555e28a4053SRui Paulo 556e28a4053SRui Paulo 557e28a4053SRui Paulo int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) 558e28a4053SRui Paulo { 559e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) 560e28a4053SRui Paulo return 0; 561e28a4053SRui Paulo return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); 562e28a4053SRui Paulo } 563e28a4053SRui Paulo 564e28a4053SRui Paulo 565e28a4053SRui Paulo int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, 566e28a4053SRui Paulo const char *ifname, const u8 *addr, void *bss_ctx, 567f05cddf9SRui Paulo void **drv_priv, char *force_ifname, u8 *if_addr, 5685b9c547cSRui Paulo const char *bridge, int use_existing) 569e28a4053SRui Paulo { 570e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->if_add == NULL) 571e28a4053SRui Paulo return -1; 572e28a4053SRui Paulo return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, 573f05cddf9SRui Paulo bss_ctx, drv_priv, force_ifname, if_addr, 574780fb4a2SCy Schubert bridge, use_existing, 1); 575e28a4053SRui Paulo } 576e28a4053SRui Paulo 577e28a4053SRui Paulo 578*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 579*a90b9d01SCy Schubert int hostapd_if_link_remove(struct hostapd_data *hapd, 580*a90b9d01SCy Schubert enum wpa_driver_if_type type, 581*a90b9d01SCy Schubert const char *ifname, u8 link_id) 582*a90b9d01SCy Schubert { 583*a90b9d01SCy Schubert if (!hapd->driver || !hapd->drv_priv || !hapd->driver->link_remove) 584*a90b9d01SCy Schubert return -1; 585*a90b9d01SCy Schubert 586*a90b9d01SCy Schubert return hapd->driver->link_remove(hapd->drv_priv, type, ifname, 587*a90b9d01SCy Schubert hapd->mld_link_id); 588*a90b9d01SCy Schubert } 589*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 590*a90b9d01SCy Schubert 591*a90b9d01SCy Schubert 592e28a4053SRui Paulo int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, 593e28a4053SRui Paulo const char *ifname) 594e28a4053SRui Paulo { 5955b9c547cSRui Paulo if (hapd->driver == NULL || hapd->drv_priv == NULL || 5965b9c547cSRui Paulo hapd->driver->if_remove == NULL) 597e28a4053SRui Paulo return -1; 598*a90b9d01SCy Schubert 599*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 600*a90b9d01SCy Schubert if (hapd->conf->mld_ap) 601*a90b9d01SCy Schubert return hostapd_if_link_remove(hapd, type, ifname, 602*a90b9d01SCy Schubert hapd->mld_link_id); 603*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 604*a90b9d01SCy Schubert 605e28a4053SRui Paulo return hapd->driver->if_remove(hapd->drv_priv, type, ifname); 606e28a4053SRui Paulo } 607e28a4053SRui Paulo 608e28a4053SRui Paulo 609e28a4053SRui Paulo int hostapd_set_ieee8021x(struct hostapd_data *hapd, 610e28a4053SRui Paulo struct wpa_bss_params *params) 611e28a4053SRui Paulo { 612e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) 613e28a4053SRui Paulo return 0; 614e28a4053SRui Paulo return hapd->driver->set_ieee8021x(hapd->drv_priv, params); 615e28a4053SRui Paulo } 616e28a4053SRui Paulo 617e28a4053SRui Paulo 618e28a4053SRui Paulo int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, 619*a90b9d01SCy Schubert const u8 *addr, int idx, int link_id, u8 *seq) 620e28a4053SRui Paulo { 621e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) 622e28a4053SRui Paulo return 0; 623e28a4053SRui Paulo return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, 624*a90b9d01SCy Schubert link_id, seq); 625e28a4053SRui Paulo } 626e28a4053SRui Paulo 627e28a4053SRui Paulo 628e28a4053SRui Paulo int hostapd_flush(struct hostapd_data *hapd) 629e28a4053SRui Paulo { 630*a90b9d01SCy Schubert int link_id = -1; 631*a90b9d01SCy Schubert 632e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->flush == NULL) 633e28a4053SRui Paulo return 0; 634*a90b9d01SCy Schubert 635*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 636*a90b9d01SCy Schubert if (hapd->conf && hapd->conf->mld_ap) 637*a90b9d01SCy Schubert link_id = hapd->mld_link_id; 638*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 639*a90b9d01SCy Schubert 640*a90b9d01SCy Schubert return hapd->driver->flush(hapd->drv_priv, link_id); 641e28a4053SRui Paulo } 642e28a4053SRui Paulo 643e28a4053SRui Paulo 6445b9c547cSRui Paulo int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, 645c1d255d3SCy Schubert int freq, int channel, int edmg, u8 edmg_channel, 646c1d255d3SCy Schubert int ht_enabled, int vht_enabled, 647*a90b9d01SCy Schubert int he_enabled, bool eht_enabled, 648206b73d0SCy Schubert int sec_channel_offset, int oper_chwidth, 6495b9c547cSRui Paulo int center_segment0, int center_segment1) 650e28a4053SRui Paulo { 651e28a4053SRui Paulo struct hostapd_freq_params data; 652206b73d0SCy Schubert struct hostapd_hw_modes *cmode = hapd->iface->current_mode; 6535b9c547cSRui Paulo 654c1d255d3SCy Schubert if (hostapd_set_freq_params(&data, mode, freq, channel, edmg, 655c1d255d3SCy Schubert edmg_channel, ht_enabled, 656*a90b9d01SCy Schubert vht_enabled, he_enabled, eht_enabled, 657*a90b9d01SCy Schubert sec_channel_offset, oper_chwidth, 6585b9c547cSRui Paulo center_segment0, center_segment1, 659206b73d0SCy Schubert cmode ? cmode->vht_capab : 0, 660206b73d0SCy Schubert cmode ? 661*a90b9d01SCy Schubert &cmode->he_capab[IEEE80211_MODE_AP] : NULL, 662*a90b9d01SCy Schubert cmode ? 663*a90b9d01SCy Schubert &cmode->eht_capab[IEEE80211_MODE_AP] : 664*a90b9d01SCy Schubert NULL, hostapd_get_punct_bitmap(hapd))) 6655b9c547cSRui Paulo return -1; 6665b9c547cSRui Paulo 667e28a4053SRui Paulo if (hapd->driver == NULL) 668e28a4053SRui Paulo return 0; 669e28a4053SRui Paulo if (hapd->driver->set_freq == NULL) 670e28a4053SRui Paulo return 0; 671*a90b9d01SCy Schubert 672*a90b9d01SCy Schubert data.link_id = -1; 673*a90b9d01SCy Schubert 674*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 675*a90b9d01SCy Schubert if (hapd->conf->mld_ap) { 676*a90b9d01SCy Schubert data.link_id = hapd->mld_link_id; 677*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, 678*a90b9d01SCy Schubert "hostapd_set_freq: link_id=%d", data.link_id); 679*a90b9d01SCy Schubert } 680*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 681*a90b9d01SCy Schubert 682e28a4053SRui Paulo return hapd->driver->set_freq(hapd->drv_priv, &data); 683e28a4053SRui Paulo } 684e28a4053SRui Paulo 685e28a4053SRui Paulo int hostapd_set_rts(struct hostapd_data *hapd, int rts) 686e28a4053SRui Paulo { 687e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_rts == NULL) 688e28a4053SRui Paulo return 0; 689e28a4053SRui Paulo return hapd->driver->set_rts(hapd->drv_priv, rts); 690e28a4053SRui Paulo } 691e28a4053SRui Paulo 692e28a4053SRui Paulo 693e28a4053SRui Paulo int hostapd_set_frag(struct hostapd_data *hapd, int frag) 694e28a4053SRui Paulo { 695e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_frag == NULL) 696e28a4053SRui Paulo return 0; 697e28a4053SRui Paulo return hapd->driver->set_frag(hapd->drv_priv, frag); 698e28a4053SRui Paulo } 699e28a4053SRui Paulo 700e28a4053SRui Paulo 701e28a4053SRui Paulo int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, 702e28a4053SRui Paulo int total_flags, int flags_or, int flags_and) 703e28a4053SRui Paulo { 704c1d255d3SCy Schubert if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags) 705e28a4053SRui Paulo return 0; 706e28a4053SRui Paulo return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, 707e28a4053SRui Paulo flags_or, flags_and); 708e28a4053SRui Paulo } 709e28a4053SRui Paulo 710e28a4053SRui Paulo 711206b73d0SCy Schubert int hostapd_sta_set_airtime_weight(struct hostapd_data *hapd, const u8 *addr, 712206b73d0SCy Schubert unsigned int weight) 713206b73d0SCy Schubert { 714206b73d0SCy Schubert if (!hapd->driver || !hapd->driver->sta_set_airtime_weight) 715206b73d0SCy Schubert return 0; 716206b73d0SCy Schubert return hapd->driver->sta_set_airtime_weight(hapd->drv_priv, addr, 717206b73d0SCy Schubert weight); 718206b73d0SCy Schubert } 719206b73d0SCy Schubert 720206b73d0SCy Schubert 721e28a4053SRui Paulo int hostapd_set_country(struct hostapd_data *hapd, const char *country) 722e28a4053SRui Paulo { 723e28a4053SRui Paulo if (hapd->driver == NULL || 724e28a4053SRui Paulo hapd->driver->set_country == NULL) 725e28a4053SRui Paulo return 0; 726e28a4053SRui Paulo return hapd->driver->set_country(hapd->drv_priv, country); 727e28a4053SRui Paulo } 728e28a4053SRui Paulo 729e28a4053SRui Paulo 730e28a4053SRui Paulo int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, 731e28a4053SRui Paulo int cw_min, int cw_max, int burst_time) 732e28a4053SRui Paulo { 733*a90b9d01SCy Schubert int link_id = -1; 734*a90b9d01SCy Schubert 735e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) 736e28a4053SRui Paulo return 0; 737*a90b9d01SCy Schubert 738*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 739*a90b9d01SCy Schubert if (hapd->conf->mld_ap) 740*a90b9d01SCy Schubert link_id = hapd->mld_link_id; 741*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 742*a90b9d01SCy Schubert 743e28a4053SRui Paulo return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, 744*a90b9d01SCy Schubert cw_min, cw_max, burst_time, 745*a90b9d01SCy Schubert link_id); 746e28a4053SRui Paulo } 747e28a4053SRui Paulo 748e28a4053SRui Paulo 749e28a4053SRui Paulo struct hostapd_hw_modes * 750e28a4053SRui Paulo hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, 75185732ac8SCy Schubert u16 *flags, u8 *dfs_domain) 752e28a4053SRui Paulo { 753*a90b9d01SCy Schubert if (!hapd->driver || !hapd->driver->get_hw_feature_data || 754*a90b9d01SCy Schubert !hapd->drv_priv) 755e28a4053SRui Paulo return NULL; 756e28a4053SRui Paulo return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, 75785732ac8SCy Schubert flags, dfs_domain); 758e28a4053SRui Paulo } 759e28a4053SRui Paulo 760e28a4053SRui Paulo 761e28a4053SRui Paulo int hostapd_driver_commit(struct hostapd_data *hapd) 762e28a4053SRui Paulo { 763e28a4053SRui Paulo if (hapd->driver == NULL || hapd->driver->commit == NULL) 764e28a4053SRui Paulo return 0; 765e28a4053SRui Paulo return hapd->driver->commit(hapd->drv_priv); 766e28a4053SRui Paulo } 767e28a4053SRui Paulo 768e28a4053SRui Paulo 769e28a4053SRui Paulo int hostapd_drv_none(struct hostapd_data *hapd) 770e28a4053SRui Paulo { 771e28a4053SRui Paulo return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; 772e28a4053SRui Paulo } 773e28a4053SRui Paulo 774e28a4053SRui Paulo 775c1d255d3SCy Schubert bool hostapd_drv_nl80211(struct hostapd_data *hapd) 776c1d255d3SCy Schubert { 777c1d255d3SCy Schubert return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0; 778c1d255d3SCy Schubert } 779c1d255d3SCy Schubert 780c1d255d3SCy Schubert 781e28a4053SRui Paulo int hostapd_driver_scan(struct hostapd_data *hapd, 782e28a4053SRui Paulo struct wpa_driver_scan_params *params) 783e28a4053SRui Paulo { 784e28a4053SRui Paulo if (hapd->driver && hapd->driver->scan2) 785e28a4053SRui Paulo return hapd->driver->scan2(hapd->drv_priv, params); 786e28a4053SRui Paulo return -1; 787e28a4053SRui Paulo } 788e28a4053SRui Paulo 789e28a4053SRui Paulo 790e28a4053SRui Paulo struct wpa_scan_results * hostapd_driver_get_scan_results( 791e28a4053SRui Paulo struct hostapd_data *hapd) 792e28a4053SRui Paulo { 793*a90b9d01SCy Schubert if (hapd->driver && hapd->driver->get_scan_results) 794*a90b9d01SCy Schubert return hapd->driver->get_scan_results(hapd->drv_priv, NULL); 795e28a4053SRui Paulo if (hapd->driver && hapd->driver->get_scan_results2) 796e28a4053SRui Paulo return hapd->driver->get_scan_results2(hapd->drv_priv); 797e28a4053SRui Paulo return NULL; 798e28a4053SRui Paulo } 799f05cddf9SRui Paulo 800f05cddf9SRui Paulo 801f05cddf9SRui Paulo int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, 802f05cddf9SRui Paulo int duration) 803f05cddf9SRui Paulo { 804f05cddf9SRui Paulo if (hapd->driver && hapd->driver->set_noa) 805f05cddf9SRui Paulo return hapd->driver->set_noa(hapd->drv_priv, count, start, 806f05cddf9SRui Paulo duration); 807f05cddf9SRui Paulo return -1; 808f05cddf9SRui Paulo } 809f05cddf9SRui Paulo 810f05cddf9SRui Paulo 811f05cddf9SRui Paulo int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, 812f05cddf9SRui Paulo enum wpa_alg alg, const u8 *addr, 813c1d255d3SCy Schubert int key_idx, int vlan_id, int set_tx, 814f05cddf9SRui Paulo const u8 *seq, size_t seq_len, 815c1d255d3SCy Schubert const u8 *key, size_t key_len, enum key_flag key_flag) 816f05cddf9SRui Paulo { 817c1d255d3SCy Schubert struct wpa_driver_set_key_params params; 818c1d255d3SCy Schubert 819f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->set_key == NULL) 820f05cddf9SRui Paulo return 0; 821c1d255d3SCy Schubert 822c1d255d3SCy Schubert os_memset(¶ms, 0, sizeof(params)); 823c1d255d3SCy Schubert params.ifname = ifname; 824c1d255d3SCy Schubert params.alg = alg; 825c1d255d3SCy Schubert params.addr = addr; 826c1d255d3SCy Schubert params.key_idx = key_idx; 827c1d255d3SCy Schubert params.set_tx = set_tx; 828c1d255d3SCy Schubert params.seq = seq; 829c1d255d3SCy Schubert params.seq_len = seq_len; 830c1d255d3SCy Schubert params.key = key; 831c1d255d3SCy Schubert params.key_len = key_len; 832c1d255d3SCy Schubert params.vlan_id = vlan_id; 833c1d255d3SCy Schubert params.key_flag = key_flag; 834*a90b9d01SCy Schubert params.link_id = -1; 835*a90b9d01SCy Schubert 836*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 837*a90b9d01SCy Schubert if (hapd->conf->mld_ap && !(key_flag & KEY_FLAG_PAIRWISE)) 838*a90b9d01SCy Schubert params.link_id = hapd->mld_link_id; 839*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 840c1d255d3SCy Schubert 841c1d255d3SCy Schubert return hapd->driver->set_key(hapd->drv_priv, ¶ms); 842f05cddf9SRui Paulo } 843f05cddf9SRui Paulo 844f05cddf9SRui Paulo 845f05cddf9SRui Paulo int hostapd_drv_send_mlme(struct hostapd_data *hapd, 846c1d255d3SCy Schubert const void *msg, size_t len, int noack, 847c1d255d3SCy Schubert const u16 *csa_offs, size_t csa_offs_len, 848c1d255d3SCy Schubert int no_encrypt) 849f05cddf9SRui Paulo { 850*a90b9d01SCy Schubert int link_id = -1; 851*a90b9d01SCy Schubert 852*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 853*a90b9d01SCy Schubert if (hapd->conf->mld_ap) 854*a90b9d01SCy Schubert link_id = hapd->mld_link_id; 855*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 856*a90b9d01SCy Schubert 857780fb4a2SCy Schubert if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) 858780fb4a2SCy Schubert return 0; 859780fb4a2SCy Schubert return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, 860*a90b9d01SCy Schubert csa_offs, csa_offs_len, no_encrypt, 0, 861*a90b9d01SCy Schubert link_id); 862f05cddf9SRui Paulo } 863f05cddf9SRui Paulo 864f05cddf9SRui Paulo 865f05cddf9SRui Paulo int hostapd_drv_sta_deauth(struct hostapd_data *hapd, 866f05cddf9SRui Paulo const u8 *addr, int reason) 867f05cddf9SRui Paulo { 868*a90b9d01SCy Schubert int link_id = -1; 869*a90b9d01SCy Schubert const u8 *own_addr = hapd->own_addr; 870*a90b9d01SCy Schubert 871*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 872*a90b9d01SCy Schubert if (hapd->conf->mld_ap) { 873*a90b9d01SCy Schubert struct sta_info *sta = ap_get_sta(hapd, addr); 874*a90b9d01SCy Schubert 875*a90b9d01SCy Schubert link_id = hapd->mld_link_id; 876*a90b9d01SCy Schubert if (ap_sta_is_mld(hapd, sta)) 877*a90b9d01SCy Schubert own_addr = hapd->mld->mld_addr; 878*a90b9d01SCy Schubert } 879*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 880*a90b9d01SCy Schubert 881780fb4a2SCy Schubert if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv) 882f05cddf9SRui Paulo return 0; 883*a90b9d01SCy Schubert return hapd->driver->sta_deauth(hapd->drv_priv, own_addr, addr, 884*a90b9d01SCy Schubert reason, link_id); 885f05cddf9SRui Paulo } 886f05cddf9SRui Paulo 887f05cddf9SRui Paulo 888f05cddf9SRui Paulo int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, 889f05cddf9SRui Paulo const u8 *addr, int reason) 890f05cddf9SRui Paulo { 891*a90b9d01SCy Schubert const u8 *own_addr = hapd->own_addr; 892*a90b9d01SCy Schubert 893*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 894*a90b9d01SCy Schubert if (hapd->conf->mld_ap) { 895*a90b9d01SCy Schubert struct sta_info *sta = ap_get_sta(hapd, addr); 896*a90b9d01SCy Schubert 897*a90b9d01SCy Schubert if (ap_sta_is_mld(hapd, sta)) 898*a90b9d01SCy Schubert own_addr = hapd->mld->mld_addr; 899*a90b9d01SCy Schubert } 900*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 901*a90b9d01SCy Schubert 902780fb4a2SCy Schubert if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv) 903f05cddf9SRui Paulo return 0; 904*a90b9d01SCy Schubert return hapd->driver->sta_disassoc(hapd->drv_priv, own_addr, addr, 905f05cddf9SRui Paulo reason); 906f05cddf9SRui Paulo } 907f05cddf9SRui Paulo 908f05cddf9SRui Paulo 909f05cddf9SRui Paulo int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, 910f05cddf9SRui Paulo const u8 *peer, u8 *buf, u16 *buf_len) 911f05cddf9SRui Paulo { 912f05cddf9SRui Paulo if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) 9135b9c547cSRui Paulo return -1; 914f05cddf9SRui Paulo return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, 915f05cddf9SRui Paulo buf_len); 916f05cddf9SRui Paulo } 917f05cddf9SRui Paulo 918f05cddf9SRui Paulo 919*a90b9d01SCy Schubert static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, 920*a90b9d01SCy Schubert unsigned int wait, const u8 *dst, 921*a90b9d01SCy Schubert const u8 *data, size_t len, bool addr3_ap) 922f05cddf9SRui Paulo { 923*a90b9d01SCy Schubert const u8 *own_addr = hapd->own_addr; 924780fb4a2SCy Schubert const u8 *bssid; 925780fb4a2SCy Schubert const u8 wildcard_bssid[ETH_ALEN] = { 926780fb4a2SCy Schubert 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 927780fb4a2SCy Schubert }; 928*a90b9d01SCy Schubert struct sta_info *sta; 929780fb4a2SCy Schubert 930780fb4a2SCy Schubert if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv) 931780fb4a2SCy Schubert return 0; 932780fb4a2SCy Schubert bssid = hapd->own_addr; 933*a90b9d01SCy Schubert if (!addr3_ap && !is_multicast_ether_addr(dst) && 934780fb4a2SCy Schubert len > 0 && data[0] == WLAN_ACTION_PUBLIC) { 935780fb4a2SCy Schubert /* 936780fb4a2SCy Schubert * Public Action frames to a STA that is not a member of the BSS 937780fb4a2SCy Schubert * shall use wildcard BSSID value. 938780fb4a2SCy Schubert */ 939780fb4a2SCy Schubert sta = ap_get_sta(hapd, dst); 940780fb4a2SCy Schubert if (!sta || !(sta->flags & WLAN_STA_ASSOC)) 941780fb4a2SCy Schubert bssid = wildcard_bssid; 942*a90b9d01SCy Schubert } else if (!addr3_ap && is_broadcast_ether_addr(dst) && 94385732ac8SCy Schubert len > 0 && data[0] == WLAN_ACTION_PUBLIC) { 94485732ac8SCy Schubert /* 94585732ac8SCy Schubert * The only current use case of Public Action frames with 94685732ac8SCy Schubert * broadcast destination address is DPP PKEX. That case is 94785732ac8SCy Schubert * directing all devices and not just the STAs within the BSS, 94885732ac8SCy Schubert * so have to use the wildcard BSSID value. 94985732ac8SCy Schubert */ 95085732ac8SCy Schubert bssid = wildcard_bssid; 951*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 952*a90b9d01SCy Schubert } else if (hapd->conf->mld_ap) { 953*a90b9d01SCy Schubert sta = ap_get_sta(hapd, dst); 954*a90b9d01SCy Schubert 955*a90b9d01SCy Schubert if (ap_sta_is_mld(hapd, sta)) { 956*a90b9d01SCy Schubert own_addr = hapd->mld->mld_addr; 957*a90b9d01SCy Schubert bssid = own_addr; 958780fb4a2SCy Schubert } 959*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 960*a90b9d01SCy Schubert } 961*a90b9d01SCy Schubert 962780fb4a2SCy Schubert return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, 963*a90b9d01SCy Schubert own_addr, bssid, data, len, 0); 964*a90b9d01SCy Schubert } 965*a90b9d01SCy Schubert 966*a90b9d01SCy Schubert 967*a90b9d01SCy Schubert int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, 968*a90b9d01SCy Schubert unsigned int wait, const u8 *dst, const u8 *data, 969*a90b9d01SCy Schubert size_t len) 970*a90b9d01SCy Schubert { 971*a90b9d01SCy Schubert return hapd_drv_send_action(hapd, freq, wait, dst, data, len, false); 972780fb4a2SCy Schubert } 973780fb4a2SCy Schubert 974780fb4a2SCy Schubert 975780fb4a2SCy Schubert int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd, 976780fb4a2SCy Schubert unsigned int freq, 977780fb4a2SCy Schubert unsigned int wait, const u8 *dst, 978780fb4a2SCy Schubert const u8 *data, size_t len) 979780fb4a2SCy Schubert { 980*a90b9d01SCy Schubert return hapd_drv_send_action(hapd, freq, wait, dst, data, len, true); 981f05cddf9SRui Paulo } 9825b9c547cSRui Paulo 9835b9c547cSRui Paulo 9845b9c547cSRui Paulo int hostapd_start_dfs_cac(struct hostapd_iface *iface, 9855b9c547cSRui Paulo enum hostapd_hw_mode mode, int freq, 9865b9c547cSRui Paulo int channel, int ht_enabled, int vht_enabled, 987*a90b9d01SCy Schubert int he_enabled, bool eht_enabled, 988206b73d0SCy Schubert int sec_channel_offset, int oper_chwidth, 989*a90b9d01SCy Schubert int center_segment0, int center_segment1, 990*a90b9d01SCy Schubert bool radar_background) 9915b9c547cSRui Paulo { 9925b9c547cSRui Paulo struct hostapd_data *hapd = iface->bss[0]; 9935b9c547cSRui Paulo struct hostapd_freq_params data; 9945b9c547cSRui Paulo int res; 995206b73d0SCy Schubert struct hostapd_hw_modes *cmode = iface->current_mode; 9965b9c547cSRui Paulo 997206b73d0SCy Schubert if (!hapd->driver || !hapd->driver->start_dfs_cac || !cmode) 9985b9c547cSRui Paulo return 0; 9995b9c547cSRui Paulo 10005b9c547cSRui Paulo if (!iface->conf->ieee80211h) { 10015b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " 10025b9c547cSRui Paulo "is not enabled"); 10035b9c547cSRui Paulo return -1; 10045b9c547cSRui Paulo } 10055b9c547cSRui Paulo 1006c1d255d3SCy Schubert if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0, 1007c1d255d3SCy Schubert ht_enabled, 1008*a90b9d01SCy Schubert vht_enabled, he_enabled, eht_enabled, 1009*a90b9d01SCy Schubert sec_channel_offset, 1010206b73d0SCy Schubert oper_chwidth, center_segment0, 10115b9c547cSRui Paulo center_segment1, 1012206b73d0SCy Schubert cmode->vht_capab, 1013*a90b9d01SCy Schubert &cmode->he_capab[IEEE80211_MODE_AP], 1014*a90b9d01SCy Schubert &cmode->eht_capab[IEEE80211_MODE_AP], 1015*a90b9d01SCy Schubert hostapd_get_punct_bitmap(hapd))) { 10165b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Can't set freq params"); 10175b9c547cSRui Paulo return -1; 10185b9c547cSRui Paulo } 1019*a90b9d01SCy Schubert data.radar_background = radar_background; 10205b9c547cSRui Paulo 10215b9c547cSRui Paulo res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); 10225b9c547cSRui Paulo if (!res) { 1023*a90b9d01SCy Schubert if (radar_background) 1024*a90b9d01SCy Schubert iface->radar_background.cac_started = 1; 1025*a90b9d01SCy Schubert else 10265b9c547cSRui Paulo iface->cac_started = 1; 10275b9c547cSRui Paulo os_get_reltime(&iface->dfs_cac_start); 10285b9c547cSRui Paulo } 10295b9c547cSRui Paulo 10305b9c547cSRui Paulo return res; 10315b9c547cSRui Paulo } 10325b9c547cSRui Paulo 10335b9c547cSRui Paulo 10345b9c547cSRui Paulo int hostapd_drv_set_qos_map(struct hostapd_data *hapd, 10355b9c547cSRui Paulo const u8 *qos_map_set, u8 qos_map_set_len) 10365b9c547cSRui Paulo { 1037*a90b9d01SCy Schubert if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv || 1038*a90b9d01SCy Schubert !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)) 10395b9c547cSRui Paulo return 0; 10405b9c547cSRui Paulo return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, 10415b9c547cSRui Paulo qos_map_set_len); 10425b9c547cSRui Paulo } 10435b9c547cSRui Paulo 10445b9c547cSRui Paulo 1045*a90b9d01SCy Schubert void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, 1046325151a3SRui Paulo struct hostapd_hw_modes *mode, 1047*a90b9d01SCy Schubert int acs_ch_list_all, bool allow_disabled, 1048325151a3SRui Paulo int **freq_list) 1049325151a3SRui Paulo { 1050325151a3SRui Paulo int i; 1051*a90b9d01SCy Schubert bool is_no_ir = false; 1052325151a3SRui Paulo 1053325151a3SRui Paulo for (i = 0; i < mode->num_channels; i++) { 1054325151a3SRui Paulo struct hostapd_channel_data *chan = &mode->channels[i]; 1055325151a3SRui Paulo 1056c1d255d3SCy Schubert if (!acs_ch_list_all && 1057c1d255d3SCy Schubert (hapd->iface->conf->acs_freq_list.num && 1058c1d255d3SCy Schubert !freq_range_list_includes( 1059c1d255d3SCy Schubert &hapd->iface->conf->acs_freq_list, 1060c1d255d3SCy Schubert chan->freq))) 1061c1d255d3SCy Schubert continue; 1062c1d255d3SCy Schubert if (!acs_ch_list_all && 1063c1d255d3SCy Schubert (!hapd->iface->conf->acs_freq_list_present && 1064c1d255d3SCy Schubert hapd->iface->conf->acs_ch_list.num && 1065c1d255d3SCy Schubert !freq_range_list_includes( 1066c1d255d3SCy Schubert &hapd->iface->conf->acs_ch_list, 1067c1d255d3SCy Schubert chan->chan))) 1068c1d255d3SCy Schubert continue; 1069c1d255d3SCy Schubert if (is_6ghz_freq(chan->freq) && 1070*a90b9d01SCy Schubert ((hapd->iface->conf->acs_exclude_6ghz_non_psc && 1071*a90b9d01SCy Schubert !is_6ghz_psc_frequency(chan->freq)) || 1072*a90b9d01SCy Schubert (!hapd->iface->conf->ieee80211ax && 1073*a90b9d01SCy Schubert !hapd->iface->conf->ieee80211be))) 1074c1d255d3SCy Schubert continue; 1075*a90b9d01SCy Schubert if ((!(chan->flag & HOSTAPD_CHAN_DISABLED) || allow_disabled) && 107685732ac8SCy Schubert !(hapd->iface->conf->acs_exclude_dfs && 107732a95656SCy Schubert (chan->flag & HOSTAPD_CHAN_RADAR)) && 107832a95656SCy Schubert !(chan->max_tx_power < hapd->iface->conf->min_tx_power)) 1079325151a3SRui Paulo int_array_add_unique(freq_list, chan->freq); 1080*a90b9d01SCy Schubert else if ((chan->flag & HOSTAPD_CHAN_NO_IR) && 1081*a90b9d01SCy Schubert is_6ghz_freq(chan->freq)) 1082*a90b9d01SCy Schubert is_no_ir = true; 1083325151a3SRui Paulo } 1084*a90b9d01SCy Schubert 1085*a90b9d01SCy Schubert hapd->iface->is_no_ir = is_no_ir; 1086325151a3SRui Paulo } 1087325151a3SRui Paulo 1088325151a3SRui Paulo 1089780fb4a2SCy Schubert void hostapd_get_ext_capa(struct hostapd_iface *iface) 1090780fb4a2SCy Schubert { 1091780fb4a2SCy Schubert struct hostapd_data *hapd = iface->bss[0]; 1092780fb4a2SCy Schubert 1093780fb4a2SCy Schubert if (!hapd->driver || !hapd->driver->get_ext_capab) 1094780fb4a2SCy Schubert return; 1095780fb4a2SCy Schubert 1096780fb4a2SCy Schubert hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS, 1097780fb4a2SCy Schubert &iface->extended_capa, 1098780fb4a2SCy Schubert &iface->extended_capa_mask, 1099780fb4a2SCy Schubert &iface->extended_capa_len); 1100780fb4a2SCy Schubert } 1101780fb4a2SCy Schubert 1102780fb4a2SCy Schubert 1103*a90b9d01SCy Schubert void hostapd_get_mld_capa(struct hostapd_iface *iface) 1104*a90b9d01SCy Schubert { 1105*a90b9d01SCy Schubert struct hostapd_data *hapd = iface->bss[0]; 1106*a90b9d01SCy Schubert 1107*a90b9d01SCy Schubert if (!hapd->driver || !hapd->driver->get_mld_capab) 1108*a90b9d01SCy Schubert return; 1109*a90b9d01SCy Schubert 1110*a90b9d01SCy Schubert hapd->driver->get_mld_capab(hapd->drv_priv, WPA_IF_AP_BSS, 1111*a90b9d01SCy Schubert &iface->mld_eml_capa, 1112*a90b9d01SCy Schubert &iface->mld_mld_capa); 1113*a90b9d01SCy Schubert } 1114*a90b9d01SCy Schubert 1115*a90b9d01SCy Schubert 1116*a90b9d01SCy Schubert /** 1117*a90b9d01SCy Schubert * hostapd_drv_do_acs - Start automatic channel selection 1118*a90b9d01SCy Schubert * @hapd: BSS data for the device initiating ACS 1119*a90b9d01SCy Schubert * Returns: 0 on success, -1 on failure, 1 on failure due to NO_IR (AFC) 1120*a90b9d01SCy Schubert */ 11215b9c547cSRui Paulo int hostapd_drv_do_acs(struct hostapd_data *hapd) 11225b9c547cSRui Paulo { 11235b9c547cSRui Paulo struct drv_acs_params params; 1124325151a3SRui Paulo int ret, i, acs_ch_list_all = 0; 1125325151a3SRui Paulo struct hostapd_hw_modes *mode; 1126325151a3SRui Paulo int *freq_list = NULL; 1127c1d255d3SCy Schubert enum hostapd_hw_mode selected_mode; 11285b9c547cSRui Paulo 11295b9c547cSRui Paulo if (hapd->driver == NULL || hapd->driver->do_acs == NULL) 11305b9c547cSRui Paulo return 0; 1131325151a3SRui Paulo 11325b9c547cSRui Paulo os_memset(¶ms, 0, sizeof(params)); 11335b9c547cSRui Paulo params.hw_mode = hapd->iface->conf->hw_mode; 1134*a90b9d01SCy Schubert params.link_id = -1; 1135*a90b9d01SCy Schubert #ifdef CONFIG_IEEE80211BE 1136*a90b9d01SCy Schubert if (hapd->conf->mld_ap && hapd->iconf->ieee80211be && 1137*a90b9d01SCy Schubert !hapd->conf->disable_11be) 1138*a90b9d01SCy Schubert params.link_id = hapd->mld_link_id; 1139*a90b9d01SCy Schubert #endif /* CONFIG_IEEE80211BE */ 1140325151a3SRui Paulo 1141325151a3SRui Paulo /* 1142325151a3SRui Paulo * If no chanlist config parameter is provided, include all enabled 1143325151a3SRui Paulo * channels of the selected hw_mode. 1144325151a3SRui Paulo */ 1145c1d255d3SCy Schubert if (hapd->iface->conf->acs_freq_list_present) 1146c1d255d3SCy Schubert acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num; 1147c1d255d3SCy Schubert else 1148c1d255d3SCy Schubert acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num; 1149325151a3SRui Paulo 1150c1d255d3SCy Schubert if (hapd->iface->current_mode) 1151c1d255d3SCy Schubert selected_mode = hapd->iface->current_mode->mode; 1152c1d255d3SCy Schubert else 1153c1d255d3SCy Schubert selected_mode = HOSTAPD_MODE_IEEE80211ANY; 1154325151a3SRui Paulo 1155325151a3SRui Paulo for (i = 0; i < hapd->iface->num_hw_features; i++) { 1156325151a3SRui Paulo mode = &hapd->iface->hw_features[i]; 1157c1d255d3SCy Schubert if (selected_mode != HOSTAPD_MODE_IEEE80211ANY && 1158c1d255d3SCy Schubert selected_mode != mode->mode) 1159c1d255d3SCy Schubert continue; 1160c1d255d3SCy Schubert hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all, 1161*a90b9d01SCy Schubert false, &freq_list); 1162*a90b9d01SCy Schubert } 1163*a90b9d01SCy Schubert 1164*a90b9d01SCy Schubert if (!freq_list && hapd->iface->is_no_ir) { 1165*a90b9d01SCy Schubert wpa_printf(MSG_ERROR, 1166*a90b9d01SCy Schubert "NO_IR: Interface freq_list is empty. Failing do_acs."); 1167*a90b9d01SCy Schubert return 1; 1168325151a3SRui Paulo } 1169325151a3SRui Paulo 1170325151a3SRui Paulo params.freq_list = freq_list; 1171c1d255d3SCy Schubert params.edmg_enabled = hapd->iface->conf->enable_edmg; 1172325151a3SRui Paulo 11735b9c547cSRui Paulo params.ht_enabled = !!(hapd->iface->conf->ieee80211n); 11745b9c547cSRui Paulo params.ht40_enabled = !!(hapd->iface->conf->ht_capab & 11755b9c547cSRui Paulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); 1176325151a3SRui Paulo params.vht_enabled = !!(hapd->iface->conf->ieee80211ac); 1177*a90b9d01SCy Schubert params.eht_enabled = !!(hapd->iface->conf->ieee80211be); 1178325151a3SRui Paulo params.ch_width = 20; 1179325151a3SRui Paulo if (hapd->iface->conf->ieee80211n && params.ht40_enabled) 1180325151a3SRui Paulo params.ch_width = 40; 1181325151a3SRui Paulo 1182206b73d0SCy Schubert /* Note: VHT20 is defined by combination of ht_capab & oper_chwidth 1183325151a3SRui Paulo */ 1184*a90b9d01SCy Schubert if ((hapd->iface->conf->ieee80211be || 1185*a90b9d01SCy Schubert hapd->iface->conf->ieee80211ax || 1186206b73d0SCy Schubert hapd->iface->conf->ieee80211ac) && 1187206b73d0SCy Schubert params.ht40_enabled) { 1188*a90b9d01SCy Schubert enum oper_chan_width oper_chwidth; 1189206b73d0SCy Schubert 1190*a90b9d01SCy Schubert oper_chwidth = hostapd_get_oper_chwidth(hapd->iface->conf); 1191*a90b9d01SCy Schubert if (oper_chwidth == CONF_OPER_CHWIDTH_80MHZ) 1192325151a3SRui Paulo params.ch_width = 80; 1193*a90b9d01SCy Schubert else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ || 1194*a90b9d01SCy Schubert oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) 1195325151a3SRui Paulo params.ch_width = 160; 1196*a90b9d01SCy Schubert else if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ) 1197*a90b9d01SCy Schubert params.ch_width = 320; 1198325151a3SRui Paulo } 1199325151a3SRui Paulo 1200c1d255d3SCy Schubert if (hapd->iface->conf->op_class) 1201c1d255d3SCy Schubert params.ch_width = op_class_to_bandwidth( 1202c1d255d3SCy Schubert hapd->iface->conf->op_class); 1203325151a3SRui Paulo ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms); 1204c1d255d3SCy Schubert os_free(freq_list); 1205325151a3SRui Paulo 1206325151a3SRui Paulo return ret; 12075b9c547cSRui Paulo } 1208206b73d0SCy Schubert 1209206b73d0SCy Schubert 1210206b73d0SCy Schubert int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, 1211206b73d0SCy Schubert u16 reason_code, const u8 *ie, size_t ielen) 1212206b73d0SCy Schubert { 1213206b73d0SCy Schubert if (!hapd->driver || !hapd->driver->update_dh_ie || !hapd->drv_priv) 1214206b73d0SCy Schubert return 0; 1215206b73d0SCy Schubert return hapd->driver->update_dh_ie(hapd->drv_priv, peer, reason_code, 1216206b73d0SCy Schubert ie, ielen); 1217206b73d0SCy Schubert } 1218c1d255d3SCy Schubert 1219c1d255d3SCy Schubert 1220c1d255d3SCy Schubert int hostapd_drv_dpp_listen(struct hostapd_data *hapd, bool enable) 1221c1d255d3SCy Schubert { 1222c1d255d3SCy Schubert if (!hapd->driver || !hapd->driver->dpp_listen || !hapd->drv_priv) 1223c1d255d3SCy Schubert return 0; 1224c1d255d3SCy Schubert return hapd->driver->dpp_listen(hapd->drv_priv, enable); 1225c1d255d3SCy Schubert } 1226*a90b9d01SCy Schubert 1227*a90b9d01SCy Schubert 1228*a90b9d01SCy Schubert #ifdef CONFIG_PASN 1229*a90b9d01SCy Schubert int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd, 1230*a90b9d01SCy Schubert const u8 *own_addr, const u8 *peer_addr, 1231*a90b9d01SCy Schubert u32 cipher, u8 tk_len, const u8 *tk, 1232*a90b9d01SCy Schubert u8 ltf_keyseed_len, 1233*a90b9d01SCy Schubert const u8 *ltf_keyseed, u32 action) 1234*a90b9d01SCy Schubert { 1235*a90b9d01SCy Schubert struct secure_ranging_params params; 1236*a90b9d01SCy Schubert 1237*a90b9d01SCy Schubert if (!hapd->driver || !hapd->driver->set_secure_ranging_ctx) 1238*a90b9d01SCy Schubert return 0; 1239*a90b9d01SCy Schubert 1240*a90b9d01SCy Schubert os_memset(¶ms, 0, sizeof(params)); 1241*a90b9d01SCy Schubert params.own_addr = own_addr; 1242*a90b9d01SCy Schubert params.peer_addr = peer_addr; 1243*a90b9d01SCy Schubert params.cipher = cipher; 1244*a90b9d01SCy Schubert params.tk_len = tk_len; 1245*a90b9d01SCy Schubert params.tk = tk; 1246*a90b9d01SCy Schubert params.ltf_keyseed_len = ltf_keyseed_len; 1247*a90b9d01SCy Schubert params.ltf_keyseed = ltf_keyseed; 1248*a90b9d01SCy Schubert params.action = action; 1249*a90b9d01SCy Schubert 1250*a90b9d01SCy Schubert return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms); 1251*a90b9d01SCy Schubert } 1252*a90b9d01SCy Schubert #endif /* CONFIG_PASN */ 1253