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 "drivers/driver.h"
     13 #include "common/ieee802_11_defs.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_WPS2
    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_WPS2 */
    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 #endif /* CONFIG_HS20 */
    175 
    176 	*beacon_ret = beacon;
    177 	*proberesp_ret = proberesp;
    178 	*assocresp_ret = assocresp;
    179 
    180 	return 0;
    181 
    182 fail:
    183 	wpabuf_free(beacon);
    184 	wpabuf_free(proberesp);
    185 	wpabuf_free(assocresp);
    186 	return -1;
    187 }
    188 
    189 
    190 void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
    191 			       struct wpabuf *beacon,
    192 			       struct wpabuf *proberesp,
    193 			       struct wpabuf *assocresp)
    194 {
    195 	wpabuf_free(beacon);
    196 	wpabuf_free(proberesp);
    197 	wpabuf_free(assocresp);
    198 }
    199 
    200 
    201 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
    202 {
    203 	struct wpabuf *beacon, *proberesp, *assocresp;
    204 	int ret;
    205 
    206 	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
    207 		return 0;
    208 
    209 	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
    210 	    0)
    211 		return -1;
    212 
    213 	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
    214 					  assocresp);
    215 
    216 	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
    217 
    218 	return ret;
    219 }
    220 
    221 
    222 int hostapd_set_authorized(struct hostapd_data *hapd,
    223 			   struct sta_info *sta, int authorized)
    224 {
    225 	if (authorized) {
    226 		return hostapd_sta_set_flags(hapd, sta->addr,
    227 					     hostapd_sta_flags_to_drv(
    228 						     sta->flags),
    229 					     WPA_STA_AUTHORIZED, ~0);
    230 	}
    231 
    232 	return hostapd_sta_set_flags(hapd, sta->addr,
    233 				     hostapd_sta_flags_to_drv(sta->flags),
    234 				     0, ~WPA_STA_AUTHORIZED);
    235 }
    236 
    237 
    238 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
    239 {
    240 	int set_flags, total_flags, flags_and, flags_or;
    241 	total_flags = hostapd_sta_flags_to_drv(sta->flags);
    242 	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
    243 	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
    244 	     sta->auth_alg == WLAN_AUTH_FT) &&
    245 	    sta->flags & WLAN_STA_AUTHORIZED)
    246 		set_flags |= WPA_STA_AUTHORIZED;
    247 	flags_or = total_flags & set_flags;
    248 	flags_and = total_flags | ~set_flags;
    249 	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
    250 				     flags_or, flags_and);
    251 }
    252 
    253 
    254 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
    255 			      int enabled)
    256 {
    257 	struct wpa_bss_params params;
    258 	os_memset(&params, 0, sizeof(params));
    259 	params.ifname = ifname;
    260 	params.enabled = enabled;
    261 	if (enabled) {
    262 		params.wpa = hapd->conf->wpa;
    263 		params.ieee802_1x = hapd->conf->ieee802_1x;
    264 		params.wpa_group = hapd->conf->wpa_group;
    265 		params.wpa_pairwise = hapd->conf->wpa_pairwise;
    266 		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
    267 		params.rsn_preauth = hapd->conf->rsn_preauth;
    268 #ifdef CONFIG_IEEE80211W
    269 		params.ieee80211w = hapd->conf->ieee80211w;
    270 #endif /* CONFIG_IEEE80211W */
    271 	}
    272 	return hostapd_set_ieee8021x(hapd, &params);
    273 }
    274 
    275 
    276 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
    277 {
    278 	char force_ifname[IFNAMSIZ];
    279 	u8 if_addr[ETH_ALEN];
    280 	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
    281 			      NULL, NULL, force_ifname, if_addr, NULL);
    282 }
    283 
    284 
    285 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
    286 {
    287 	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
    288 }
    289 
    290 
    291 int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
    292 			int val)
    293 {
    294 	const char *bridge = NULL;
    295 
    296 	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
    297 		return 0;
    298 	if (hapd->conf->wds_bridge[0])
    299 		bridge = hapd->conf->wds_bridge;
    300 	else if (hapd->conf->bridge[0])
    301 		bridge = hapd->conf->bridge;
    302 	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
    303 					 bridge);
    304 }
    305 
    306 
    307 int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
    308 			 u16 auth_alg)
    309 {
    310 	if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
    311 		return 0;
    312 	return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
    313 }
    314 
    315 
    316 int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
    317 		     u16 seq, u16 status, const u8 *ie, size_t len)
    318 {
    319 	if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
    320 		return 0;
    321 	return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
    322 				      seq, status, ie, len);
    323 }
    324 
    325 
    326 int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
    327 		      int reassoc, u16 status, const u8 *ie, size_t len)
    328 {
    329 	if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
    330 		return 0;
    331 	return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
    332 				       reassoc, status, ie, len);
    333 }
    334 
    335 
    336 int hostapd_sta_add(struct hostapd_data *hapd,
    337 		    const u8 *addr, u16 aid, u16 capability,
    338 		    const u8 *supp_rates, size_t supp_rates_len,
    339 		    u16 listen_interval,
    340 		    const struct ieee80211_ht_capabilities *ht_capab,
    341 		    u32 flags, u8 qosinfo)
    342 {
    343 	struct hostapd_sta_add_params params;
    344 
    345 	if (hapd->driver == NULL)
    346 		return 0;
    347 	if (hapd->driver->sta_add == NULL)
    348 		return 0;
    349 
    350 	os_memset(&params, 0, sizeof(params));
    351 	params.addr = addr;
    352 	params.aid = aid;
    353 	params.capability = capability;
    354 	params.supp_rates = supp_rates;
    355 	params.supp_rates_len = supp_rates_len;
    356 	params.listen_interval = listen_interval;
    357 	params.ht_capabilities = ht_capab;
    358 	params.flags = hostapd_sta_flags_to_drv(flags);
    359 	params.qosinfo = qosinfo;
    360 	return hapd->driver->sta_add(hapd->drv_priv, &params);
    361 }
    362 
    363 
    364 int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
    365 		      u8 *tspec_ie, size_t tspec_ielen)
    366 {
    367 	if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
    368 		return 0;
    369 	return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
    370 				       tspec_ielen);
    371 }
    372 
    373 
    374 int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
    375 {
    376 	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
    377 		return 0;
    378 	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
    379 }
    380 
    381 
    382 int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
    383 			     size_t elem_len)
    384 {
    385 	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
    386 		return 0;
    387 	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
    388 }
    389 
    390 
    391 int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
    392 {
    393 	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
    394 		return 0;
    395 	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
    396 }
    397 
    398 
    399 int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
    400 {
    401 	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
    402 		return 0;
    403 	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
    404 }
    405 
    406 
    407 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    408 		   const char *ifname, const u8 *addr, void *bss_ctx,
    409 		   void **drv_priv, char *force_ifname, u8 *if_addr,
    410 		   const char *bridge)
    411 {
    412 	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
    413 		return -1;
    414 	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
    415 				    bss_ctx, drv_priv, force_ifname, if_addr,
    416 				    bridge);
    417 }
    418 
    419 
    420 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
    421 		      const char *ifname)
    422 {
    423 	if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
    424 		return -1;
    425 	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
    426 }
    427 
    428 
    429 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
    430 			  struct wpa_bss_params *params)
    431 {
    432 	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
    433 		return 0;
    434 	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
    435 }
    436 
    437 
    438 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
    439 		       const u8 *addr, int idx, u8 *seq)
    440 {
    441 	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
    442 		return 0;
    443 	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
    444 					seq);
    445 }
    446 
    447 
    448 int hostapd_flush(struct hostapd_data *hapd)
    449 {
    450 	if (hapd->driver == NULL || hapd->driver->flush == NULL)
    451 		return 0;
    452 	return hapd->driver->flush(hapd->drv_priv);
    453 }
    454 
    455 
    456 int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
    457 		     int channel, int ht_enabled, int sec_channel_offset)
    458 {
    459 	struct hostapd_freq_params data;
    460 	if (hapd->driver == NULL)
    461 		return 0;
    462 	if (hapd->driver->set_freq == NULL)
    463 		return 0;
    464 	os_memset(&data, 0, sizeof(data));
    465 	data.mode = mode;
    466 	data.freq = freq;
    467 	data.channel = channel;
    468 	data.ht_enabled = ht_enabled;
    469 	data.sec_channel_offset = sec_channel_offset;
    470 	return hapd->driver->set_freq(hapd->drv_priv, &data);
    471 }
    472 
    473 int hostapd_set_rts(struct hostapd_data *hapd, int rts)
    474 {
    475 	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
    476 		return 0;
    477 	return hapd->driver->set_rts(hapd->drv_priv, rts);
    478 }
    479 
    480 
    481 int hostapd_set_frag(struct hostapd_data *hapd, int frag)
    482 {
    483 	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
    484 		return 0;
    485 	return hapd->driver->set_frag(hapd->drv_priv, frag);
    486 }
    487 
    488 
    489 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
    490 			  int total_flags, int flags_or, int flags_and)
    491 {
    492 	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
    493 		return 0;
    494 	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
    495 					   flags_or, flags_and);
    496 }
    497 
    498 
    499 int hostapd_set_country(struct hostapd_data *hapd, const char *country)
    500 {
    501 	if (hapd->driver == NULL ||
    502 	    hapd->driver->set_country == NULL)
    503 		return 0;
    504 	return hapd->driver->set_country(hapd->drv_priv, country);
    505 }
    506 
    507 
    508 int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
    509 				int cw_min, int cw_max, int burst_time)
    510 {
    511 	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
    512 		return 0;
    513 	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
    514 						 cw_min, cw_max, burst_time);
    515 }
    516 
    517 
    518 struct hostapd_hw_modes *
    519 hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
    520 			    u16 *flags)
    521 {
    522 	if (hapd->driver == NULL ||
    523 	    hapd->driver->get_hw_feature_data == NULL)
    524 		return NULL;
    525 	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
    526 						 flags);
    527 }
    528 
    529 
    530 int hostapd_driver_commit(struct hostapd_data *hapd)
    531 {
    532 	if (hapd->driver == NULL || hapd->driver->commit == NULL)
    533 		return 0;
    534 	return hapd->driver->commit(hapd->drv_priv);
    535 }
    536 
    537 
    538 int hostapd_drv_none(struct hostapd_data *hapd)
    539 {
    540 	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
    541 }
    542 
    543 
    544 int hostapd_driver_scan(struct hostapd_data *hapd,
    545 			struct wpa_driver_scan_params *params)
    546 {
    547 	if (hapd->driver && hapd->driver->scan2)
    548 		return hapd->driver->scan2(hapd->drv_priv, params);
    549 	return -1;
    550 }
    551 
    552 
    553 struct wpa_scan_results * hostapd_driver_get_scan_results(
    554 	struct hostapd_data *hapd)
    555 {
    556 	if (hapd->driver && hapd->driver->get_scan_results2)
    557 		return hapd->driver->get_scan_results2(hapd->drv_priv);
    558 	return NULL;
    559 }
    560 
    561 
    562 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
    563 			   int duration)
    564 {
    565 	if (hapd->driver && hapd->driver->set_noa)
    566 		return hapd->driver->set_noa(hapd->drv_priv, count, start,
    567 					     duration);
    568 	return -1;
    569 }
    570 
    571 
    572 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
    573 			enum wpa_alg alg, const u8 *addr,
    574 			int key_idx, int set_tx,
    575 			const u8 *seq, size_t seq_len,
    576 			const u8 *key, size_t key_len)
    577 {
    578 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
    579 		return 0;
    580 	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
    581 				     key_idx, set_tx, seq, seq_len, key,
    582 				     key_len);
    583 }
    584 
    585 
    586 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
    587 			  const void *msg, size_t len, int noack)
    588 {
    589 	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
    590 		return 0;
    591 	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
    592 }
    593 
    594 
    595 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
    596 			   const u8 *addr, int reason)
    597 {
    598 	if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
    599 		return 0;
    600 	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
    601 					reason);
    602 }
    603 
    604 
    605 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
    606 			     const u8 *addr, int reason)
    607 {
    608 	if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
    609 		return 0;
    610 	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
    611 					  reason);
    612 }
    613 
    614 
    615 int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
    616 			 const u8 *peer, u8 *buf, u16 *buf_len)
    617 {
    618 	if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
    619 		return 0;
    620 	return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
    621 				      buf_len);
    622 }
    623 
    624 
    625 int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
    626 			    unsigned int wait, const u8 *dst, const u8 *data,
    627 			    size_t len)
    628 {
    629 	if (hapd->driver == NULL || hapd->driver->send_action == NULL)
    630 		return 0;
    631 	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
    632 					 hapd->own_addr, hapd->own_addr, data,
    633 					 len, 0);
    634 }
    635