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