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