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