1/*
2 * hostapd - Driver operations
3 * Copyright (c) 2009-2010, Jouni Malinen <j@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
25u32 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
40int 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
201fail:
202	wpabuf_free(beacon);
203	wpabuf_free(proberesp);
204	wpabuf_free(assocresp);
205	return -1;
206}
207
208
209void 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
220int 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
229int 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
250int 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
266int 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
282int 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
311int 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
320int 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
326int 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
342int 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
351int 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
361int 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
371int 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
403int 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
413int 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
421int 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
430int 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
438int 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
446int 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
459int 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
469int 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
478int 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
488int 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
496int 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
518int 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
526int 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
534int 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
544int 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
553int 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
563struct hostapd_hw_modes *
564hostapd_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
575int 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
583int hostapd_drv_none(struct hostapd_data *hapd)
584{
585	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
586}
587
588
589int 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
598struct 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
607int 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
617int 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
631int 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
640int 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
650int 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
660int 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
670int 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
682int 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
720int 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
730int 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