Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd - Driver operations
      3  * Copyright (c) 2009-2010, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 
     11 #include "utils/common.h"
     12 #include "common/ieee802_11_defs.h"
     13 #include "common/hw_features_common.h"
     14 #include "wps/wps.h"
     15 #include "p2p/p2p.h"
     16 #include "hostapd.h"
     17 #include "ieee802_11.h"
     18 #include "sta_info.h"
     19 #include "ap_config.h"
     20 #include "p2p_hostapd.h"
     21 #include "hs20.h"
     22 #include "wpa_auth.h"
     23 #include "ap_drv_ops.h"
     24 
     25 
     26 u32 hostapd_sta_flags_to_drv(u32 flags)
     27 {
     28 	int res = 0;
     29 	if (flags & WLAN_STA_AUTHORIZED)
     30 		res |= WPA_STA_AUTHORIZED;
     31 	if (flags & WLAN_STA_WMM)
     32 		res |= WPA_STA_WMM;
     33 	if (flags & WLAN_STA_SHORT_PREAMBLE)
     34 		res |= WPA_STA_SHORT_PREAMBLE;
     35 	if (flags & WLAN_STA_MFP)
     36 		res |= WPA_STA_MFP;
     37 	if (flags & WLAN_STA_AUTH)
     38 		res |= WPA_STA_AUTHENTICATED;
     39 	if (flags & WLAN_STA_ASSOC)
     40 		res |= WPA_STA_ASSOCIATED;
     41 	return res;
     42 }
     43 
     44 
     45 static int add_buf(struct wpabuf **dst, const struct wpabuf *src)
     46 {
     47 	if (!src)
     48 		return 0;
     49 	if (wpabuf_resize(dst, wpabuf_len(src)) != 0)
     50 		return -1;
     51 	wpabuf_put_buf(*dst, src);
     52 	return 0;
     53 }
     54 
     55 
     56 static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len)
     57 {
     58 	if (!data || !len)
     59 		return 0;
     60 	if (wpabuf_resize(dst, len) != 0)
     61 		return -1;
     62 	wpabuf_put_data(*dst, data, len);
     63 	return 0;
     64 }
     65 
     66 
     67 int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
     68 			       struct wpabuf **beacon_ret,
     69 			       struct wpabuf **proberesp_ret,
     70 			       struct wpabuf **assocresp_ret)
     71 {
     72 	struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
     73 	u8 buf[200], *pos;
     74 
     75 	*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
     76 
     77 	pos = buf;
     78 	pos = hostapd_eid_time_adv(hapd, pos);
     79 	if (add_buf_data(&beacon, buf, pos - buf) < 0)
     80 		goto fail;
     81 	pos = hostapd_eid_time_zone(hapd, pos);
     82 	if (add_buf_data(&proberesp, buf, pos - buf) < 0)
     83 		goto fail;
     84 
     85 	pos = buf;
     86 	pos = hostapd_eid_ext_capab(hapd, pos);
     87 	if (add_buf_data(&assocresp, buf, pos - buf) < 0)
     88 		goto fail;
     89 	pos = hostapd_eid_interworking(hapd, pos);
     90 	pos = hostapd_eid_adv_proto(hapd, pos);
     91 	pos = hostapd_eid_roaming_consortium(hapd, pos);
     92 	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
     93 	    add_buf_data(&proberesp, buf, pos - buf) < 0)
     94 		goto fail;
     95 
     96 #ifdef CONFIG_FST
     97 	if (add_buf(&beacon, hapd->iface->fst_ies) < 0 ||
     98 	    add_buf(&proberesp, hapd->iface->fst_ies) < 0 ||
     99 	    add_buf(&assocresp, hapd->iface->fst_ies) < 0)
    100 		goto fail;
    101 #endif /* CONFIG_FST */
    102 
    103 #ifdef CONFIG_FILS
    104 	pos = hostapd_eid_fils_indic(hapd, buf, 0);
    105 	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
    106 	    add_buf_data(&proberesp, buf, pos - buf) < 0)
    107 		goto fail;
    108 #endif /* CONFIG_FILS */
    109 
    110 	if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
    111 	    add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
    112 		goto fail;
    113 
    114 #ifdef CONFIG_P2P
    115 	if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 ||
    116 	    add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0)
    117 		goto fail;
    118 #endif /* CONFIG_P2P */
    119 
    120 #ifdef CONFIG_P2P_MANAGER
    121 	if (hapd->conf->p2p & P2P_MANAGE) {
    122 		if (wpabuf_resize(&beacon, 100) == 0) {
    123 			u8 *start, *p;
    124 			start = wpabuf_put(beacon, 0);
    125 			p = hostapd_eid_p2p_manage(hapd, start);
    126 			wpabuf_put(beacon, p - start);
    127 		}
    128 
    129 		if (wpabuf_resize(&proberesp, 100) == 0) {
    130 			u8 *start, *p;
    131 			start = wpabuf_put(proberesp, 0);
    132 			p = hostapd_eid_p2p_manage(hapd, start);
    133 			wpabuf_put(proberesp, p - start);
    134 		}
    135 	}
    136 #endif /* CONFIG_P2P_MANAGER */
    137 
    138 #ifdef CONFIG_WPS
    139 	if (hapd->conf->wps_state) {
    140 		struct wpabuf *a = wps_build_assoc_resp_ie();
    141 		add_buf(&assocresp, a);
    142 		wpabuf_free(a);
    143 	}
    144 #endif /* CONFIG_WPS */
    145 
    146 #ifdef CONFIG_P2P_MANAGER
    147 	if (hapd->conf->p2p & P2P_MANAGE) {
    148 		if (wpabuf_resize(&assocresp, 100) == 0) {
    149 			u8 *start, *p;
    150 			start = wpabuf_put(assocresp, 0);
    151 			p = hostapd_eid_p2p_manage(hapd, start);
    152 			wpabuf_put(assocresp, p - start);
    153 		}
    154 	}
    155 #endif /* CONFIG_P2P_MANAGER */
    156 
    157 #ifdef CONFIG_WIFI_DISPLAY
    158 	if (hapd->p2p_group) {
    159 		struct wpabuf *a;
    160 		a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
    161 		add_buf(&assocresp, a);
    162 		wpabuf_free(a);
    163 	}
    164 #endif /* CONFIG_WIFI_DISPLAY */
    165 
    166 #ifdef CONFIG_HS20
    167 	pos = hostapd_eid_hs20_indication(hapd, buf);
    168 	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
    169 	    add_buf_data(&proberesp, buf, pos - buf) < 0)
    170 		goto fail;
    171 
    172 	pos = hostapd_eid_osen(hapd, buf);
    173 	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
    174 	    add_buf_data(&proberesp, buf, pos - buf) < 0)
    175 		goto fail;
    176 #endif /* CONFIG_HS20 */
    177 
    178 #ifdef CONFIG_MBO
    179 	if (hapd->conf->mbo_enabled ||
    180 	    OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
    181 		pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
    182 		if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
    183 		    add_buf_data(&proberesp, buf, pos - buf) < 0 ||
    184 		    add_buf_data(&assocresp, buf, pos - buf) < 0)
    185 			goto fail;
    186 	}
    187 #endif /* CONFIG_MBO */
    188 
    189 #ifdef CONFIG_OWE
    190 	pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf));
    191 	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
    192 	    add_buf_data(&proberesp, buf, pos - buf) < 0)
    193 		goto fail;
    194 #endif /* CONFIG_OWE */
    195 
    196 	add_buf(&beacon, hapd->conf->vendor_elements);
    197 	add_buf(&proberesp, hapd->conf->vendor_elements);
    198 	add_buf(&assocresp, hapd->conf->assocresp_elements);
    199 
    200 	*beacon_ret = beacon;
    201 	*proberesp_ret = proberesp;
    202 	*assocresp_ret = assocresp;
    203 
    204 	return 0;
    205 
    206 fail:
    207 	wpabuf_free(beacon);
    208 	wpabuf_free(proberesp);
    209 	wpabuf_free(assocresp);
    210 	return -1;
    211 }
    212 
    213 
    214 void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
    215 			       struct wpabuf *beacon,
    216 			       struct wpabuf *proberesp,
    217 			       struct wpabuf *assocresp)
    218 {
    219 	wpabuf_free(beacon);
    220 	wpabuf_free(proberesp);
    221 	wpabuf_free(assocresp);
    222 }
    223 
    224 
    225 int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd)
    226 {
    227 	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
    228 		return 0;
    229 
    230 	return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL);
    231 }
    232 
    233 
    234 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
    235 {
    236 	struct wpabuf *beacon, *proberesp, *assocresp;
    237 	int ret;
    238 
    239 	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
    240 		return 0;
    241 
    242 	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
    243 	    0)
    244 		return -1;
    245 
    246 	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
    247 					  assocresp);
    248 
    249 	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
    250 
    251 	return ret;
    252 }
    253 
    254 
    255 int hostapd_set_authorized(struct hostapd_data *hapd,
    256 			   struct sta_info *sta, int authorized)
    257 {
    258 	if (authorized) {
    259 		return hostapd_sta_set_flags(hapd, sta->addr,
    260 					     hostapd_sta_flags_to_drv(
    261 						     sta->flags),
    262 					     WPA_STA_AUTHORIZED, ~0);
    263 	}
    264 
    265 	return hostapd_sta_set_flags(hapd, sta->addr,
    266 				     hostapd_sta_flags_to_drv(sta->flags),
    267 				     0, ~WPA_STA_AUTHORIZED);
    268 }
    269 
    270 
    271 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
    272 {
    273 	int set_flags, total_flags, flags_and, flags_or;
    274 	total_flags = hostapd_sta_flags_to_drv(sta->flags);
    275 	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
    276 	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
    277 	     sta->auth_alg == WLAN_AUTH_FT) &&
    278 	    sta->flags & WLAN_STA_AUTHORIZED)
    279 		set_flags |= WPA_STA_AUTHORIZED;
    280 	flags_or = total_flags & set_flags;
    281 	flags_and = total_flags | ~set_flags;
    282 	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
    283 				     flags_or, flags_and);
    284 }
    285 
    286 
    287 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
    288 			      int enabled)
    289 {
    290 	struct wpa_bss_params params;
    291 	os_memset(&params, 0, sizeof(params));
    292 	params.ifname = ifname;
    293 	params.enabled = enabled;
    294 	if (enabled) {
    295 		params.wpa = hapd->conf->wpa;
    296 		params.ieee802_1x = hapd->conf->ieee802_1x;
    297 		params.wpa_group = hapd->conf->wpa_group;
    298 		if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
    299 		    (WPA_PROTO_WPA | WPA_PROTO_RSN))
    300 			params.wpa_pairwise = hapd->conf->wpa_pairwise |
    301 				hapd->conf->rsn_pairwise;
    302 		else if (hapd->conf->wpa & WPA_PROTO_RSN)
    303 			params.wpa_pairwise = hapd->conf->rsn_pairwise;
    304 		else if (hapd->conf->wpa & WPA_PROTO_WPA)
    305 			params.wpa_pairwise = hapd->conf->wpa_pairwise;
    306 		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
    307 		params.rsn_preauth = hapd->conf->rsn_preauth;
    308 #ifdef CONFIG_IEEE80211W
    309 		params.ieee80211w = hapd->conf->ieee80211w;
    310 #endif /* CONFIG_IEEE80211W */
    311 	}
    312 	return hostapd_set_ieee8021x(hapd, &params);
    313 }
    314 
    315 
    316 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
    317 {
    318 	char force_ifname[IFNAMSIZ];
    319 	u8 if_addr[ETH_ALEN];
    320 	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
    321 			      NULL, NULL, force_ifname, if_addr, NULL, 0);
    322 }
    323 
    324 
    325 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
    326 {
    327 	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
    328 }
    329 
    330 
    331 int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
    332 			const u8 *addr, int aid, int val)
    333 {
    334 	const char *bridge = NULL;
    335 
    336 	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
    337 		return -1;
    338 	if (hapd->conf->wds_bridge[0])
    339 		bridge = hapd->conf->wds_bridge;
    340 	else if (hapd->conf->bridge[0])
    341 		bridge = hapd->conf->bridge;
    342 	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
    343 					 bridge, ifname_wds);
    344 }
    345 
    346 
    347 int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
    348 			 u16 auth_alg)
    349 {
    350 	if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
    351 		return 0;
    352 	return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
    353 }
    354 
    355 
    356 int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
    357 		     u16 seq, u16 status, const u8 *ie, size_t len)
    358 {
    359 	struct wpa_driver_sta_auth_params params;
    360 #ifdef CONFIG_FILS
    361 	struct sta_info *sta;
    362 #endif /* CONFIG_FILS */
    363 
    364 	if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
    365 		return 0;
    366 
    367 	os_memset(&params, 0, sizeof(params));
    368 
    369 #ifdef CONFIG_FILS
    370 	sta = ap_get_sta(hapd, addr);
    371 	if (!sta) {
    372 		wpa_printf(MSG_DEBUG, "Station " MACSTR
    373 			   " not found for sta_auth processing",
    374 			   MAC2STR(addr));
    375 		return 0;
    376 	}
    377 
    378 	if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
    379 	    sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
    380 	    sta->auth_alg == WLAN_AUTH_FILS_PK) {
    381 		params.fils_auth = 1;
    382 		wpa_auth_get_fils_aead_params(sta->wpa_sm, params.fils_anonce,
    383 					      params.fils_snonce,
    384 					      params.fils_kek,
    385 					      &params.fils_kek_len);
    386 	}
    387 #endif /* CONFIG_FILS */
    388 
    389 	params.own_addr = hapd->own_addr;
    390 	params.addr = addr;
    391 	params.seq = seq;
    392 	params.status = status;
    393 	params.ie = ie;
    394 	params.len = len;
    395 
    396 	return hapd->driver->sta_auth(hapd->drv_priv, &params);
    397 }
    398 
    399 
    400 int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
    401 		      int reassoc, u16 status, const u8 *ie, size_t len)
    402 {
    403 	if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
    404 		return 0;
    405 	return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
    406 				       reassoc, status, ie, len);
    407 }
    408 
    409 
    410 int hostapd_sta_add(struct hostapd_data *hapd,
    411 		    const u8 *addr, u16 aid, u16 capability,
    412 		    const u8 *supp_rates, size_t supp_rates_len,
    413 		    u16 listen_interval,
    414 		    const struct ieee80211_ht_capabilities *ht_capab,
    415 		    const struct ieee80211_vht_capabilities *vht_capab,
    416 		    u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
    417 		    int set)
    418 {
    419 	struct hostapd_sta_add_params params;
    420 
    421 	if (hapd->driver == NULL)
    422 		return 0;
    423 	if (hapd->driver->sta_add == NULL)
    424 		return 0;
    425 
    426 	os_memset(&params, 0, sizeof(params));
    427 	params.addr = addr;
    428 	params.aid = aid;
    429 	params.capability = capability;
    430 	params.supp_rates = supp_rates;
    431 	params.supp_rates_len = supp_rates_len;
    432 	params.listen_interval = listen_interval;
    433 	params.ht_capabilities = ht_capab;
    434 	params.vht_capabilities = vht_capab;
    435 	params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
    436 	params.vht_opmode = vht_opmode;
    437 	params.flags = hostapd_sta_flags_to_drv(flags);
    438 	params.qosinfo = qosinfo;
    439 	params.support_p2p_ps = supp_p2p_ps;
    440 	params.set = set;
    441 	return hapd->driver->sta_add(hapd->drv_priv, &params);
    442 }
    443 
    444 
    445 int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
    446 		      u8 *tspec_ie, size_t tspec_ielen)
    447 {
    448 	if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
    449 		return 0;
    450 	return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
    451 				       tspec_ielen);
    452 }
    453 
    454 
    455 int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
    456 {
    457 	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
    458 		return 0;
    459 	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
    460 }
    461 
    462 
    463 int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
    464 			     size_t elem_len)
    465 {
    466 	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
    467 		return 0;
    468 	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
    469 }
    470 
    471 
    472 int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
    473 {
    474 	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
    475 		return 0;
    476 	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
    477 }
    478 
    479 
    480 int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
    481 {
    482 	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
    483 		return 0;
    484 	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
    485 }
    486 
    487 
    488 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    489 		   const char *ifname, const u8 *addr, void *bss_ctx,
    490 		   void **drv_priv, char *force_ifname, u8 *if_addr,
    491 		   const char *bridge, int use_existing)
    492 {
    493 	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
    494 		return -1;
    495 	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
    496 				    bss_ctx, drv_priv, force_ifname, if_addr,
    497 				    bridge, use_existing, 1);
    498 }
    499 
    500 
    501 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    502 		      const char *ifname)
    503 {
    504 	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
    505 	    hapd->driver->if_remove == NULL)
    506 		return -1;
    507 	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
    508 }
    509 
    510 
    511 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
    512 			  struct wpa_bss_params *params)
    513 {
    514 	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
    515 		return 0;
    516 	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
    517 }
    518 
    519 
    520 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
    521 		       const u8 *addr, int idx, u8 *seq)
    522 {
    523 	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
    524 		return 0;
    525 	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
    526 					seq);
    527 }
    528 
    529 
    530 int hostapd_flush(struct hostapd_data *hapd)
    531 {
    532 	if (hapd->driver == NULL || hapd->driver->flush == NULL)
    533 		return 0;
    534 	return hapd->driver->flush(hapd->drv_priv);
    535 }
    536 
    537 
    538 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
    539 		     int freq, int channel, int ht_enabled, int vht_enabled,
    540 		     int sec_channel_offset, int vht_oper_chwidth,
    541 		     int center_segment0, int center_segment1)
    542 {
    543 	struct hostapd_freq_params data;
    544 
    545 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
    546 				    vht_enabled, sec_channel_offset,
    547 				    vht_oper_chwidth,
    548 				    center_segment0, center_segment1,
    549 				    hapd->iface->current_mode ?
    550 				    hapd->iface->current_mode->vht_capab : 0))
    551 		return -1;
    552 
    553 	if (hapd->driver == NULL)
    554 		return 0;
    555 	if (hapd->driver->set_freq == NULL)
    556 		return 0;
    557 	return hapd->driver->set_freq(hapd->drv_priv, &data);
    558 }
    559 
    560 int hostapd_set_rts(struct hostapd_data *hapd, int rts)
    561 {
    562 	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
    563 		return 0;
    564 	return hapd->driver->set_rts(hapd->drv_priv, rts);
    565 }
    566 
    567 
    568 int hostapd_set_frag(struct hostapd_data *hapd, int frag)
    569 {
    570 	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
    571 		return 0;
    572 	return hapd->driver->set_frag(hapd->drv_priv, frag);
    573 }
    574 
    575 
    576 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
    577 			  int total_flags, int flags_or, int flags_and)
    578 {
    579 	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
    580 		return 0;
    581 	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
    582 					   flags_or, flags_and);
    583 }
    584 
    585 
    586 int hostapd_set_country(struct hostapd_data *hapd, const char *country)
    587 {
    588 	if (hapd->driver == NULL ||
    589 	    hapd->driver->set_country == NULL)
    590 		return 0;
    591 	return hapd->driver->set_country(hapd->drv_priv, country);
    592 }
    593 
    594 
    595 int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
    596 				int cw_min, int cw_max, int burst_time)
    597 {
    598 	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
    599 		return 0;
    600 	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
    601 						 cw_min, cw_max, burst_time);
    602 }
    603 
    604 
    605 struct hostapd_hw_modes *
    606 hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
    607 			    u16 *flags, u8 *dfs_domain)
    608 {
    609 	if (hapd->driver == NULL ||
    610 	    hapd->driver->get_hw_feature_data == NULL)
    611 		return NULL;
    612 	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
    613 						 flags, dfs_domain);
    614 }
    615 
    616 
    617 int hostapd_driver_commit(struct hostapd_data *hapd)
    618 {
    619 	if (hapd->driver == NULL || hapd->driver->commit == NULL)
    620 		return 0;
    621 	return hapd->driver->commit(hapd->drv_priv);
    622 }
    623 
    624 
    625 int hostapd_drv_none(struct hostapd_data *hapd)
    626 {
    627 	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
    628 }
    629 
    630 
    631 int hostapd_driver_scan(struct hostapd_data *hapd,
    632 			struct wpa_driver_scan_params *params)
    633 {
    634 	if (hapd->driver && hapd->driver->scan2)
    635 		return hapd->driver->scan2(hapd->drv_priv, params);
    636 	return -1;
    637 }
    638 
    639 
    640 struct wpa_scan_results * hostapd_driver_get_scan_results(
    641 	struct hostapd_data *hapd)
    642 {
    643 	if (hapd->driver && hapd->driver->get_scan_results2)
    644 		return hapd->driver->get_scan_results2(hapd->drv_priv);
    645 	return NULL;
    646 }
    647 
    648 
    649 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
    650 			   int duration)
    651 {
    652 	if (hapd->driver && hapd->driver->set_noa)
    653 		return hapd->driver->set_noa(hapd->drv_priv, count, start,
    654 					     duration);
    655 	return -1;
    656 }
    657 
    658 
    659 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
    660 			enum wpa_alg alg, const u8 *addr,
    661 			int key_idx, int set_tx,
    662 			const u8 *seq, size_t seq_len,
    663 			const u8 *key, size_t key_len)
    664 {
    665 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
    666 		return 0;
    667 	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
    668 				     key_idx, set_tx, seq, seq_len, key,
    669 				     key_len);
    670 }
    671 
    672 
    673 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
    674 			  const void *msg, size_t len, int noack)
    675 {
    676 	if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
    677 		return 0;
    678 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
    679 				       NULL, 0);
    680 }
    681 
    682 
    683 int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
    684 			      const void *msg, size_t len, int noack,
    685 			      const u16 *csa_offs, size_t csa_offs_len)
    686 {
    687 	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
    688 		return 0;
    689 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
    690 				       csa_offs, csa_offs_len);
    691 }
    692 
    693 
    694 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
    695 			   const u8 *addr, int reason)
    696 {
    697 	if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv)
    698 		return 0;
    699 	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
    700 					reason);
    701 }
    702 
    703 
    704 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
    705 			     const u8 *addr, int reason)
    706 {
    707 	if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
    708 		return 0;
    709 	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
    710 					  reason);
    711 }
    712 
    713 
    714 int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
    715 			 const u8 *peer, u8 *buf, u16 *buf_len)
    716 {
    717 	if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
    718 		return -1;
    719 	return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
    720 				      buf_len);
    721 }
    722 
    723 
    724 int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
    725 			    unsigned int wait, const u8 *dst, const u8 *data,
    726 			    size_t len)
    727 {
    728 	const u8 *bssid;
    729 	const u8 wildcard_bssid[ETH_ALEN] = {
    730 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    731 	};
    732 
    733 	if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
    734 		return 0;
    735 	bssid = hapd->own_addr;
    736 	if (!is_multicast_ether_addr(dst) &&
    737 	    len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
    738 		struct sta_info *sta;
    739 
    740 		/*
    741 		 * Public Action frames to a STA that is not a member of the BSS
    742 		 * shall use wildcard BSSID value.
    743 		 */
    744 		sta = ap_get_sta(hapd, dst);
    745 		if (!sta || !(sta->flags & WLAN_STA_ASSOC))
    746 			bssid = wildcard_bssid;
    747 	} else if (is_broadcast_ether_addr(dst) &&
    748 		   len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
    749 		/*
    750 		 * The only current use case of Public Action frames with
    751 		 * broadcast destination address is DPP PKEX. That case is
    752 		 * directing all devices and not just the STAs within the BSS,
    753 		 * so have to use the wildcard BSSID value.
    754 		 */
    755 		bssid = wildcard_bssid;
    756 	}
    757 	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
    758 					 hapd->own_addr, bssid, data, len, 0);
    759 }
    760 
    761 
    762 int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
    763 				     unsigned int freq,
    764 				     unsigned int wait, const u8 *dst,
    765 				     const u8 *data, size_t len)
    766 {
    767 	if (hapd->driver == NULL || hapd->driver->send_action == NULL)
    768 		return 0;
    769 	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
    770 					 hapd->own_addr, hapd->own_addr, data,
    771 					 len, 0);
    772 }
    773 
    774 
    775 int hostapd_start_dfs_cac(struct hostapd_iface *iface,
    776 			  enum hostapd_hw_mode mode, int freq,
    777 			  int channel, int ht_enabled, int vht_enabled,
    778 			  int sec_channel_offset, int vht_oper_chwidth,
    779 			  int center_segment0, int center_segment1)
    780 {
    781 	struct hostapd_data *hapd = iface->bss[0];
    782 	struct hostapd_freq_params data;
    783 	int res;
    784 
    785 	if (!hapd->driver || !hapd->driver->start_dfs_cac)
    786 		return 0;
    787 
    788 	if (!iface->conf->ieee80211h) {
    789 		wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
    790 			   "is not enabled");
    791 		return -1;
    792 	}
    793 
    794 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
    795 				    vht_enabled, sec_channel_offset,
    796 				    vht_oper_chwidth, center_segment0,
    797 				    center_segment1,
    798 				    iface->current_mode->vht_capab)) {
    799 		wpa_printf(MSG_ERROR, "Can't set freq params");
    800 		return -1;
    801 	}
    802 
    803 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
    804 	if (!res) {
    805 		iface->cac_started = 1;
    806 		os_get_reltime(&iface->dfs_cac_start);
    807 	}
    808 
    809 	return res;
    810 }
    811 
    812 
    813 int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
    814 			    const u8 *qos_map_set, u8 qos_map_set_len)
    815 {
    816 	if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
    817 		return 0;
    818 	return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
    819 					 qos_map_set_len);
    820 }
    821 
    822 
    823 static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
    824 					     struct hostapd_hw_modes *mode,
    825 					     int acs_ch_list_all,
    826 					     int **freq_list)
    827 {
    828 	int i;
    829 
    830 	for (i = 0; i < mode->num_channels; i++) {
    831 		struct hostapd_channel_data *chan = &mode->channels[i];
    832 
    833 		if ((acs_ch_list_all ||
    834 		     freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
    835 					      chan->chan)) &&
    836 		    !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
    837 		    !(hapd->iface->conf->acs_exclude_dfs &&
    838 		      (chan->flag & HOSTAPD_CHAN_RADAR)))
    839 			int_array_add_unique(freq_list, chan->freq);
    840 	}
    841 }
    842 
    843 
    844 void hostapd_get_ext_capa(struct hostapd_iface *iface)
    845 {
    846 	struct hostapd_data *hapd = iface->bss[0];
    847 
    848 	if (!hapd->driver || !hapd->driver->get_ext_capab)
    849 		return;
    850 
    851 	hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS,
    852 				    &iface->extended_capa,
    853 				    &iface->extended_capa_mask,
    854 				    &iface->extended_capa_len);
    855 }
    856 
    857 
    858 int hostapd_drv_do_acs(struct hostapd_data *hapd)
    859 {
    860 	struct drv_acs_params params;
    861 	int ret, i, acs_ch_list_all = 0;
    862 	u8 *channels = NULL;
    863 	unsigned int num_channels = 0;
    864 	struct hostapd_hw_modes *mode;
    865 	int *freq_list = NULL;
    866 
    867 	if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
    868 		return 0;
    869 
    870 	os_memset(&params, 0, sizeof(params));
    871 	params.hw_mode = hapd->iface->conf->hw_mode;
    872 
    873 	/*
    874 	 * If no chanlist config parameter is provided, include all enabled
    875 	 * channels of the selected hw_mode.
    876 	 */
    877 	if (!hapd->iface->conf->acs_ch_list.num)
    878 		acs_ch_list_all = 1;
    879 
    880 	mode = hapd->iface->current_mode;
    881 	if (mode) {
    882 		channels = os_malloc(mode->num_channels);
    883 		if (channels == NULL)
    884 			return -1;
    885 
    886 		for (i = 0; i < mode->num_channels; i++) {
    887 			struct hostapd_channel_data *chan = &mode->channels[i];
    888 			if (!acs_ch_list_all &&
    889 			    !freq_range_list_includes(
    890 				    &hapd->iface->conf->acs_ch_list,
    891 				    chan->chan))
    892 				continue;
    893 			if (hapd->iface->conf->acs_exclude_dfs &&
    894 			    (chan->flag & HOSTAPD_CHAN_RADAR))
    895 				continue;
    896 			if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
    897 				channels[num_channels++] = chan->chan;
    898 				int_array_add_unique(&freq_list, chan->freq);
    899 			}
    900 		}
    901 	} else {
    902 		for (i = 0; i < hapd->iface->num_hw_features; i++) {
    903 			mode = &hapd->iface->hw_features[i];
    904 			hostapd_get_hw_mode_any_channels(hapd, mode,
    905 							 acs_ch_list_all,
    906 							 &freq_list);
    907 		}
    908 	}
    909 
    910 	params.ch_list = channels;
    911 	params.ch_list_len = num_channels;
    912 	params.freq_list = freq_list;
    913 
    914 	params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
    915 	params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
    916 				 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
    917 	params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
    918 	params.ch_width = 20;
    919 	if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
    920 		params.ch_width = 40;
    921 
    922 	/* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
    923 	 */
    924 	if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
    925 		if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
    926 			params.ch_width = 80;
    927 		else if (hapd->iface->conf->vht_oper_chwidth ==
    928 			 VHT_CHANWIDTH_160MHZ ||
    929 			 hapd->iface->conf->vht_oper_chwidth ==
    930 			 VHT_CHANWIDTH_80P80MHZ)
    931 			params.ch_width = 160;
    932 	}
    933 
    934 	ret = hapd->driver->do_acs(hapd->drv_priv, &params);
    935 	os_free(channels);
    936 
    937 	return ret;
    938 }
    939