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 "ap_drv_ops.h"
     23 
     24 
     25 u32 hostapd_sta_flags_to_drv(u32 flags)
     26 {
     27 	int res = 0;
     28 	if (flags & WLAN_STA_AUTHORIZED)
     29 		res |= WPA_STA_AUTHORIZED;
     30 	if (flags & WLAN_STA_WMM)
     31 		res |= WPA_STA_WMM;
     32 	if (flags & WLAN_STA_SHORT_PREAMBLE)
     33 		res |= WPA_STA_SHORT_PREAMBLE;
     34 	if (flags & WLAN_STA_MFP)
     35 		res |= WPA_STA_MFP;
     36 	return res;
     37 }
     38 
     39 
     40 int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
     41 			       struct wpabuf **beacon_ret,
     42 			       struct wpabuf **proberesp_ret,
     43 			       struct wpabuf **assocresp_ret)
     44 {
     45 	struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
     46 	u8 buf[200], *pos;
     47 
     48 	*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
     49 
     50 	pos = buf;
     51 	pos = hostapd_eid_time_adv(hapd, pos);
     52 	if (pos != buf) {
     53 		if (wpabuf_resize(&beacon, pos - buf) != 0)
     54 			goto fail;
     55 		wpabuf_put_data(beacon, buf, pos - buf);
     56 	}
     57 	pos = hostapd_eid_time_zone(hapd, pos);
     58 	if (pos != buf) {
     59 		if (wpabuf_resize(&proberesp, pos - buf) != 0)
     60 			goto fail;
     61 		wpabuf_put_data(proberesp, buf, pos - buf);
     62 	}
     63 
     64 	pos = buf;
     65 	pos = hostapd_eid_ext_capab(hapd, pos);
     66 	if (pos != buf) {
     67 		if (wpabuf_resize(&assocresp, pos - buf) != 0)
     68 			goto fail;
     69 		wpabuf_put_data(assocresp, buf, pos - buf);
     70 	}
     71 	pos = hostapd_eid_interworking(hapd, pos);
     72 	pos = hostapd_eid_adv_proto(hapd, pos);
     73 	pos = hostapd_eid_roaming_consortium(hapd, pos);
     74 	if (pos != buf) {
     75 		if (wpabuf_resize(&beacon, pos - buf) != 0)
     76 			goto fail;
     77 		wpabuf_put_data(beacon, buf, pos - buf);
     78 
     79 		if (wpabuf_resize(&proberesp, pos - buf) != 0)
     80 			goto fail;
     81 		wpabuf_put_data(proberesp, buf, pos - buf);
     82 	}
     83 
     84 	if (hapd->wps_beacon_ie) {
     85 		if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
     86 		    0)
     87 			goto fail;
     88 		wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
     89 	}
     90 
     91 	if (hapd->wps_probe_resp_ie) {
     92 		if (wpabuf_resize(&proberesp,
     93 				  wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
     94 			goto fail;
     95 		wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
     96 	}
     97 
     98 #ifdef CONFIG_P2P
     99 	if (hapd->p2p_beacon_ie) {
    100 		if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
    101 		    0)
    102 			goto fail;
    103 		wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
    104 	}
    105 
    106 	if (hapd->p2p_probe_resp_ie) {
    107 		if (wpabuf_resize(&proberesp,
    108 				  wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
    109 			goto fail;
    110 		wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
    111 	}
    112 #endif /* CONFIG_P2P */
    113 
    114 #ifdef CONFIG_P2P_MANAGER
    115 	if (hapd->conf->p2p & P2P_MANAGE) {
    116 		if (wpabuf_resize(&beacon, 100) == 0) {
    117 			u8 *start, *p;
    118 			start = wpabuf_put(beacon, 0);
    119 			p = hostapd_eid_p2p_manage(hapd, start);
    120 			wpabuf_put(beacon, p - start);
    121 		}
    122 
    123 		if (wpabuf_resize(&proberesp, 100) == 0) {
    124 			u8 *start, *p;
    125 			start = wpabuf_put(proberesp, 0);
    126 			p = hostapd_eid_p2p_manage(hapd, start);
    127 			wpabuf_put(proberesp, p - start);
    128 		}
    129 	}
    130 #endif /* CONFIG_P2P_MANAGER */
    131 
    132 #ifdef CONFIG_WPS
    133 	if (hapd->conf->wps_state) {
    134 		struct wpabuf *a = wps_build_assoc_resp_ie();
    135 		if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
    136 			wpabuf_put_buf(assocresp, a);
    137 		wpabuf_free(a);
    138 	}
    139 #endif /* CONFIG_WPS */
    140 
    141 #ifdef CONFIG_P2P_MANAGER
    142 	if (hapd->conf->p2p & P2P_MANAGE) {
    143 		if (wpabuf_resize(&assocresp, 100) == 0) {
    144 			u8 *start, *p;
    145 			start = wpabuf_put(assocresp, 0);
    146 			p = hostapd_eid_p2p_manage(hapd, start);
    147 			wpabuf_put(assocresp, p - start);
    148 		}
    149 	}
    150 #endif /* CONFIG_P2P_MANAGER */
    151 
    152 #ifdef CONFIG_WIFI_DISPLAY
    153 	if (hapd->p2p_group) {
    154 		struct wpabuf *a;
    155 		a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
    156 		if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
    157 			wpabuf_put_buf(assocresp, a);
    158 		wpabuf_free(a);
    159 	}
    160 #endif /* CONFIG_WIFI_DISPLAY */
    161 
    162 #ifdef CONFIG_HS20
    163 	pos = buf;
    164 	pos = hostapd_eid_hs20_indication(hapd, pos);
    165 	if (pos != buf) {
    166 		if (wpabuf_resize(&beacon, pos - buf) != 0)
    167 			goto fail;
    168 		wpabuf_put_data(beacon, buf, pos - buf);
    169 
    170 		if (wpabuf_resize(&proberesp, pos - buf) != 0)
    171 			goto fail;
    172 		wpabuf_put_data(proberesp, buf, pos - buf);
    173 	}
    174 
    175 	pos = hostapd_eid_osen(hapd, buf);
    176 	if (pos != buf) {
    177 		if (wpabuf_resize(&beacon, pos - buf) != 0)
    178 			goto fail;
    179 		wpabuf_put_data(beacon, buf, pos - buf);
    180 
    181 		if (wpabuf_resize(&proberesp, pos - buf) != 0)
    182 			goto fail;
    183 		wpabuf_put_data(proberesp, buf, pos - buf);
    184 	}
    185 #endif /* CONFIG_HS20 */
    186 
    187 	if (hapd->conf->vendor_elements) {
    188 		size_t add = wpabuf_len(hapd->conf->vendor_elements);
    189 		if (wpabuf_resize(&beacon, add) == 0)
    190 			wpabuf_put_buf(beacon, hapd->conf->vendor_elements);
    191 		if (wpabuf_resize(&proberesp, add) == 0)
    192 			wpabuf_put_buf(proberesp, hapd->conf->vendor_elements);
    193 	}
    194 
    195 	*beacon_ret = beacon;
    196 	*proberesp_ret = proberesp;
    197 	*assocresp_ret = assocresp;
    198 
    199 	return 0;
    200 
    201 fail:
    202 	wpabuf_free(beacon);
    203 	wpabuf_free(proberesp);
    204 	wpabuf_free(assocresp);
    205 	return -1;
    206 }
    207 
    208 
    209 void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
    210 			       struct wpabuf *beacon,
    211 			       struct wpabuf *proberesp,
    212 			       struct wpabuf *assocresp)
    213 {
    214 	wpabuf_free(beacon);
    215 	wpabuf_free(proberesp);
    216 	wpabuf_free(assocresp);
    217 }
    218 
    219 
    220 int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd)
    221 {
    222 	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
    223 		return 0;
    224 
    225 	return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL);
    226 }
    227 
    228 
    229 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
    230 {
    231 	struct wpabuf *beacon, *proberesp, *assocresp;
    232 	int ret;
    233 
    234 	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
    235 		return 0;
    236 
    237 	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
    238 	    0)
    239 		return -1;
    240 
    241 	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
    242 					  assocresp);
    243 
    244 	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
    245 
    246 	return ret;
    247 }
    248 
    249 
    250 int hostapd_set_authorized(struct hostapd_data *hapd,
    251 			   struct sta_info *sta, int authorized)
    252 {
    253 	if (authorized) {
    254 		return hostapd_sta_set_flags(hapd, sta->addr,
    255 					     hostapd_sta_flags_to_drv(
    256 						     sta->flags),
    257 					     WPA_STA_AUTHORIZED, ~0);
    258 	}
    259 
    260 	return hostapd_sta_set_flags(hapd, sta->addr,
    261 				     hostapd_sta_flags_to_drv(sta->flags),
    262 				     0, ~WPA_STA_AUTHORIZED);
    263 }
    264 
    265 
    266 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
    267 {
    268 	int set_flags, total_flags, flags_and, flags_or;
    269 	total_flags = hostapd_sta_flags_to_drv(sta->flags);
    270 	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
    271 	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
    272 	     sta->auth_alg == WLAN_AUTH_FT) &&
    273 	    sta->flags & WLAN_STA_AUTHORIZED)
    274 		set_flags |= WPA_STA_AUTHORIZED;
    275 	flags_or = total_flags & set_flags;
    276 	flags_and = total_flags | ~set_flags;
    277 	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
    278 				     flags_or, flags_and);
    279 }
    280 
    281 
    282 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
    283 			      int enabled)
    284 {
    285 	struct wpa_bss_params params;
    286 	os_memset(&params, 0, sizeof(params));
    287 	params.ifname = ifname;
    288 	params.enabled = enabled;
    289 	if (enabled) {
    290 		params.wpa = hapd->conf->wpa;
    291 		params.ieee802_1x = hapd->conf->ieee802_1x;
    292 		params.wpa_group = hapd->conf->wpa_group;
    293 		if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
    294 		    (WPA_PROTO_WPA | WPA_PROTO_RSN))
    295 			params.wpa_pairwise = hapd->conf->wpa_pairwise |
    296 				hapd->conf->rsn_pairwise;
    297 		else if (hapd->conf->wpa & WPA_PROTO_RSN)
    298 			params.wpa_pairwise = hapd->conf->rsn_pairwise;
    299 		else if (hapd->conf->wpa & WPA_PROTO_WPA)
    300 			params.wpa_pairwise = hapd->conf->wpa_pairwise;
    301 		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
    302 		params.rsn_preauth = hapd->conf->rsn_preauth;
    303 #ifdef CONFIG_IEEE80211W
    304 		params.ieee80211w = hapd->conf->ieee80211w;
    305 #endif /* CONFIG_IEEE80211W */
    306 	}
    307 	return hostapd_set_ieee8021x(hapd, &params);
    308 }
    309 
    310 
    311 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
    312 {
    313 	char force_ifname[IFNAMSIZ];
    314 	u8 if_addr[ETH_ALEN];
    315 	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
    316 			      NULL, NULL, force_ifname, if_addr, NULL, 0);
    317 }
    318 
    319 
    320 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
    321 {
    322 	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
    323 }
    324 
    325 
    326 int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
    327 			const u8 *addr, int aid, int val)
    328 {
    329 	const char *bridge = NULL;
    330 
    331 	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
    332 		return -1;
    333 	if (hapd->conf->wds_bridge[0])
    334 		bridge = hapd->conf->wds_bridge;
    335 	else if (hapd->conf->bridge[0])
    336 		bridge = hapd->conf->bridge;
    337 	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
    338 					 bridge, ifname_wds);
    339 }
    340 
    341 
    342 int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
    343 			 u16 auth_alg)
    344 {
    345 	if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
    346 		return 0;
    347 	return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
    348 }
    349 
    350 
    351 int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
    352 		     u16 seq, u16 status, const u8 *ie, size_t len)
    353 {
    354 	if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
    355 		return 0;
    356 	return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
    357 				      seq, status, ie, len);
    358 }
    359 
    360 
    361 int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
    362 		      int reassoc, u16 status, const u8 *ie, size_t len)
    363 {
    364 	if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
    365 		return 0;
    366 	return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
    367 				       reassoc, status, ie, len);
    368 }
    369 
    370 
    371 int hostapd_sta_add(struct hostapd_data *hapd,
    372 		    const u8 *addr, u16 aid, u16 capability,
    373 		    const u8 *supp_rates, size_t supp_rates_len,
    374 		    u16 listen_interval,
    375 		    const struct ieee80211_ht_capabilities *ht_capab,
    376 		    const struct ieee80211_vht_capabilities *vht_capab,
    377 		    u32 flags, u8 qosinfo, u8 vht_opmode)
    378 {
    379 	struct hostapd_sta_add_params params;
    380 
    381 	if (hapd->driver == NULL)
    382 		return 0;
    383 	if (hapd->driver->sta_add == NULL)
    384 		return 0;
    385 
    386 	os_memset(&params, 0, sizeof(params));
    387 	params.addr = addr;
    388 	params.aid = aid;
    389 	params.capability = capability;
    390 	params.supp_rates = supp_rates;
    391 	params.supp_rates_len = supp_rates_len;
    392 	params.listen_interval = listen_interval;
    393 	params.ht_capabilities = ht_capab;
    394 	params.vht_capabilities = vht_capab;
    395 	params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
    396 	params.vht_opmode = vht_opmode;
    397 	params.flags = hostapd_sta_flags_to_drv(flags);
    398 	params.qosinfo = qosinfo;
    399 	return hapd->driver->sta_add(hapd->drv_priv, &params);
    400 }
    401 
    402 
    403 int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
    404 		      u8 *tspec_ie, size_t tspec_ielen)
    405 {
    406 	if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
    407 		return 0;
    408 	return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
    409 				       tspec_ielen);
    410 }
    411 
    412 
    413 int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
    414 {
    415 	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
    416 		return 0;
    417 	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
    418 }
    419 
    420 
    421 int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
    422 			     size_t elem_len)
    423 {
    424 	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
    425 		return 0;
    426 	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
    427 }
    428 
    429 
    430 int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
    431 {
    432 	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
    433 		return 0;
    434 	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
    435 }
    436 
    437 
    438 int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
    439 {
    440 	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
    441 		return 0;
    442 	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
    443 }
    444 
    445 
    446 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    447 		   const char *ifname, const u8 *addr, void *bss_ctx,
    448 		   void **drv_priv, char *force_ifname, u8 *if_addr,
    449 		   const char *bridge, int use_existing)
    450 {
    451 	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
    452 		return -1;
    453 	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
    454 				    bss_ctx, drv_priv, force_ifname, if_addr,
    455 				    bridge, use_existing);
    456 }
    457 
    458 
    459 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    460 		      const char *ifname)
    461 {
    462 	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
    463 	    hapd->driver->if_remove == NULL)
    464 		return -1;
    465 	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
    466 }
    467 
    468 
    469 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
    470 			  struct wpa_bss_params *params)
    471 {
    472 	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
    473 		return 0;
    474 	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
    475 }
    476 
    477 
    478 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
    479 		       const u8 *addr, int idx, u8 *seq)
    480 {
    481 	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
    482 		return 0;
    483 	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
    484 					seq);
    485 }
    486 
    487 
    488 int hostapd_flush(struct hostapd_data *hapd)
    489 {
    490 	if (hapd->driver == NULL || hapd->driver->flush == NULL)
    491 		return 0;
    492 	return hapd->driver->flush(hapd->drv_priv);
    493 }
    494 
    495 
    496 int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
    497 		     int freq, int channel, int ht_enabled, int vht_enabled,
    498 		     int sec_channel_offset, int vht_oper_chwidth,
    499 		     int center_segment0, int center_segment1)
    500 {
    501 	struct hostapd_freq_params data;
    502 
    503 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
    504 				    vht_enabled, sec_channel_offset,
    505 				    vht_oper_chwidth,
    506 				    center_segment0, center_segment1,
    507 				    hapd->iface->current_mode ?
    508 				    hapd->iface->current_mode->vht_capab : 0))
    509 		return -1;
    510 
    511 	if (hapd->driver == NULL)
    512 		return 0;
    513 	if (hapd->driver->set_freq == NULL)
    514 		return 0;
    515 	return hapd->driver->set_freq(hapd->drv_priv, &data);
    516 }
    517 
    518 int hostapd_set_rts(struct hostapd_data *hapd, int rts)
    519 {
    520 	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
    521 		return 0;
    522 	return hapd->driver->set_rts(hapd->drv_priv, rts);
    523 }
    524 
    525 
    526 int hostapd_set_frag(struct hostapd_data *hapd, int frag)
    527 {
    528 	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
    529 		return 0;
    530 	return hapd->driver->set_frag(hapd->drv_priv, frag);
    531 }
    532 
    533 
    534 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
    535 			  int total_flags, int flags_or, int flags_and)
    536 {
    537 	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
    538 		return 0;
    539 	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
    540 					   flags_or, flags_and);
    541 }
    542 
    543 
    544 int hostapd_set_country(struct hostapd_data *hapd, const char *country)
    545 {
    546 	if (hapd->driver == NULL ||
    547 	    hapd->driver->set_country == NULL)
    548 		return 0;
    549 	return hapd->driver->set_country(hapd->drv_priv, country);
    550 }
    551 
    552 
    553 int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
    554 				int cw_min, int cw_max, int burst_time)
    555 {
    556 	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
    557 		return 0;
    558 	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
    559 						 cw_min, cw_max, burst_time);
    560 }
    561 
    562 
    563 struct hostapd_hw_modes *
    564 hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
    565 			    u16 *flags)
    566 {
    567 	if (hapd->driver == NULL ||
    568 	    hapd->driver->get_hw_feature_data == NULL)
    569 		return NULL;
    570 	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
    571 						 flags);
    572 }
    573 
    574 
    575 int hostapd_driver_commit(struct hostapd_data *hapd)
    576 {
    577 	if (hapd->driver == NULL || hapd->driver->commit == NULL)
    578 		return 0;
    579 	return hapd->driver->commit(hapd->drv_priv);
    580 }
    581 
    582 
    583 int hostapd_drv_none(struct hostapd_data *hapd)
    584 {
    585 	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
    586 }
    587 
    588 
    589 int hostapd_driver_scan(struct hostapd_data *hapd,
    590 			struct wpa_driver_scan_params *params)
    591 {
    592 	if (hapd->driver && hapd->driver->scan2)
    593 		return hapd->driver->scan2(hapd->drv_priv, params);
    594 	return -1;
    595 }
    596 
    597 
    598 struct wpa_scan_results * hostapd_driver_get_scan_results(
    599 	struct hostapd_data *hapd)
    600 {
    601 	if (hapd->driver && hapd->driver->get_scan_results2)
    602 		return hapd->driver->get_scan_results2(hapd->drv_priv);
    603 	return NULL;
    604 }
    605 
    606 
    607 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
    608 			   int duration)
    609 {
    610 	if (hapd->driver && hapd->driver->set_noa)
    611 		return hapd->driver->set_noa(hapd->drv_priv, count, start,
    612 					     duration);
    613 	return -1;
    614 }
    615 
    616 
    617 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
    618 			enum wpa_alg alg, const u8 *addr,
    619 			int key_idx, int set_tx,
    620 			const u8 *seq, size_t seq_len,
    621 			const u8 *key, size_t key_len)
    622 {
    623 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
    624 		return 0;
    625 	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
    626 				     key_idx, set_tx, seq, seq_len, key,
    627 				     key_len);
    628 }
    629 
    630 
    631 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
    632 			  const void *msg, size_t len, int noack)
    633 {
    634 	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
    635 		return 0;
    636 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
    637 }
    638 
    639 
    640 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
    641 			   const u8 *addr, int reason)
    642 {
    643 	if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
    644 		return 0;
    645 	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
    646 					reason);
    647 }
    648 
    649 
    650 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
    651 			     const u8 *addr, int reason)
    652 {
    653 	if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
    654 		return 0;
    655 	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
    656 					  reason);
    657 }
    658 
    659 
    660 int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
    661 			 const u8 *peer, u8 *buf, u16 *buf_len)
    662 {
    663 	if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
    664 		return -1;
    665 	return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
    666 				      buf_len);
    667 }
    668 
    669 
    670 int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
    671 			    unsigned int wait, const u8 *dst, const u8 *data,
    672 			    size_t len)
    673 {
    674 	if (hapd->driver == NULL || hapd->driver->send_action == NULL)
    675 		return 0;
    676 	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
    677 					 hapd->own_addr, hapd->own_addr, data,
    678 					 len, 0);
    679 }
    680 
    681 
    682 int hostapd_start_dfs_cac(struct hostapd_iface *iface,
    683 			  enum hostapd_hw_mode mode, int freq,
    684 			  int channel, int ht_enabled, int vht_enabled,
    685 			  int sec_channel_offset, int vht_oper_chwidth,
    686 			  int center_segment0, int center_segment1)
    687 {
    688 	struct hostapd_data *hapd = iface->bss[0];
    689 	struct hostapd_freq_params data;
    690 	int res;
    691 
    692 	if (!hapd->driver || !hapd->driver->start_dfs_cac)
    693 		return 0;
    694 
    695 	if (!iface->conf->ieee80211h) {
    696 		wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
    697 			   "is not enabled");
    698 		return -1;
    699 	}
    700 
    701 	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
    702 				    vht_enabled, sec_channel_offset,
    703 				    vht_oper_chwidth, center_segment0,
    704 				    center_segment1,
    705 				    iface->current_mode->vht_capab)) {
    706 		wpa_printf(MSG_ERROR, "Can't set freq params");
    707 		return -1;
    708 	}
    709 
    710 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
    711 	if (!res) {
    712 		iface->cac_started = 1;
    713 		os_get_reltime(&iface->dfs_cac_start);
    714 	}
    715 
    716 	return res;
    717 }
    718 
    719 
    720 int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
    721 			    const u8 *qos_map_set, u8 qos_map_set_len)
    722 {
    723 	if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL)
    724 		return 0;
    725 	return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
    726 					 qos_map_set_len);
    727 }
    728 
    729 
    730 int hostapd_drv_do_acs(struct hostapd_data *hapd)
    731 {
    732 	struct drv_acs_params params;
    733 	int ret, i, acs_ch_list_all = 0;
    734 	u8 *channels = NULL;
    735 	unsigned int num_channels = 0;
    736 	struct hostapd_hw_modes *mode;
    737 
    738 	if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
    739 		return 0;
    740 
    741 	os_memset(&params, 0, sizeof(params));
    742 	params.hw_mode = hapd->iface->conf->hw_mode;
    743 
    744 	/*
    745 	 * If no chanlist config parameter is provided, include all enabled
    746 	 * channels of the selected hw_mode.
    747 	 */
    748 	if (!hapd->iface->conf->acs_ch_list.num)
    749 		acs_ch_list_all = 1;
    750 
    751 	mode = hapd->iface->current_mode;
    752 	if (mode == NULL)
    753 		return -1;
    754 	channels = os_malloc(mode->num_channels);
    755 	if (channels == NULL)
    756 		return -1;
    757 
    758 	for (i = 0; i < mode->num_channels; i++) {
    759 		struct hostapd_channel_data *chan = &mode->channels[i];
    760 		if (!acs_ch_list_all &&
    761 		    !freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
    762 					      chan->chan))
    763 			continue;
    764 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED))
    765 			channels[num_channels++] = chan->chan;
    766 	}
    767 
    768 	params.ch_list = channels;
    769 	params.ch_list_len = num_channels;
    770 
    771 	params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
    772 	params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
    773 				 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
    774 	params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
    775 	params.ch_width = 20;
    776 	if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
    777 		params.ch_width = 40;
    778 
    779 	/* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
    780 	 */
    781 	if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
    782 		if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
    783 			params.ch_width = 80;
    784 		else if (hapd->iface->conf->vht_oper_chwidth ==
    785 			 VHT_CHANWIDTH_160MHZ ||
    786 			 hapd->iface->conf->vht_oper_chwidth ==
    787 			 VHT_CHANWIDTH_80P80MHZ)
    788 			params.ch_width = 160;
    789 	}
    790 
    791 	ret = hapd->driver->do_acs(hapd->drv_priv, &params);
    792 	os_free(channels);
    793 
    794 	return ret;
    795 }
    796