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