Line data Source code
1 : /*
2 : * hostapd / Initialization and configuration
3 : * Copyright (c) 2002-2014, 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 "utils/eloop.h"
13 : #include "common/ieee802_11_defs.h"
14 : #include "common/wpa_ctrl.h"
15 : #include "radius/radius_client.h"
16 : #include "radius/radius_das.h"
17 : #include "eap_server/tncs.h"
18 : #include "hostapd.h"
19 : #include "authsrv.h"
20 : #include "sta_info.h"
21 : #include "accounting.h"
22 : #include "ap_list.h"
23 : #include "beacon.h"
24 : #include "iapp.h"
25 : #include "ieee802_1x.h"
26 : #include "ieee802_11_auth.h"
27 : #include "vlan_init.h"
28 : #include "wpa_auth.h"
29 : #include "wps_hostapd.h"
30 : #include "hw_features.h"
31 : #include "wpa_auth_glue.h"
32 : #include "ap_drv_ops.h"
33 : #include "ap_config.h"
34 : #include "p2p_hostapd.h"
35 : #include "gas_serv.h"
36 : #include "dfs.h"
37 : #include "ieee802_11.h"
38 :
39 :
40 : static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
41 : static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
42 : static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
43 : static int setup_interface2(struct hostapd_iface *iface);
44 : static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
45 :
46 :
47 1817 : int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
48 : int (*cb)(struct hostapd_iface *iface,
49 : void *ctx), void *ctx)
50 : {
51 : size_t i;
52 : int ret;
53 :
54 3860 : for (i = 0; i < interfaces->count; i++) {
55 2299 : ret = cb(interfaces->iface[i], ctx);
56 2299 : if (ret)
57 256 : return ret;
58 : }
59 :
60 1561 : return 0;
61 : }
62 :
63 :
64 18 : static void hostapd_reload_bss(struct hostapd_data *hapd)
65 : {
66 : struct hostapd_ssid *ssid;
67 :
68 : #ifndef CONFIG_NO_RADIUS
69 18 : radius_client_reconfig(hapd->radius, hapd->conf->radius);
70 : #endif /* CONFIG_NO_RADIUS */
71 :
72 18 : ssid = &hapd->conf->ssid;
73 18 : if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
74 1 : ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
75 : /*
76 : * Force PSK to be derived again since SSID or passphrase may
77 : * have changed.
78 : */
79 1 : os_free(ssid->wpa_psk);
80 1 : ssid->wpa_psk = NULL;
81 : }
82 18 : if (hostapd_setup_wpa_psk(hapd->conf)) {
83 0 : wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
84 : "after reloading configuration");
85 : }
86 :
87 18 : if (hapd->conf->ieee802_1x || hapd->conf->wpa)
88 17 : hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
89 : else
90 1 : hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
91 :
92 18 : if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) {
93 15 : hostapd_setup_wpa(hapd);
94 30 : if (hapd->wpa_auth)
95 15 : wpa_init_keys(hapd->wpa_auth);
96 3 : } else if (hapd->conf->wpa) {
97 : const u8 *wpa_ie;
98 : size_t wpa_ie_len;
99 2 : hostapd_reconfig_wpa(hapd);
100 2 : wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
101 2 : if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
102 0 : wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
103 : "the kernel driver.");
104 1 : } else if (hapd->wpa_auth) {
105 1 : wpa_deinit(hapd->wpa_auth);
106 1 : hapd->wpa_auth = NULL;
107 1 : hostapd_set_privacy(hapd, 0);
108 1 : hostapd_setup_encryption(hapd->conf->iface, hapd);
109 1 : hostapd_set_generic_elem(hapd, (u8 *) "", 0);
110 : }
111 :
112 18 : ieee802_11_set_beacon(hapd);
113 18 : hostapd_update_wps(hapd);
114 :
115 36 : if (hapd->conf->ssid.ssid_set &&
116 18 : hostapd_set_ssid(hapd, hapd->conf->ssid.ssid,
117 18 : hapd->conf->ssid.ssid_len)) {
118 0 : wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
119 : /* try to continue */
120 : }
121 18 : wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
122 18 : }
123 :
124 :
125 18 : static void hostapd_clear_old(struct hostapd_iface *iface)
126 : {
127 : size_t j;
128 :
129 : /*
130 : * Deauthenticate all stations since the new configuration may not
131 : * allow them to use the BSS anymore.
132 : */
133 36 : for (j = 0; j < iface->num_bss; j++) {
134 18 : hostapd_flush_old_stations(iface->bss[j],
135 : WLAN_REASON_PREV_AUTH_NOT_VALID);
136 18 : hostapd_broadcast_wep_clear(iface->bss[j]);
137 :
138 : #ifndef CONFIG_NO_RADIUS
139 : /* TODO: update dynamic data based on changed configuration
140 : * items (e.g., open/close sockets, etc.) */
141 18 : radius_client_flush(iface->bss[j]->radius, 0);
142 : #endif /* CONFIG_NO_RADIUS */
143 : }
144 18 : }
145 :
146 :
147 17 : int hostapd_reload_config(struct hostapd_iface *iface)
148 : {
149 17 : struct hostapd_data *hapd = iface->bss[0];
150 : struct hostapd_config *newconf, *oldconf;
151 : size_t j;
152 :
153 17 : if (iface->config_fname == NULL) {
154 : /* Only in-memory config in use - assume it has been updated */
155 16 : hostapd_clear_old(iface);
156 32 : for (j = 0; j < iface->num_bss; j++)
157 16 : hostapd_reload_bss(iface->bss[j]);
158 16 : return 0;
159 : }
160 :
161 2 : if (iface->interfaces == NULL ||
162 1 : iface->interfaces->config_read_cb == NULL)
163 0 : return -1;
164 1 : newconf = iface->interfaces->config_read_cb(iface->config_fname);
165 1 : if (newconf == NULL)
166 0 : return -1;
167 :
168 1 : hostapd_clear_old(iface);
169 :
170 1 : oldconf = hapd->iconf;
171 1 : iface->conf = newconf;
172 :
173 2 : for (j = 0; j < iface->num_bss; j++) {
174 1 : hapd = iface->bss[j];
175 1 : hapd->iconf = newconf;
176 1 : hapd->iconf->channel = oldconf->channel;
177 1 : hapd->iconf->secondary_channel = oldconf->secondary_channel;
178 1 : hapd->iconf->ieee80211n = oldconf->ieee80211n;
179 1 : hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
180 1 : hapd->iconf->ht_capab = oldconf->ht_capab;
181 1 : hapd->iconf->vht_capab = oldconf->vht_capab;
182 1 : hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
183 2 : hapd->iconf->vht_oper_centr_freq_seg0_idx =
184 1 : oldconf->vht_oper_centr_freq_seg0_idx;
185 2 : hapd->iconf->vht_oper_centr_freq_seg1_idx =
186 1 : oldconf->vht_oper_centr_freq_seg1_idx;
187 1 : hapd->conf = newconf->bss[j];
188 1 : hostapd_reload_bss(hapd);
189 : }
190 :
191 1 : hostapd_config_free(oldconf);
192 :
193 :
194 1 : return 0;
195 : }
196 :
197 :
198 673 : static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
199 : char *ifname)
200 : {
201 : int i;
202 :
203 3365 : for (i = 0; i < NUM_WEP_KEYS; i++) {
204 2692 : if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
205 : 0, NULL, 0, NULL, 0)) {
206 4 : wpa_printf(MSG_DEBUG, "Failed to clear default "
207 : "encryption keys (ifname=%s keyidx=%d)",
208 : ifname, i);
209 : }
210 : }
211 : #ifdef CONFIG_IEEE80211W
212 673 : if (hapd->conf->ieee80211w) {
213 375 : for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
214 250 : if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
215 : NULL, i, 0, NULL,
216 : 0, NULL, 0)) {
217 0 : wpa_printf(MSG_DEBUG, "Failed to clear "
218 : "default mgmt encryption keys "
219 : "(ifname=%s keyidx=%d)", ifname, i);
220 : }
221 : }
222 : }
223 : #endif /* CONFIG_IEEE80211W */
224 673 : }
225 :
226 :
227 673 : static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
228 : {
229 673 : hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
230 673 : return 0;
231 : }
232 :
233 :
234 638 : static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
235 : {
236 638 : int errors = 0, idx;
237 638 : struct hostapd_ssid *ssid = &hapd->conf->ssid;
238 :
239 638 : idx = ssid->wep.idx;
240 640 : if (ssid->wep.default_len &&
241 4 : hostapd_drv_set_key(hapd->conf->iface,
242 : hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
243 2 : 1, NULL, 0, ssid->wep.key[idx],
244 : ssid->wep.len[idx])) {
245 2 : wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
246 2 : errors++;
247 : }
248 :
249 638 : return errors;
250 : }
251 :
252 :
253 667 : static void hostapd_free_hapd_data(struct hostapd_data *hapd)
254 : {
255 667 : if (!hapd->started) {
256 30 : wpa_printf(MSG_ERROR, "%s: Interface %s wasn't started",
257 30 : __func__, hapd->conf->iface);
258 697 : return;
259 : }
260 637 : hapd->started = 0;
261 :
262 637 : wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
263 637 : iapp_deinit(hapd->iapp);
264 637 : hapd->iapp = NULL;
265 637 : accounting_deinit(hapd);
266 637 : hostapd_deinit_wpa(hapd);
267 637 : vlan_deinit(hapd);
268 637 : hostapd_acl_deinit(hapd);
269 : #ifndef CONFIG_NO_RADIUS
270 637 : radius_client_deinit(hapd->radius);
271 637 : hapd->radius = NULL;
272 637 : radius_das_deinit(hapd->radius_das);
273 637 : hapd->radius_das = NULL;
274 : #endif /* CONFIG_NO_RADIUS */
275 :
276 637 : hostapd_deinit_wps(hapd);
277 :
278 637 : authsrv_deinit(hapd);
279 :
280 637 : if (hapd->interface_added) {
281 19 : hapd->interface_added = 0;
282 19 : if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
283 0 : wpa_printf(MSG_WARNING,
284 : "Failed to remove BSS interface %s",
285 0 : hapd->conf->iface);
286 0 : hapd->interface_added = 1;
287 : } else {
288 : /*
289 : * Since this was a dynamically added interface, the
290 : * driver wrapper may have removed its internal instance
291 : * and hapd->drv_priv is not valid anymore.
292 : */
293 19 : hapd->drv_priv = NULL;
294 : }
295 : }
296 :
297 637 : os_free(hapd->probereq_cb);
298 637 : hapd->probereq_cb = NULL;
299 :
300 : #ifdef CONFIG_P2P
301 : wpabuf_free(hapd->p2p_beacon_ie);
302 : hapd->p2p_beacon_ie = NULL;
303 : wpabuf_free(hapd->p2p_probe_resp_ie);
304 : hapd->p2p_probe_resp_ie = NULL;
305 : #endif /* CONFIG_P2P */
306 :
307 637 : wpabuf_free(hapd->time_adv);
308 :
309 : #ifdef CONFIG_INTERWORKING
310 637 : gas_serv_deinit(hapd);
311 : #endif /* CONFIG_INTERWORKING */
312 :
313 : #ifdef CONFIG_SQLITE
314 637 : bin_clear_free(hapd->tmp_eap_user.identity,
315 : hapd->tmp_eap_user.identity_len);
316 637 : bin_clear_free(hapd->tmp_eap_user.password,
317 : hapd->tmp_eap_user.password_len);
318 : #endif /* CONFIG_SQLITE */
319 : }
320 :
321 :
322 : /**
323 : * hostapd_cleanup - Per-BSS cleanup (deinitialization)
324 : * @hapd: Pointer to BSS data
325 : *
326 : * This function is used to free all per-BSS data structures and resources.
327 : * Most of the modules that are initialized in hostapd_setup_bss() are
328 : * deinitialized here.
329 : */
330 652 : static void hostapd_cleanup(struct hostapd_data *hapd)
331 : {
332 652 : wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd,
333 652 : hapd->conf->iface);
334 1304 : if (hapd->iface->interfaces &&
335 652 : hapd->iface->interfaces->ctrl_iface_deinit)
336 652 : hapd->iface->interfaces->ctrl_iface_deinit(hapd);
337 652 : hostapd_free_hapd_data(hapd);
338 652 : }
339 :
340 :
341 641 : static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
342 : {
343 641 : wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
344 641 : hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
345 641 : iface->hw_features = NULL;
346 641 : os_free(iface->current_rates);
347 641 : iface->current_rates = NULL;
348 641 : os_free(iface->basic_rates);
349 641 : iface->basic_rates = NULL;
350 641 : ap_list_deinit(iface);
351 641 : }
352 :
353 :
354 : /**
355 : * hostapd_cleanup_iface - Complete per-interface cleanup
356 : * @iface: Pointer to interface data
357 : *
358 : * This function is called after per-BSS data structures are deinitialized
359 : * with hostapd_cleanup().
360 : */
361 632 : static void hostapd_cleanup_iface(struct hostapd_iface *iface)
362 : {
363 632 : wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
364 632 : eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
365 :
366 632 : hostapd_cleanup_iface_partial(iface);
367 632 : hostapd_config_free(iface->conf);
368 632 : iface->conf = NULL;
369 :
370 632 : os_free(iface->config_fname);
371 632 : os_free(iface->bss);
372 632 : wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface);
373 632 : os_free(iface);
374 632 : }
375 :
376 :
377 667 : static void hostapd_clear_wep(struct hostapd_data *hapd)
378 : {
379 667 : if (hapd->drv_priv && !hapd->iface->driver_ap_teardown) {
380 18 : hostapd_set_privacy(hapd, 0);
381 18 : hostapd_broadcast_wep_clear(hapd);
382 : }
383 667 : }
384 :
385 :
386 638 : static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
387 : {
388 : int i;
389 :
390 638 : hostapd_broadcast_wep_set(hapd);
391 :
392 638 : if (hapd->conf->ssid.wep.default_len) {
393 2 : hostapd_set_privacy(hapd, 1);
394 2 : return 0;
395 : }
396 :
397 : /*
398 : * When IEEE 802.1X is not enabled, the driver may need to know how to
399 : * set authentication algorithms for static WEP.
400 : */
401 636 : hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs);
402 :
403 3180 : for (i = 0; i < 4; i++) {
404 2548 : if (hapd->conf->ssid.wep.key[i] &&
405 8 : hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
406 4 : i == hapd->conf->ssid.wep.idx, NULL, 0,
407 4 : hapd->conf->ssid.wep.key[i],
408 4 : hapd->conf->ssid.wep.len[i])) {
409 0 : wpa_printf(MSG_WARNING, "Could not set WEP "
410 : "encryption.");
411 0 : return -1;
412 : }
413 2548 : if (hapd->conf->ssid.wep.key[i] &&
414 4 : i == hapd->conf->ssid.wep.idx)
415 4 : hostapd_set_privacy(hapd, 1);
416 : }
417 :
418 636 : return 0;
419 : }
420 :
421 :
422 1322 : static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
423 : {
424 1322 : int ret = 0;
425 : u8 addr[ETH_ALEN];
426 :
427 1322 : if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
428 18 : return 0;
429 :
430 1304 : if (!hapd->iface->driver_ap_teardown) {
431 673 : wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
432 : "Flushing old station entries");
433 :
434 673 : if (hostapd_flush(hapd)) {
435 0 : wpa_msg(hapd->msg_ctx, MSG_WARNING,
436 : "Could not connect to kernel driver");
437 0 : ret = -1;
438 : }
439 : }
440 1304 : wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
441 1304 : os_memset(addr, 0xff, ETH_ALEN);
442 1304 : hostapd_drv_sta_deauth(hapd, addr, reason);
443 1304 : hostapd_free_stas(hapd);
444 :
445 1304 : return ret;
446 : }
447 :
448 :
449 667 : static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
450 : {
451 667 : hostapd_free_stas(hapd);
452 667 : hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
453 667 : hostapd_clear_wep(hapd);
454 667 : }
455 :
456 :
457 : /**
458 : * hostapd_validate_bssid_configuration - Validate BSSID configuration
459 : * @iface: Pointer to interface data
460 : * Returns: 0 on success, -1 on failure
461 : *
462 : * This function is used to validate that the configured BSSIDs are valid.
463 : */
464 631 : static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
465 : {
466 631 : u8 mask[ETH_ALEN] = { 0 };
467 631 : struct hostapd_data *hapd = iface->bss[0];
468 631 : unsigned int i = iface->conf->num_bss, bits = 0, j;
469 631 : int auto_addr = 0;
470 :
471 631 : if (hostapd_drv_none(hapd))
472 0 : return 0;
473 :
474 : /* Generate BSSID mask that is large enough to cover the BSSIDs. */
475 :
476 : /* Determine the bits necessary to cover the number of BSSIDs. */
477 642 : for (i--; i; i >>= 1)
478 11 : bits++;
479 :
480 : /* Determine the bits necessary to any configured BSSIDs,
481 : if they are higher than the number of BSSIDs. */
482 1273 : for (j = 0; j < iface->conf->num_bss; j++) {
483 642 : if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
484 627 : if (j)
485 4 : auto_addr++;
486 627 : continue;
487 : }
488 :
489 105 : for (i = 0; i < ETH_ALEN; i++) {
490 180 : mask[i] |=
491 90 : iface->conf->bss[j]->bssid[i] ^
492 90 : hapd->own_addr[i];
493 : }
494 : }
495 :
496 631 : if (!auto_addr)
497 627 : goto skip_mask_ext;
498 :
499 4 : for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
500 : ;
501 4 : j = 0;
502 4 : if (i < ETH_ALEN) {
503 0 : j = (5 - i) * 8;
504 :
505 0 : while (mask[i] != 0) {
506 0 : mask[i] >>= 1;
507 0 : j++;
508 : }
509 : }
510 :
511 4 : if (bits < j)
512 0 : bits = j;
513 :
514 4 : if (bits > 40) {
515 0 : wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
516 : bits);
517 0 : return -1;
518 : }
519 :
520 4 : os_memset(mask, 0xff, ETH_ALEN);
521 4 : j = bits / 8;
522 4 : for (i = 5; i > 5 - j; i--)
523 0 : mask[i] = 0;
524 4 : j = bits % 8;
525 12 : while (j--)
526 4 : mask[i] <<= 1;
527 :
528 : skip_mask_ext:
529 4417 : wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
530 4417 : (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
531 :
532 631 : if (!auto_addr)
533 627 : return 0;
534 :
535 28 : for (i = 0; i < ETH_ALEN; i++) {
536 24 : if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
537 0 : wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
538 : " for start address " MACSTR ".",
539 0 : MAC2STR(mask), MAC2STR(hapd->own_addr));
540 0 : wpa_printf(MSG_ERROR, "Start address must be the "
541 : "first address in the block (i.e., addr "
542 : "AND mask == addr).");
543 0 : return -1;
544 : }
545 : }
546 :
547 4 : return 0;
548 : }
549 :
550 :
551 0 : static int mac_in_conf(struct hostapd_config *conf, const void *a)
552 : {
553 : size_t i;
554 :
555 0 : for (i = 0; i < conf->num_bss; i++) {
556 0 : if (hostapd_mac_comp(conf->bss[i]->bssid, a) == 0) {
557 0 : return 1;
558 : }
559 : }
560 :
561 0 : return 0;
562 : }
563 :
564 :
565 : #ifndef CONFIG_NO_RADIUS
566 :
567 10 : static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
568 : struct radius_das_attrs *attr)
569 : {
570 13 : if (attr->nas_identifier &&
571 6 : (!hapd->conf->nas_identifier ||
572 3 : os_strlen(hapd->conf->nas_identifier) !=
573 5 : attr->nas_identifier_len ||
574 2 : os_memcmp(hapd->conf->nas_identifier, attr->nas_identifier,
575 : attr->nas_identifier_len) != 0)) {
576 1 : wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-Identifier mismatch");
577 1 : return 1;
578 : }
579 :
580 12 : if (attr->nas_ip_addr &&
581 6 : (hapd->conf->own_ip_addr.af != AF_INET ||
582 3 : os_memcmp(&hapd->conf->own_ip_addr.u.v4, attr->nas_ip_addr, 4) !=
583 : 0)) {
584 1 : wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IP-Address mismatch");
585 1 : return 1;
586 : }
587 :
588 : #ifdef CONFIG_IPV6
589 8 : if (attr->nas_ipv6_addr &&
590 0 : (hapd->conf->own_ip_addr.af != AF_INET6 ||
591 0 : os_memcmp(&hapd->conf->own_ip_addr.u.v6, attr->nas_ipv6_addr, 16)
592 : != 0)) {
593 0 : wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IPv6-Address mismatch");
594 0 : return 1;
595 : }
596 : #endif /* CONFIG_IPV6 */
597 :
598 8 : return 0;
599 : }
600 :
601 :
602 8 : static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
603 : struct radius_das_attrs *attr)
604 : {
605 8 : struct sta_info *sta = NULL;
606 : char buf[128];
607 :
608 8 : if (attr->sta_addr)
609 3 : sta = ap_get_sta(hapd, attr->sta_addr);
610 :
611 10 : if (sta == NULL && attr->acct_session_id &&
612 2 : attr->acct_session_id_len == 17) {
613 3 : for (sta = hapd->sta_list; sta; sta = sta->next) {
614 2 : os_snprintf(buf, sizeof(buf), "%08X-%08X",
615 : sta->acct_session_id_hi,
616 : sta->acct_session_id_lo);
617 2 : if (os_memcmp(attr->acct_session_id, buf, 17) == 0)
618 1 : break;
619 : }
620 : }
621 :
622 8 : if (sta == NULL && attr->cui) {
623 1 : for (sta = hapd->sta_list; sta; sta = sta->next) {
624 : struct wpabuf *cui;
625 1 : cui = ieee802_1x_get_radius_cui(sta->eapol_sm);
626 2 : if (cui && wpabuf_len(cui) == attr->cui_len &&
627 1 : os_memcmp(wpabuf_head(cui), attr->cui,
628 : attr->cui_len) == 0)
629 1 : break;
630 : }
631 : }
632 :
633 8 : if (sta == NULL && attr->user_name) {
634 3 : for (sta = hapd->sta_list; sta; sta = sta->next) {
635 : u8 *identity;
636 : size_t identity_len;
637 2 : identity = ieee802_1x_get_identity(sta->eapol_sm,
638 : &identity_len);
639 4 : if (identity &&
640 3 : identity_len == attr->user_name_len &&
641 1 : os_memcmp(identity, attr->user_name, identity_len)
642 : == 0)
643 1 : break;
644 : }
645 : }
646 :
647 8 : return sta;
648 : }
649 :
650 :
651 : static enum radius_das_res
652 10 : hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
653 : {
654 10 : struct hostapd_data *hapd = ctx;
655 : struct sta_info *sta;
656 :
657 10 : if (hostapd_das_nas_mismatch(hapd, attr))
658 2 : return RADIUS_DAS_NAS_MISMATCH;
659 :
660 8 : sta = hostapd_das_find_sta(hapd, attr);
661 8 : if (sta == NULL)
662 3 : return RADIUS_DAS_SESSION_NOT_FOUND;
663 :
664 5 : wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
665 :
666 5 : hostapd_drv_sta_deauth(hapd, sta->addr,
667 : WLAN_REASON_PREV_AUTH_NOT_VALID);
668 5 : ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
669 :
670 5 : return RADIUS_DAS_SUCCESS;
671 : }
672 :
673 : #endif /* CONFIG_NO_RADIUS */
674 :
675 :
676 : /**
677 : * hostapd_setup_bss - Per-BSS setup (initialization)
678 : * @hapd: Pointer to BSS data
679 : * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
680 : * but interface may exist
681 : *
682 : * This function is used to initialize all per-BSS data structures and
683 : * resources. This gets called in a loop for each BSS when an interface is
684 : * initialized. Most of the modules that are initialized here will be
685 : * deinitialized in hostapd_cleanup().
686 : */
687 637 : static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
688 : {
689 637 : struct hostapd_bss_config *conf = hapd->conf;
690 : u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
691 : int ssid_len, set_ssid;
692 : char force_ifname[IFNAMSIZ];
693 : u8 if_addr[ETH_ALEN];
694 :
695 637 : wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
696 637 : __func__, hapd, conf->iface, first);
697 :
698 : #ifdef EAP_SERVER_TNC
699 637 : if (conf->tnc && tncs_global_init() < 0) {
700 0 : wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
701 0 : return -1;
702 : }
703 : #endif /* EAP_SERVER_TNC */
704 :
705 637 : if (hapd->started) {
706 0 : wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
707 0 : __func__, conf->iface);
708 0 : return -1;
709 : }
710 637 : hapd->started = 1;
711 :
712 637 : if (!first || first == -1) {
713 19 : if (hostapd_mac_comp_empty(conf->bssid) == 0) {
714 : /* Allocate the next available BSSID. */
715 : do {
716 0 : inc_byte_array(hapd->own_addr, ETH_ALEN);
717 0 : } while (mac_in_conf(hapd->iconf, hapd->own_addr));
718 : } else {
719 : /* Allocate the configured BSSID. */
720 19 : os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
721 :
722 19 : if (hostapd_mac_comp(hapd->own_addr,
723 19 : hapd->iface->bss[0]->own_addr) ==
724 : 0) {
725 0 : wpa_printf(MSG_ERROR, "BSS '%s' may not have "
726 : "BSSID set to the MAC address of "
727 0 : "the radio", conf->iface);
728 0 : return -1;
729 : }
730 : }
731 :
732 19 : hapd->interface_added = 1;
733 57 : if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
734 19 : conf->iface, hapd->own_addr, hapd,
735 : &hapd->drv_priv, force_ifname, if_addr,
736 19 : conf->bridge[0] ? conf->bridge : NULL,
737 : first == -1)) {
738 0 : wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
739 0 : MACSTR ")", MAC2STR(hapd->own_addr));
740 0 : hapd->interface_added = 0;
741 0 : return -1;
742 : }
743 : }
744 :
745 637 : if (conf->wmm_enabled < 0)
746 628 : conf->wmm_enabled = hapd->iconf->ieee80211n;
747 :
748 637 : hostapd_flush_old_stations(hapd, WLAN_REASON_PREV_AUTH_NOT_VALID);
749 637 : hostapd_set_privacy(hapd, 0);
750 :
751 637 : hostapd_broadcast_wep_clear(hapd);
752 637 : if (hostapd_setup_encryption(conf->iface, hapd))
753 0 : return -1;
754 :
755 : /*
756 : * Fetch the SSID from the system and use it or,
757 : * if one was specified in the config file, verify they
758 : * match.
759 : */
760 637 : ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
761 637 : if (ssid_len < 0) {
762 0 : wpa_printf(MSG_ERROR, "Could not read SSID from system");
763 0 : return -1;
764 : }
765 637 : if (conf->ssid.ssid_set) {
766 : /*
767 : * If SSID is specified in the config file and it differs
768 : * from what is being used then force installation of the
769 : * new SSID.
770 : */
771 637 : set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
772 0 : os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
773 : } else {
774 : /*
775 : * No SSID in the config file; just use the one we got
776 : * from the system.
777 : */
778 0 : set_ssid = 0;
779 0 : conf->ssid.ssid_len = ssid_len;
780 0 : os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
781 : }
782 :
783 637 : if (!hostapd_drv_none(hapd)) {
784 5733 : wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
785 : " and ssid \"%s\"",
786 4459 : conf->iface, MAC2STR(hapd->own_addr),
787 637 : wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
788 : }
789 :
790 637 : if (hostapd_setup_wpa_psk(conf)) {
791 4 : wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
792 4 : return -1;
793 : }
794 :
795 : /* Set SSID for the kernel driver (to be used in beacon and probe
796 : * response frames) */
797 633 : if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid,
798 : conf->ssid.ssid_len)) {
799 0 : wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
800 0 : return -1;
801 : }
802 :
803 633 : if (wpa_debug_level <= MSG_MSGDUMP)
804 633 : conf->radius->msg_dumps = 1;
805 : #ifndef CONFIG_NO_RADIUS
806 633 : hapd->radius = radius_client_init(hapd, conf->radius);
807 633 : if (hapd->radius == NULL) {
808 0 : wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
809 0 : return -1;
810 : }
811 :
812 633 : if (conf->radius_das_port) {
813 : struct radius_das_conf das_conf;
814 2 : os_memset(&das_conf, 0, sizeof(das_conf));
815 2 : das_conf.port = conf->radius_das_port;
816 2 : das_conf.shared_secret = conf->radius_das_shared_secret;
817 2 : das_conf.shared_secret_len =
818 2 : conf->radius_das_shared_secret_len;
819 2 : das_conf.client_addr = &conf->radius_das_client_addr;
820 2 : das_conf.time_window = conf->radius_das_time_window;
821 2 : das_conf.require_event_timestamp =
822 2 : conf->radius_das_require_event_timestamp;
823 2 : das_conf.ctx = hapd;
824 2 : das_conf.disconnect = hostapd_das_disconnect;
825 2 : hapd->radius_das = radius_das_init(&das_conf);
826 2 : if (hapd->radius_das == NULL) {
827 0 : wpa_printf(MSG_ERROR, "RADIUS DAS initialization "
828 : "failed.");
829 0 : return -1;
830 : }
831 : }
832 : #endif /* CONFIG_NO_RADIUS */
833 :
834 633 : if (hostapd_acl_init(hapd)) {
835 0 : wpa_printf(MSG_ERROR, "ACL initialization failed.");
836 0 : return -1;
837 : }
838 633 : if (hostapd_init_wps(hapd, conf))
839 0 : return -1;
840 :
841 633 : if (authsrv_init(hapd) < 0)
842 0 : return -1;
843 :
844 633 : if (ieee802_1x_init(hapd)) {
845 0 : wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
846 0 : return -1;
847 : }
848 :
849 633 : if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd))
850 0 : return -1;
851 :
852 633 : if (accounting_init(hapd)) {
853 0 : wpa_printf(MSG_ERROR, "Accounting initialization failed.");
854 0 : return -1;
855 : }
856 :
857 633 : if (conf->ieee802_11f &&
858 0 : (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
859 0 : wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
860 : "failed.");
861 0 : return -1;
862 : }
863 :
864 : #ifdef CONFIG_INTERWORKING
865 633 : if (gas_serv_init(hapd)) {
866 0 : wpa_printf(MSG_ERROR, "GAS server initialization failed");
867 0 : return -1;
868 : }
869 :
870 634 : if (conf->qos_map_set_len &&
871 1 : hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
872 1 : conf->qos_map_set_len)) {
873 0 : wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
874 0 : return -1;
875 : }
876 : #endif /* CONFIG_INTERWORKING */
877 :
878 633 : if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
879 0 : wpa_printf(MSG_ERROR, "VLAN initialization failed.");
880 0 : return -1;
881 : }
882 :
883 633 : if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
884 0 : return -1;
885 :
886 633 : if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
887 0 : return -1;
888 :
889 633 : if (hapd->driver && hapd->driver->set_operstate)
890 633 : hapd->driver->set_operstate(hapd->drv_priv, 1);
891 :
892 633 : return 0;
893 : }
894 :
895 :
896 614 : static void hostapd_tx_queue_params(struct hostapd_iface *iface)
897 : {
898 614 : struct hostapd_data *hapd = iface->bss[0];
899 : int i;
900 : struct hostapd_tx_queue_params *p;
901 :
902 3070 : for (i = 0; i < NUM_TX_QUEUES; i++) {
903 2456 : p = &iface->conf->tx_queue[i];
904 :
905 2456 : if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
906 : p->cwmax, p->burst)) {
907 0 : wpa_printf(MSG_DEBUG, "Failed to set TX queue "
908 : "parameters for queue %d.", i);
909 : /* Continue anyway */
910 : }
911 : }
912 614 : }
913 :
914 :
915 0 : static int hostapd_set_acl_list(struct hostapd_data *hapd,
916 : struct mac_acl_entry *mac_acl,
917 : int n_entries, u8 accept_acl)
918 : {
919 : struct hostapd_acl_params *acl_params;
920 : int i, err;
921 :
922 0 : acl_params = os_zalloc(sizeof(*acl_params) +
923 0 : (n_entries * sizeof(acl_params->mac_acl[0])));
924 0 : if (!acl_params)
925 0 : return -ENOMEM;
926 :
927 0 : for (i = 0; i < n_entries; i++)
928 0 : os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
929 : ETH_ALEN);
930 :
931 0 : acl_params->acl_policy = accept_acl;
932 0 : acl_params->num_mac_acl = n_entries;
933 :
934 0 : err = hostapd_drv_set_acl(hapd, acl_params);
935 :
936 0 : os_free(acl_params);
937 :
938 0 : return err;
939 : }
940 :
941 :
942 614 : static void hostapd_set_acl(struct hostapd_data *hapd)
943 : {
944 614 : struct hostapd_config *conf = hapd->iconf;
945 : int err;
946 : u8 accept_acl;
947 :
948 614 : if (hapd->iface->drv_max_acl_mac_addrs == 0)
949 614 : return;
950 :
951 0 : if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) {
952 0 : accept_acl = 1;
953 0 : err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac,
954 0 : conf->bss[0]->num_accept_mac,
955 : accept_acl);
956 0 : if (err) {
957 0 : wpa_printf(MSG_DEBUG, "Failed to set accept acl");
958 0 : return;
959 : }
960 0 : } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) {
961 0 : accept_acl = 0;
962 0 : err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac,
963 0 : conf->bss[0]->num_deny_mac,
964 : accept_acl);
965 0 : if (err) {
966 0 : wpa_printf(MSG_DEBUG, "Failed to set deny acl");
967 0 : return;
968 : }
969 : }
970 : }
971 :
972 :
973 14 : static int start_ctrl_iface_bss(struct hostapd_data *hapd)
974 : {
975 28 : if (!hapd->iface->interfaces ||
976 14 : !hapd->iface->interfaces->ctrl_iface_init)
977 0 : return 0;
978 :
979 14 : if (hapd->iface->interfaces->ctrl_iface_init(hapd)) {
980 0 : wpa_printf(MSG_ERROR,
981 : "Failed to setup control interface for %s",
982 0 : hapd->conf->iface);
983 0 : return -1;
984 : }
985 :
986 14 : return 0;
987 : }
988 :
989 :
990 1255 : static int start_ctrl_iface(struct hostapd_iface *iface)
991 : {
992 : size_t i;
993 :
994 1255 : if (!iface->interfaces || !iface->interfaces->ctrl_iface_init)
995 0 : return 0;
996 :
997 2523 : for (i = 0; i < iface->num_bss; i++) {
998 1268 : struct hostapd_data *hapd = iface->bss[i];
999 1268 : if (iface->interfaces->ctrl_iface_init(hapd)) {
1000 0 : wpa_printf(MSG_ERROR,
1001 : "Failed to setup control interface for %s",
1002 0 : hapd->conf->iface);
1003 0 : return -1;
1004 : }
1005 : }
1006 :
1007 1255 : return 0;
1008 : }
1009 :
1010 :
1011 0 : static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx)
1012 : {
1013 0 : struct hostapd_iface *iface = eloop_ctx;
1014 :
1015 0 : if (!iface->wait_channel_update) {
1016 0 : wpa_printf(MSG_INFO, "Channel list update timeout, but interface was not waiting for it");
1017 0 : return;
1018 : }
1019 :
1020 : /*
1021 : * It is possible that the existing channel list is acceptable, so try
1022 : * to proceed.
1023 : */
1024 0 : wpa_printf(MSG_DEBUG, "Channel list update timeout - try to continue anyway");
1025 0 : setup_interface2(iface);
1026 : }
1027 :
1028 :
1029 800 : void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator)
1030 : {
1031 800 : if (!iface->wait_channel_update || initiator != REGDOM_SET_BY_USER)
1032 1579 : return;
1033 :
1034 21 : wpa_printf(MSG_DEBUG, "Channel list updated - continue setup");
1035 21 : eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
1036 21 : setup_interface2(iface);
1037 : }
1038 :
1039 :
1040 631 : static int setup_interface(struct hostapd_iface *iface)
1041 : {
1042 631 : struct hostapd_data *hapd = iface->bss[0];
1043 : size_t i;
1044 :
1045 : /*
1046 : * It is possible that setup_interface() is called after the interface
1047 : * was disabled etc., in which case driver_ap_teardown is possibly set
1048 : * to 1. Clear it here so any other key/station deletion, which is not
1049 : * part of a teardown flow, would also call the relevant driver
1050 : * callbacks.
1051 : */
1052 631 : iface->driver_ap_teardown = 0;
1053 :
1054 631 : if (!iface->phy[0]) {
1055 616 : const char *phy = hostapd_drv_get_radio_name(hapd);
1056 616 : if (phy) {
1057 616 : wpa_printf(MSG_DEBUG, "phy: %s", phy);
1058 616 : os_strlcpy(iface->phy, phy, sizeof(iface->phy));
1059 : }
1060 : }
1061 :
1062 : /*
1063 : * Make sure that all BSSes get configured with a pointer to the same
1064 : * driver interface.
1065 : */
1066 638 : for (i = 1; i < iface->num_bss; i++) {
1067 7 : iface->bss[i]->driver = hapd->driver;
1068 7 : iface->bss[i]->drv_priv = hapd->drv_priv;
1069 : }
1070 :
1071 631 : if (hostapd_validate_bssid_configuration(iface))
1072 0 : return -1;
1073 :
1074 : /*
1075 : * Initialize control interfaces early to allow external monitoring of
1076 : * channel setup operations that may take considerable amount of time
1077 : * especially for DFS cases.
1078 : */
1079 631 : if (start_ctrl_iface(iface))
1080 0 : return -1;
1081 :
1082 631 : if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
1083 : char country[4], previous_country[4];
1084 :
1085 24 : hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE);
1086 24 : if (hostapd_get_country(hapd, previous_country) < 0)
1087 0 : previous_country[0] = '\0';
1088 :
1089 24 : os_memcpy(country, hapd->iconf->country, 3);
1090 24 : country[3] = '\0';
1091 24 : if (hostapd_set_country(hapd, country) < 0) {
1092 0 : wpa_printf(MSG_ERROR, "Failed to set country code");
1093 21 : return -1;
1094 : }
1095 :
1096 24 : wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s",
1097 : previous_country, country);
1098 :
1099 24 : if (os_strncmp(previous_country, country, 2) != 0) {
1100 21 : wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update");
1101 21 : iface->wait_channel_update = 1;
1102 21 : eloop_register_timeout(5, 0,
1103 : channel_list_update_timeout,
1104 : iface, NULL);
1105 21 : return 0;
1106 : }
1107 : }
1108 :
1109 610 : return setup_interface2(iface);
1110 : }
1111 :
1112 :
1113 631 : static int setup_interface2(struct hostapd_iface *iface)
1114 : {
1115 631 : iface->wait_channel_update = 0;
1116 :
1117 631 : if (hostapd_get_hw_features(iface)) {
1118 : /* Not all drivers support this yet, so continue without hw
1119 : * feature data. */
1120 : } else {
1121 631 : int ret = hostapd_select_hw_mode(iface);
1122 631 : if (ret < 0) {
1123 2 : wpa_printf(MSG_ERROR, "Could not select hw_mode and "
1124 : "channel. (%d)", ret);
1125 2 : goto fail;
1126 : }
1127 629 : if (ret == 1) {
1128 9 : wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
1129 9 : return 0;
1130 : }
1131 620 : ret = hostapd_check_ht_capab(iface);
1132 620 : if (ret < 0)
1133 2 : goto fail;
1134 618 : if (ret == 1) {
1135 30 : wpa_printf(MSG_DEBUG, "Interface initialization will "
1136 : "be completed in a callback");
1137 30 : return 0;
1138 : }
1139 :
1140 588 : if (iface->conf->ieee80211h)
1141 2 : wpa_printf(MSG_DEBUG, "DFS support is enabled");
1142 : }
1143 588 : return hostapd_setup_interface_complete(iface, 0);
1144 :
1145 : fail:
1146 4 : hostapd_set_state(iface, HAPD_IFACE_DISABLED);
1147 4 : wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
1148 4 : if (iface->interfaces && iface->interfaces->terminate_on_error)
1149 0 : eloop_terminate();
1150 4 : return -1;
1151 : }
1152 :
1153 :
1154 : /**
1155 : * hostapd_setup_interface_complete - Complete interface setup
1156 : *
1157 : * This function is called when previous steps in the interface setup has been
1158 : * completed. This can also start operations, e.g., DFS, that will require
1159 : * additional processing before interface is ready to be enabled. Such
1160 : * operations will call this function from eloop callbacks when finished.
1161 : */
1162 627 : int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
1163 : {
1164 627 : struct hostapd_data *hapd = iface->bss[0];
1165 : size_t j;
1166 : u8 *prev_addr;
1167 :
1168 627 : if (err)
1169 3 : goto fail;
1170 :
1171 624 : wpa_printf(MSG_DEBUG, "Completing interface initialization");
1172 624 : if (iface->conf->channel) {
1173 : #ifdef NEED_AP_MLME
1174 : int res;
1175 : #endif /* NEED_AP_MLME */
1176 :
1177 624 : iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
1178 1872 : wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
1179 : "Frequency: %d MHz",
1180 624 : hostapd_hw_mode_txt(iface->conf->hw_mode),
1181 624 : iface->conf->channel, iface->freq);
1182 :
1183 : #ifdef NEED_AP_MLME
1184 : /* Handle DFS only if it is not offloaded to the driver */
1185 624 : if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
1186 : /* Check DFS */
1187 624 : res = hostapd_handle_dfs(iface);
1188 624 : if (res <= 0) {
1189 6 : if (res < 0)
1190 1 : goto fail;
1191 5 : return res;
1192 : }
1193 : }
1194 : #endif /* NEED_AP_MLME */
1195 :
1196 4326 : if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
1197 618 : hapd->iconf->channel,
1198 618 : hapd->iconf->ieee80211n,
1199 618 : hapd->iconf->ieee80211ac,
1200 618 : hapd->iconf->secondary_channel,
1201 618 : hapd->iconf->vht_oper_chwidth,
1202 618 : hapd->iconf->vht_oper_centr_freq_seg0_idx,
1203 618 : hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
1204 0 : wpa_printf(MSG_ERROR, "Could not set channel for "
1205 : "kernel driver");
1206 0 : goto fail;
1207 : }
1208 : }
1209 :
1210 618 : if (iface->current_mode) {
1211 618 : if (hostapd_prepare_rates(iface, iface->current_mode)) {
1212 0 : wpa_printf(MSG_ERROR, "Failed to prepare rates "
1213 : "table.");
1214 0 : hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1215 : HOSTAPD_LEVEL_WARNING,
1216 : "Failed to prepare rates table.");
1217 0 : goto fail;
1218 : }
1219 : }
1220 :
1221 619 : if (hapd->iconf->rts_threshold > -1 &&
1222 1 : hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
1223 0 : wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
1224 : "kernel driver");
1225 0 : goto fail;
1226 : }
1227 :
1228 621 : if (hapd->iconf->fragm_threshold > -1 &&
1229 3 : hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
1230 0 : wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
1231 : "for kernel driver");
1232 0 : goto fail;
1233 : }
1234 :
1235 618 : prev_addr = hapd->own_addr;
1236 :
1237 1240 : for (j = 0; j < iface->num_bss; j++) {
1238 626 : hapd = iface->bss[j];
1239 626 : if (j)
1240 8 : os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
1241 626 : if (hostapd_setup_bss(hapd, j == 0)) {
1242 : do {
1243 4 : hapd = iface->bss[j];
1244 4 : hostapd_bss_deinit_no_free(hapd);
1245 4 : hostapd_free_hapd_data(hapd);
1246 4 : } while (j-- > 0);
1247 4 : goto fail;
1248 : }
1249 622 : if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
1250 607 : prev_addr = hapd->own_addr;
1251 : }
1252 614 : hapd = iface->bss[0];
1253 :
1254 614 : hostapd_tx_queue_params(iface);
1255 :
1256 614 : ap_list_init(iface);
1257 :
1258 614 : hostapd_set_acl(hapd);
1259 :
1260 614 : if (hostapd_driver_commit(hapd) < 0) {
1261 0 : wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
1262 : "configuration", __func__);
1263 0 : goto fail;
1264 : }
1265 :
1266 : /*
1267 : * WPS UPnP module can be initialized only when the "upnp_iface" is up.
1268 : * If "interface" and "upnp_iface" are the same (e.g., non-bridge
1269 : * mode), the interface is up only after driver_commit, so initialize
1270 : * WPS after driver_commit.
1271 : */
1272 1236 : for (j = 0; j < iface->num_bss; j++) {
1273 622 : if (hostapd_init_wps_complete(iface->bss[j]))
1274 0 : goto fail;
1275 : }
1276 :
1277 614 : hostapd_set_state(iface, HAPD_IFACE_ENABLED);
1278 614 : wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
1279 614 : if (hapd->setup_complete_cb)
1280 0 : hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
1281 :
1282 614 : wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
1283 614 : iface->bss[0]->conf->iface);
1284 614 : if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
1285 0 : iface->interfaces->terminate_on_error--;
1286 :
1287 614 : return 0;
1288 :
1289 : fail:
1290 8 : wpa_printf(MSG_ERROR, "Interface initialization failed");
1291 8 : hostapd_set_state(iface, HAPD_IFACE_DISABLED);
1292 8 : wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
1293 8 : if (iface->interfaces && iface->interfaces->terminate_on_error)
1294 0 : eloop_terminate();
1295 8 : return -1;
1296 : }
1297 :
1298 :
1299 : /**
1300 : * hostapd_setup_interface - Setup of an interface
1301 : * @iface: Pointer to interface data.
1302 : * Returns: 0 on success, -1 on failure
1303 : *
1304 : * Initializes the driver interface, validates the configuration,
1305 : * and sets driver parameters based on the configuration.
1306 : * Flushes old stations, sets the channel, encryption,
1307 : * beacons, and WDS links based on the configuration.
1308 : *
1309 : * If interface setup requires more time, e.g., to perform HT co-ex scans, ACS,
1310 : * or DFS operations, this function returns 0 before such operations have been
1311 : * completed. The pending operations are registered into eloop and will be
1312 : * completed from eloop callbacks. Those callbacks end up calling
1313 : * hostapd_setup_interface_complete() once setup has been completed.
1314 : */
1315 631 : int hostapd_setup_interface(struct hostapd_iface *iface)
1316 : {
1317 : int ret;
1318 :
1319 631 : ret = setup_interface(iface);
1320 631 : if (ret) {
1321 7 : wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
1322 7 : iface->bss[0]->conf->iface);
1323 7 : return -1;
1324 : }
1325 :
1326 624 : return 0;
1327 : }
1328 :
1329 :
1330 : /**
1331 : * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
1332 : * @hapd_iface: Pointer to interface data
1333 : * @conf: Pointer to per-interface configuration
1334 : * @bss: Pointer to per-BSS configuration for this BSS
1335 : * Returns: Pointer to allocated BSS data
1336 : *
1337 : * This function is used to allocate per-BSS data structure. This data will be
1338 : * freed after hostapd_cleanup() is called for it during interface
1339 : * deinitialization.
1340 : */
1341 : struct hostapd_data *
1342 652 : hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
1343 : struct hostapd_config *conf,
1344 : struct hostapd_bss_config *bss)
1345 : {
1346 : struct hostapd_data *hapd;
1347 :
1348 652 : hapd = os_zalloc(sizeof(*hapd));
1349 652 : if (hapd == NULL)
1350 0 : return NULL;
1351 :
1352 652 : hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
1353 652 : hapd->iconf = conf;
1354 652 : hapd->conf = bss;
1355 652 : hapd->iface = hapd_iface;
1356 652 : hapd->driver = hapd->iconf->driver;
1357 652 : hapd->ctrl_sock = -1;
1358 :
1359 652 : return hapd;
1360 : }
1361 :
1362 :
1363 652 : static void hostapd_bss_deinit(struct hostapd_data *hapd)
1364 : {
1365 652 : wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
1366 652 : hapd->conf->iface);
1367 652 : hostapd_bss_deinit_no_free(hapd);
1368 652 : hostapd_cleanup(hapd);
1369 652 : }
1370 :
1371 :
1372 632 : void hostapd_interface_deinit(struct hostapd_iface *iface)
1373 : {
1374 : int j;
1375 :
1376 632 : wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
1377 632 : if (iface == NULL)
1378 632 : return;
1379 :
1380 : #ifdef CONFIG_IEEE80211N
1381 : #ifdef NEED_AP_MLME
1382 632 : hostapd_stop_setup_timers(iface);
1383 632 : eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
1384 : #endif /* NEED_AP_MLME */
1385 : #endif /* CONFIG_IEEE80211N */
1386 632 : eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
1387 632 : iface->wait_channel_update = 0;
1388 :
1389 1269 : for (j = iface->num_bss - 1; j >= 0; j--)
1390 637 : hostapd_bss_deinit(iface->bss[j]);
1391 : }
1392 :
1393 :
1394 632 : void hostapd_interface_free(struct hostapd_iface *iface)
1395 : {
1396 : size_t j;
1397 632 : wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
1398 1269 : for (j = 0; j < iface->num_bss; j++) {
1399 637 : wpa_printf(MSG_DEBUG, "%s: free hapd %p",
1400 637 : __func__, iface->bss[j]);
1401 637 : os_free(iface->bss[j]);
1402 : }
1403 632 : hostapd_cleanup_iface(iface);
1404 632 : }
1405 :
1406 :
1407 : /**
1408 : * hostapd_init - Allocate and initialize per-interface data
1409 : * @config_file: Path to the configuration file
1410 : * Returns: Pointer to the allocated interface data or %NULL on failure
1411 : *
1412 : * This function is used to allocate main data structures for per-interface
1413 : * data. The allocated data buffer will be freed by calling
1414 : * hostapd_cleanup_iface().
1415 : */
1416 8 : struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
1417 : const char *config_file)
1418 : {
1419 8 : struct hostapd_iface *hapd_iface = NULL;
1420 8 : struct hostapd_config *conf = NULL;
1421 : struct hostapd_data *hapd;
1422 : size_t i;
1423 :
1424 8 : hapd_iface = os_zalloc(sizeof(*hapd_iface));
1425 8 : if (hapd_iface == NULL)
1426 0 : goto fail;
1427 :
1428 8 : hapd_iface->config_fname = os_strdup(config_file);
1429 8 : if (hapd_iface->config_fname == NULL)
1430 0 : goto fail;
1431 :
1432 8 : conf = interfaces->config_read_cb(hapd_iface->config_fname);
1433 8 : if (conf == NULL)
1434 0 : goto fail;
1435 8 : hapd_iface->conf = conf;
1436 :
1437 8 : hapd_iface->num_bss = conf->num_bss;
1438 8 : hapd_iface->bss = os_calloc(conf->num_bss,
1439 : sizeof(struct hostapd_data *));
1440 8 : if (hapd_iface->bss == NULL)
1441 0 : goto fail;
1442 :
1443 16 : for (i = 0; i < conf->num_bss; i++) {
1444 16 : hapd = hapd_iface->bss[i] =
1445 8 : hostapd_alloc_bss_data(hapd_iface, conf,
1446 8 : conf->bss[i]);
1447 8 : if (hapd == NULL)
1448 0 : goto fail;
1449 8 : hapd->msg_ctx = hapd;
1450 : }
1451 :
1452 8 : return hapd_iface;
1453 :
1454 : fail:
1455 0 : wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
1456 : config_file);
1457 0 : if (conf)
1458 0 : hostapd_config_free(conf);
1459 0 : if (hapd_iface) {
1460 0 : os_free(hapd_iface->config_fname);
1461 0 : os_free(hapd_iface->bss);
1462 0 : wpa_printf(MSG_DEBUG, "%s: free iface %p",
1463 : __func__, hapd_iface);
1464 0 : os_free(hapd_iface);
1465 : }
1466 0 : return NULL;
1467 : }
1468 :
1469 :
1470 15 : static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname)
1471 : {
1472 : size_t i, j;
1473 :
1474 29 : for (i = 0; i < interfaces->count; i++) {
1475 15 : struct hostapd_iface *iface = interfaces->iface[i];
1476 37 : for (j = 0; j < iface->num_bss; j++) {
1477 23 : struct hostapd_data *hapd = iface->bss[j];
1478 23 : if (os_strcmp(ifname, hapd->conf->iface) == 0)
1479 1 : return 1;
1480 : }
1481 : }
1482 :
1483 14 : return 0;
1484 : }
1485 :
1486 :
1487 : /**
1488 : * hostapd_interface_init_bss - Read configuration file and init BSS data
1489 : *
1490 : * This function is used to parse configuration file for a BSS. This BSS is
1491 : * added to an existing interface sharing the same radio (if any) or a new
1492 : * interface is created if this is the first interface on a radio. This
1493 : * allocate memory for the BSS. No actual driver operations are started.
1494 : *
1495 : * This is similar to hostapd_interface_init(), but for a case where the
1496 : * configuration is used to add a single BSS instead of all BSSes for a radio.
1497 : */
1498 : struct hostapd_iface *
1499 23 : hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
1500 : const char *config_fname, int debug)
1501 : {
1502 23 : struct hostapd_iface *new_iface = NULL, *iface = NULL;
1503 : struct hostapd_data *hapd;
1504 : int k;
1505 : size_t i, bss_idx;
1506 :
1507 23 : if (!phy || !*phy)
1508 0 : return NULL;
1509 :
1510 23 : for (i = 0; i < interfaces->count; i++) {
1511 15 : if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) {
1512 15 : iface = interfaces->iface[i];
1513 15 : break;
1514 : }
1515 : }
1516 :
1517 23 : wpa_printf(MSG_INFO, "Configuration file: %s (phy %s)%s",
1518 : config_fname, phy, iface ? "" : " --> new PHY");
1519 23 : if (iface) {
1520 : struct hostapd_config *conf;
1521 : struct hostapd_bss_config **tmp_conf;
1522 : struct hostapd_data **tmp_bss;
1523 : struct hostapd_bss_config *bss;
1524 : const char *ifname;
1525 :
1526 : /* Add new BSS to existing iface */
1527 15 : conf = interfaces->config_read_cb(config_fname);
1528 15 : if (conf == NULL)
1529 0 : return NULL;
1530 15 : if (conf->num_bss > 1) {
1531 0 : wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config");
1532 0 : hostapd_config_free(conf);
1533 0 : return NULL;
1534 : }
1535 :
1536 15 : ifname = conf->bss[0]->iface;
1537 15 : if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) {
1538 1 : wpa_printf(MSG_ERROR,
1539 : "Interface name %s already in use", ifname);
1540 1 : hostapd_config_free(conf);
1541 1 : return NULL;
1542 : }
1543 :
1544 28 : tmp_conf = os_realloc_array(
1545 28 : iface->conf->bss, iface->conf->num_bss + 1,
1546 : sizeof(struct hostapd_bss_config *));
1547 14 : tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1,
1548 : sizeof(struct hostapd_data *));
1549 14 : if (tmp_bss)
1550 14 : iface->bss = tmp_bss;
1551 14 : if (tmp_conf) {
1552 14 : iface->conf->bss = tmp_conf;
1553 14 : iface->conf->last_bss = tmp_conf[0];
1554 : }
1555 14 : if (tmp_bss == NULL || tmp_conf == NULL) {
1556 0 : hostapd_config_free(conf);
1557 0 : return NULL;
1558 : }
1559 14 : bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0];
1560 14 : iface->conf->num_bss++;
1561 :
1562 14 : hapd = hostapd_alloc_bss_data(iface, iface->conf, bss);
1563 14 : if (hapd == NULL) {
1564 0 : iface->conf->num_bss--;
1565 0 : hostapd_config_free(conf);
1566 0 : return NULL;
1567 : }
1568 14 : iface->conf->last_bss = bss;
1569 14 : iface->bss[iface->num_bss] = hapd;
1570 14 : hapd->msg_ctx = hapd;
1571 :
1572 14 : bss_idx = iface->num_bss++;
1573 14 : conf->num_bss--;
1574 14 : conf->bss[0] = NULL;
1575 14 : hostapd_config_free(conf);
1576 : } else {
1577 : /* Add a new iface with the first BSS */
1578 8 : new_iface = iface = hostapd_init(interfaces, config_fname);
1579 8 : if (!iface)
1580 0 : return NULL;
1581 8 : os_strlcpy(iface->phy, phy, sizeof(iface->phy));
1582 8 : iface->interfaces = interfaces;
1583 8 : bss_idx = 0;
1584 : }
1585 :
1586 22 : for (k = 0; k < debug; k++) {
1587 0 : if (iface->bss[bss_idx]->conf->logger_stdout_level > 0)
1588 0 : iface->bss[bss_idx]->conf->logger_stdout_level--;
1589 : }
1590 :
1591 22 : if (iface->conf->bss[bss_idx]->iface[0] == '\0' &&
1592 0 : !hostapd_drv_none(iface->bss[bss_idx])) {
1593 0 : wpa_printf(MSG_ERROR, "Interface name not specified in %s",
1594 : config_fname);
1595 0 : if (new_iface)
1596 0 : hostapd_interface_deinit_free(new_iface);
1597 0 : return NULL;
1598 : }
1599 :
1600 22 : return iface;
1601 : }
1602 :
1603 :
1604 632 : void hostapd_interface_deinit_free(struct hostapd_iface *iface)
1605 : {
1606 : const struct wpa_driver_ops *driver;
1607 : void *drv_priv;
1608 :
1609 632 : wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
1610 632 : if (iface == NULL)
1611 632 : return;
1612 1264 : wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u",
1613 632 : __func__, (unsigned int) iface->num_bss,
1614 632 : (unsigned int) iface->conf->num_bss);
1615 632 : driver = iface->bss[0]->driver;
1616 632 : drv_priv = iface->bss[0]->drv_priv;
1617 632 : hostapd_interface_deinit(iface);
1618 632 : wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
1619 : __func__, driver, drv_priv);
1620 632 : if (driver && driver->hapd_deinit && drv_priv) {
1621 615 : driver->hapd_deinit(drv_priv);
1622 615 : iface->bss[0]->drv_priv = NULL;
1623 : }
1624 632 : hostapd_interface_free(iface);
1625 : }
1626 :
1627 :
1628 16 : static void hostapd_deinit_driver(const struct wpa_driver_ops *driver,
1629 : void *drv_priv,
1630 : struct hostapd_iface *hapd_iface)
1631 : {
1632 : size_t j;
1633 :
1634 16 : wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
1635 : __func__, driver, drv_priv);
1636 16 : if (driver && driver->hapd_deinit && drv_priv) {
1637 16 : driver->hapd_deinit(drv_priv);
1638 34 : for (j = 0; j < hapd_iface->num_bss; j++) {
1639 18 : wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
1640 : __func__, (int) j,
1641 18 : hapd_iface->bss[j]->drv_priv);
1642 18 : if (hapd_iface->bss[j]->drv_priv == drv_priv)
1643 16 : hapd_iface->bss[j]->drv_priv = NULL;
1644 : }
1645 : }
1646 16 : }
1647 :
1648 :
1649 631 : int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
1650 : {
1651 : size_t j;
1652 :
1653 631 : if (hapd_iface->bss[0]->drv_priv != NULL) {
1654 0 : wpa_printf(MSG_ERROR, "Interface %s already enabled",
1655 0 : hapd_iface->conf->bss[0]->iface);
1656 0 : return -1;
1657 : }
1658 :
1659 631 : wpa_printf(MSG_DEBUG, "Enable interface %s",
1660 631 : hapd_iface->conf->bss[0]->iface);
1661 :
1662 1269 : for (j = 0; j < hapd_iface->num_bss; j++)
1663 638 : hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
1664 631 : if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
1665 8 : wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
1666 8 : return -1;
1667 : }
1668 :
1669 1246 : if (hapd_iface->interfaces == NULL ||
1670 1246 : hapd_iface->interfaces->driver_init == NULL ||
1671 623 : hapd_iface->interfaces->driver_init(hapd_iface))
1672 0 : return -1;
1673 :
1674 623 : if (hostapd_setup_interface(hapd_iface)) {
1675 7 : hostapd_deinit_driver(hapd_iface->bss[0]->driver,
1676 7 : hapd_iface->bss[0]->drv_priv,
1677 : hapd_iface);
1678 7 : return -1;
1679 : }
1680 :
1681 616 : return 0;
1682 : }
1683 :
1684 :
1685 1 : int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
1686 : {
1687 : size_t j;
1688 :
1689 1 : wpa_printf(MSG_DEBUG, "Reload interface %s",
1690 1 : hapd_iface->conf->bss[0]->iface);
1691 2 : for (j = 0; j < hapd_iface->num_bss; j++)
1692 1 : hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
1693 1 : if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
1694 0 : wpa_printf(MSG_ERROR, "Updated configuration is invalid");
1695 0 : return -1;
1696 : }
1697 1 : hostapd_clear_old(hapd_iface);
1698 2 : for (j = 0; j < hapd_iface->num_bss; j++)
1699 1 : hostapd_reload_bss(hapd_iface->bss[j]);
1700 :
1701 1 : return 0;
1702 : }
1703 :
1704 :
1705 15 : int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
1706 : {
1707 : size_t j;
1708 : const struct wpa_driver_ops *driver;
1709 : void *drv_priv;
1710 :
1711 15 : if (hapd_iface == NULL)
1712 0 : return -1;
1713 :
1714 15 : if (hapd_iface->bss[0]->drv_priv == NULL) {
1715 6 : wpa_printf(MSG_INFO, "Interface %s already disabled",
1716 6 : hapd_iface->conf->bss[0]->iface);
1717 6 : return -1;
1718 : }
1719 :
1720 9 : wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
1721 9 : driver = hapd_iface->bss[0]->driver;
1722 9 : drv_priv = hapd_iface->bss[0]->drv_priv;
1723 :
1724 9 : hapd_iface->driver_ap_teardown =
1725 9 : !!(hapd_iface->drv_flags &
1726 : WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
1727 :
1728 : /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
1729 20 : for (j = 0; j < hapd_iface->num_bss; j++) {
1730 11 : struct hostapd_data *hapd = hapd_iface->bss[j];
1731 11 : hostapd_bss_deinit_no_free(hapd);
1732 11 : hostapd_free_hapd_data(hapd);
1733 : }
1734 :
1735 9 : hostapd_deinit_driver(driver, drv_priv, hapd_iface);
1736 :
1737 : /* From hostapd_cleanup_iface: These were initialized in
1738 : * hostapd_setup_interface and hostapd_setup_interface_complete
1739 : */
1740 9 : hostapd_cleanup_iface_partial(hapd_iface);
1741 :
1742 9 : wpa_printf(MSG_DEBUG, "Interface %s disabled",
1743 9 : hapd_iface->bss[0]->conf->iface);
1744 9 : hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED);
1745 9 : return 0;
1746 : }
1747 :
1748 :
1749 : static struct hostapd_iface *
1750 624 : hostapd_iface_alloc(struct hapd_interfaces *interfaces)
1751 : {
1752 : struct hostapd_iface **iface, *hapd_iface;
1753 :
1754 624 : iface = os_realloc_array(interfaces->iface, interfaces->count + 1,
1755 : sizeof(struct hostapd_iface *));
1756 624 : if (iface == NULL)
1757 0 : return NULL;
1758 624 : interfaces->iface = iface;
1759 1248 : hapd_iface = interfaces->iface[interfaces->count] =
1760 624 : os_zalloc(sizeof(*hapd_iface));
1761 624 : if (hapd_iface == NULL) {
1762 0 : wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
1763 : "the interface", __func__);
1764 0 : return NULL;
1765 : }
1766 624 : interfaces->count++;
1767 624 : hapd_iface->interfaces = interfaces;
1768 :
1769 624 : return hapd_iface;
1770 : }
1771 :
1772 :
1773 : static struct hostapd_config *
1774 621 : hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
1775 : const char *ctrl_iface)
1776 : {
1777 : struct hostapd_bss_config *bss;
1778 : struct hostapd_config *conf;
1779 :
1780 : /* Allocates memory for bss and conf */
1781 621 : conf = hostapd_config_defaults();
1782 621 : if (conf == NULL) {
1783 0 : wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
1784 : "configuration", __func__);
1785 0 : return NULL;
1786 : }
1787 :
1788 621 : conf->driver = wpa_drivers[0];
1789 621 : if (conf->driver == NULL) {
1790 0 : wpa_printf(MSG_ERROR, "No driver wrappers registered!");
1791 0 : hostapd_config_free(conf);
1792 0 : return NULL;
1793 : }
1794 :
1795 621 : bss = conf->last_bss = conf->bss[0];
1796 :
1797 621 : os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
1798 621 : bss->ctrl_interface = os_strdup(ctrl_iface);
1799 621 : if (bss->ctrl_interface == NULL) {
1800 0 : hostapd_config_free(conf);
1801 0 : return NULL;
1802 : }
1803 :
1804 : /* Reading configuration file skipped, will be done in SET!
1805 : * From reading the configuration till the end has to be done in
1806 : * SET
1807 : */
1808 621 : return conf;
1809 : }
1810 :
1811 :
1812 624 : static struct hostapd_iface * hostapd_data_alloc(
1813 : struct hapd_interfaces *interfaces, struct hostapd_config *conf)
1814 : {
1815 : size_t i;
1816 624 : struct hostapd_iface *hapd_iface =
1817 624 : interfaces->iface[interfaces->count - 1];
1818 : struct hostapd_data *hapd;
1819 :
1820 624 : hapd_iface->conf = conf;
1821 624 : hapd_iface->num_bss = conf->num_bss;
1822 :
1823 624 : hapd_iface->bss = os_zalloc(conf->num_bss *
1824 : sizeof(struct hostapd_data *));
1825 624 : if (hapd_iface->bss == NULL)
1826 0 : return NULL;
1827 :
1828 1254 : for (i = 0; i < conf->num_bss; i++) {
1829 1260 : hapd = hapd_iface->bss[i] =
1830 630 : hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
1831 630 : if (hapd == NULL)
1832 0 : return NULL;
1833 630 : hapd->msg_ctx = hapd;
1834 : }
1835 :
1836 624 : hapd_iface->interfaces = interfaces;
1837 :
1838 624 : return hapd_iface;
1839 : }
1840 :
1841 :
1842 647 : int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
1843 : {
1844 647 : struct hostapd_config *conf = NULL;
1845 647 : struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL;
1846 : struct hostapd_data *hapd;
1847 : char *ptr;
1848 : size_t i, j;
1849 647 : const char *conf_file = NULL, *phy_name = NULL;
1850 :
1851 647 : if (os_strncmp(buf, "bss_config=", 11) == 0) {
1852 : char *pos;
1853 23 : phy_name = buf + 11;
1854 23 : pos = os_strchr(phy_name, ':');
1855 23 : if (!pos)
1856 0 : return -1;
1857 23 : *pos++ = '\0';
1858 23 : conf_file = pos;
1859 23 : if (!os_strlen(conf_file))
1860 0 : return -1;
1861 :
1862 23 : hapd_iface = hostapd_interface_init_bss(interfaces, phy_name,
1863 : conf_file, 0);
1864 23 : if (!hapd_iface)
1865 1 : return -1;
1866 22 : for (j = 0; j < interfaces->count; j++) {
1867 14 : if (interfaces->iface[j] == hapd_iface)
1868 14 : break;
1869 : }
1870 22 : if (j == interfaces->count) {
1871 : struct hostapd_iface **tmp;
1872 8 : tmp = os_realloc_array(interfaces->iface,
1873 8 : interfaces->count + 1,
1874 : sizeof(struct hostapd_iface *));
1875 8 : if (!tmp) {
1876 0 : hostapd_interface_deinit_free(hapd_iface);
1877 0 : return -1;
1878 : }
1879 8 : interfaces->iface = tmp;
1880 8 : interfaces->iface[interfaces->count++] = hapd_iface;
1881 8 : new_iface = hapd_iface;
1882 : }
1883 :
1884 22 : if (new_iface) {
1885 16 : if (interfaces->driver_init(hapd_iface) ||
1886 8 : hostapd_setup_interface(hapd_iface)) {
1887 0 : interfaces->count--;
1888 0 : goto fail;
1889 : }
1890 : } else {
1891 : /* Assign new BSS with bss[0]'s driver info */
1892 14 : hapd = hapd_iface->bss[hapd_iface->num_bss - 1];
1893 14 : hapd->driver = hapd_iface->bss[0]->driver;
1894 14 : hapd->drv_priv = hapd_iface->bss[0]->drv_priv;
1895 14 : os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr,
1896 : ETH_ALEN);
1897 :
1898 28 : if (start_ctrl_iface_bss(hapd) < 0 ||
1899 25 : (hapd_iface->state == HAPD_IFACE_ENABLED &&
1900 11 : hostapd_setup_bss(hapd, -1))) {
1901 0 : hostapd_cleanup(hapd);
1902 0 : hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
1903 0 : hapd_iface->conf->num_bss--;
1904 0 : hapd_iface->num_bss--;
1905 0 : wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
1906 0 : __func__, hapd, hapd->conf->iface);
1907 0 : os_free(hapd);
1908 0 : return -1;
1909 : }
1910 : }
1911 22 : return 0;
1912 : }
1913 :
1914 624 : ptr = os_strchr(buf, ' ');
1915 624 : if (ptr == NULL)
1916 0 : return -1;
1917 624 : *ptr++ = '\0';
1918 :
1919 624 : if (os_strncmp(ptr, "config=", 7) == 0)
1920 3 : conf_file = ptr + 7;
1921 :
1922 703 : for (i = 0; i < interfaces->count; i++) {
1923 79 : if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface,
1924 : buf)) {
1925 0 : wpa_printf(MSG_INFO, "Cannot add interface - it "
1926 : "already exists");
1927 0 : return -1;
1928 : }
1929 : }
1930 :
1931 624 : hapd_iface = hostapd_iface_alloc(interfaces);
1932 624 : if (hapd_iface == NULL) {
1933 0 : wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
1934 : "for interface", __func__);
1935 0 : goto fail;
1936 : }
1937 :
1938 624 : if (conf_file && interfaces->config_read_cb) {
1939 3 : conf = interfaces->config_read_cb(conf_file);
1940 6 : if (conf && conf->bss)
1941 3 : os_strlcpy(conf->bss[0]->iface, buf,
1942 : sizeof(conf->bss[0]->iface));
1943 : } else
1944 621 : conf = hostapd_config_alloc(interfaces, buf, ptr);
1945 624 : if (conf == NULL || conf->bss == NULL) {
1946 0 : wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
1947 : "for configuration", __func__);
1948 0 : goto fail;
1949 : }
1950 :
1951 624 : hapd_iface = hostapd_data_alloc(interfaces, conf);
1952 624 : if (hapd_iface == NULL) {
1953 0 : wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
1954 : "for hostapd", __func__);
1955 0 : goto fail;
1956 : }
1957 :
1958 624 : if (start_ctrl_iface(hapd_iface) < 0)
1959 0 : goto fail;
1960 :
1961 624 : wpa_printf(MSG_INFO, "Add interface '%s'", conf->bss[0]->iface);
1962 :
1963 624 : return 0;
1964 :
1965 : fail:
1966 0 : if (conf)
1967 0 : hostapd_config_free(conf);
1968 0 : if (hapd_iface) {
1969 0 : if (hapd_iface->bss) {
1970 0 : for (i = 0; i < hapd_iface->num_bss; i++) {
1971 0 : hapd = hapd_iface->bss[i];
1972 0 : if (!hapd)
1973 0 : continue;
1974 0 : if (hapd_iface->interfaces &&
1975 0 : hapd_iface->interfaces->ctrl_iface_deinit)
1976 0 : hapd_iface->interfaces->
1977 0 : ctrl_iface_deinit(hapd);
1978 0 : wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
1979 0 : __func__, hapd_iface->bss[i],
1980 0 : hapd->conf->iface);
1981 0 : os_free(hapd);
1982 0 : hapd_iface->bss[i] = NULL;
1983 : }
1984 0 : os_free(hapd_iface->bss);
1985 : }
1986 0 : wpa_printf(MSG_DEBUG, "%s: free iface %p",
1987 : __func__, hapd_iface);
1988 0 : os_free(hapd_iface);
1989 : }
1990 0 : return -1;
1991 : }
1992 :
1993 :
1994 17 : static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
1995 : {
1996 : size_t i;
1997 :
1998 17 : wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface);
1999 :
2000 : /* Remove hostapd_data only if it has already been initialized */
2001 17 : if (idx < iface->num_bss) {
2002 15 : struct hostapd_data *hapd = iface->bss[idx];
2003 :
2004 15 : hostapd_bss_deinit(hapd);
2005 15 : wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
2006 15 : __func__, hapd, hapd->conf->iface);
2007 15 : hostapd_config_free_bss(hapd->conf);
2008 15 : os_free(hapd);
2009 :
2010 15 : iface->num_bss--;
2011 :
2012 18 : for (i = idx; i < iface->num_bss; i++)
2013 3 : iface->bss[i] = iface->bss[i + 1];
2014 : } else {
2015 2 : hostapd_config_free_bss(iface->conf->bss[idx]);
2016 2 : iface->conf->bss[idx] = NULL;
2017 : }
2018 :
2019 17 : iface->conf->num_bss--;
2020 20 : for (i = idx; i < iface->conf->num_bss; i++)
2021 3 : iface->conf->bss[i] = iface->conf->bss[i + 1];
2022 :
2023 17 : return 0;
2024 : }
2025 :
2026 :
2027 3561 : int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
2028 : {
2029 : struct hostapd_iface *hapd_iface;
2030 3561 : size_t i, j, k = 0;
2031 :
2032 4847 : for (i = 0; i < interfaces->count; i++) {
2033 1935 : hapd_iface = interfaces->iface[i];
2034 1935 : if (hapd_iface == NULL)
2035 0 : return -1;
2036 1935 : if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
2037 632 : wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
2038 632 : hapd_iface->driver_ap_teardown =
2039 632 : !!(hapd_iface->drv_flags &
2040 : WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
2041 :
2042 632 : hostapd_interface_deinit_free(hapd_iface);
2043 632 : k = i;
2044 1333 : while (k < (interfaces->count - 1)) {
2045 138 : interfaces->iface[k] =
2046 69 : interfaces->iface[k + 1];
2047 69 : k++;
2048 : }
2049 632 : interfaces->count--;
2050 632 : return 0;
2051 : }
2052 :
2053 2611 : for (j = 0; j < hapd_iface->conf->num_bss; j++) {
2054 1325 : if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) {
2055 17 : hapd_iface->driver_ap_teardown =
2056 17 : !(hapd_iface->drv_flags &
2057 : WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
2058 17 : return hostapd_remove_bss(hapd_iface, j);
2059 : }
2060 : }
2061 : }
2062 2912 : return -1;
2063 : }
2064 :
2065 :
2066 : /**
2067 : * hostapd_new_assoc_sta - Notify that a new station associated with the AP
2068 : * @hapd: Pointer to BSS data
2069 : * @sta: Pointer to the associated STA data
2070 : * @reassoc: 1 to indicate this was a re-association; 0 = first association
2071 : *
2072 : * This function will be called whenever a station associates with the AP. It
2073 : * can be called from ieee802_11.c for drivers that export MLME to hostapd and
2074 : * from drv_callbacks.c based on driver events for drivers that take care of
2075 : * management frames (IEEE 802.11 authentication and association) internally.
2076 : */
2077 1300 : void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
2078 : int reassoc)
2079 : {
2080 1300 : if (hapd->tkip_countermeasures) {
2081 0 : hostapd_drv_sta_deauth(hapd, sta->addr,
2082 : WLAN_REASON_MICHAEL_MIC_FAILURE);
2083 1300 : return;
2084 : }
2085 :
2086 1300 : hostapd_prune_associations(hapd, sta->addr);
2087 :
2088 : /* IEEE 802.11F (IAPP) */
2089 1300 : if (hapd->conf->ieee802_11f)
2090 0 : iapp_new_station(hapd->iapp, sta);
2091 :
2092 : #ifdef CONFIG_P2P
2093 : if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
2094 : sta->no_p2p_set = 1;
2095 : hapd->num_sta_no_p2p++;
2096 : if (hapd->num_sta_no_p2p == 1)
2097 : hostapd_p2p_non_p2p_sta_connected(hapd);
2098 : }
2099 : #endif /* CONFIG_P2P */
2100 :
2101 : /* Start accounting here, if IEEE 802.1X and WPA are not used.
2102 : * IEEE 802.1X/WPA code will start accounting after the station has
2103 : * been authorized. */
2104 1300 : if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) {
2105 202 : ap_sta_set_authorized(hapd, sta, 1);
2106 202 : os_get_reltime(&sta->connected_time);
2107 202 : accounting_sta_start(hapd, sta);
2108 : }
2109 :
2110 : /* Start IEEE 802.1X authentication process for new stations */
2111 1300 : ieee802_1x_new_station(hapd, sta);
2112 1300 : if (reassoc) {
2113 8 : if (sta->auth_alg != WLAN_AUTH_FT &&
2114 4 : !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
2115 4 : wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
2116 : } else
2117 1296 : wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
2118 :
2119 1300 : if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
2120 9100 : wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
2121 : "for " MACSTR " (%d seconds - ap_max_inactivity)",
2122 7800 : __func__, MAC2STR(sta->addr),
2123 1300 : hapd->conf->ap_max_inactivity);
2124 1300 : eloop_cancel_timeout(ap_handle_timer, hapd, sta);
2125 1300 : eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
2126 : ap_handle_timer, hapd, sta);
2127 : }
2128 : }
2129 :
2130 :
2131 1539 : const char * hostapd_state_text(enum hostapd_iface_state s)
2132 : {
2133 1539 : switch (s) {
2134 : case HAPD_IFACE_UNINITIALIZED:
2135 624 : return "UNINITIALIZED";
2136 : case HAPD_IFACE_DISABLED:
2137 31 : return "DISABLED";
2138 : case HAPD_IFACE_COUNTRY_UPDATE:
2139 48 : return "COUNTRY_UPDATE";
2140 : case HAPD_IFACE_ACS:
2141 22 : return "ACS";
2142 : case HAPD_IFACE_HT_SCAN:
2143 66 : return "HT_SCAN";
2144 : case HAPD_IFACE_DFS:
2145 16 : return "DFS";
2146 : case HAPD_IFACE_ENABLED:
2147 732 : return "ENABLED";
2148 : }
2149 :
2150 0 : return "UNKNOWN";
2151 : }
2152 :
2153 :
2154 705 : void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s)
2155 : {
2156 1410 : wpa_printf(MSG_INFO, "%s: interface state %s->%s",
2157 705 : iface->conf->bss[0]->iface, hostapd_state_text(iface->state),
2158 : hostapd_state_text(s));
2159 705 : iface->state = s;
2160 705 : }
2161 :
2162 :
2163 : #ifdef NEED_AP_MLME
2164 :
2165 4 : static void free_beacon_data(struct beacon_data *beacon)
2166 : {
2167 4 : os_free(beacon->head);
2168 4 : beacon->head = NULL;
2169 4 : os_free(beacon->tail);
2170 4 : beacon->tail = NULL;
2171 4 : os_free(beacon->probe_resp);
2172 4 : beacon->probe_resp = NULL;
2173 4 : os_free(beacon->beacon_ies);
2174 4 : beacon->beacon_ies = NULL;
2175 4 : os_free(beacon->proberesp_ies);
2176 4 : beacon->proberesp_ies = NULL;
2177 4 : os_free(beacon->assocresp_ies);
2178 4 : beacon->assocresp_ies = NULL;
2179 4 : }
2180 :
2181 :
2182 4 : static int hostapd_build_beacon_data(struct hostapd_data *hapd,
2183 : struct beacon_data *beacon)
2184 : {
2185 : struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
2186 : struct wpa_driver_ap_params params;
2187 : int ret;
2188 :
2189 4 : os_memset(beacon, 0, sizeof(*beacon));
2190 4 : ret = ieee802_11_build_ap_params(hapd, ¶ms);
2191 4 : if (ret < 0)
2192 0 : return ret;
2193 :
2194 4 : ret = hostapd_build_ap_extra_ies(hapd, &beacon_extra,
2195 : &proberesp_extra,
2196 : &assocresp_extra);
2197 4 : if (ret)
2198 0 : goto free_ap_params;
2199 :
2200 4 : ret = -1;
2201 4 : beacon->head = os_malloc(params.head_len);
2202 4 : if (!beacon->head)
2203 0 : goto free_ap_extra_ies;
2204 :
2205 4 : os_memcpy(beacon->head, params.head, params.head_len);
2206 4 : beacon->head_len = params.head_len;
2207 :
2208 4 : beacon->tail = os_malloc(params.tail_len);
2209 4 : if (!beacon->tail)
2210 0 : goto free_beacon;
2211 :
2212 4 : os_memcpy(beacon->tail, params.tail, params.tail_len);
2213 4 : beacon->tail_len = params.tail_len;
2214 :
2215 4 : if (params.proberesp != NULL) {
2216 0 : beacon->probe_resp = os_malloc(params.proberesp_len);
2217 0 : if (!beacon->probe_resp)
2218 0 : goto free_beacon;
2219 :
2220 0 : os_memcpy(beacon->probe_resp, params.proberesp,
2221 : params.proberesp_len);
2222 0 : beacon->probe_resp_len = params.proberesp_len;
2223 : }
2224 :
2225 : /* copy the extra ies */
2226 4 : if (beacon_extra) {
2227 4 : beacon->beacon_ies = os_malloc(wpabuf_len(beacon_extra));
2228 4 : if (!beacon->beacon_ies)
2229 0 : goto free_beacon;
2230 :
2231 4 : os_memcpy(beacon->beacon_ies,
2232 : beacon_extra->buf, wpabuf_len(beacon_extra));
2233 4 : beacon->beacon_ies_len = wpabuf_len(beacon_extra);
2234 : }
2235 :
2236 4 : if (proberesp_extra) {
2237 4 : beacon->proberesp_ies =
2238 4 : os_malloc(wpabuf_len(proberesp_extra));
2239 4 : if (!beacon->proberesp_ies)
2240 0 : goto free_beacon;
2241 :
2242 4 : os_memcpy(beacon->proberesp_ies, proberesp_extra->buf,
2243 : wpabuf_len(proberesp_extra));
2244 4 : beacon->proberesp_ies_len = wpabuf_len(proberesp_extra);
2245 : }
2246 :
2247 4 : if (assocresp_extra) {
2248 4 : beacon->assocresp_ies =
2249 4 : os_malloc(wpabuf_len(assocresp_extra));
2250 4 : if (!beacon->assocresp_ies)
2251 0 : goto free_beacon;
2252 :
2253 4 : os_memcpy(beacon->assocresp_ies, assocresp_extra->buf,
2254 : wpabuf_len(assocresp_extra));
2255 4 : beacon->assocresp_ies_len = wpabuf_len(assocresp_extra);
2256 : }
2257 :
2258 4 : ret = 0;
2259 : free_beacon:
2260 : /* if the function fails, the caller should not free beacon data */
2261 4 : if (ret)
2262 0 : free_beacon_data(beacon);
2263 :
2264 : free_ap_extra_ies:
2265 4 : hostapd_free_ap_extra_ies(hapd, beacon_extra, proberesp_extra,
2266 : assocresp_extra);
2267 : free_ap_params:
2268 4 : ieee802_11_free_ap_params(¶ms);
2269 4 : return ret;
2270 : }
2271 :
2272 :
2273 : /*
2274 : * TODO: This flow currently supports only changing frequency within the
2275 : * same hw_mode. Any other changes to MAC parameters or provided settings (even
2276 : * width) are not supported.
2277 : */
2278 4 : static int hostapd_change_config_freq(struct hostapd_data *hapd,
2279 : struct hostapd_config *conf,
2280 : struct hostapd_freq_params *params,
2281 : struct hostapd_freq_params *old_params)
2282 : {
2283 : int channel;
2284 :
2285 4 : if (!params->channel) {
2286 : /* check if the new channel is supported by hw */
2287 1 : params->channel = hostapd_hw_get_channel(hapd, params->freq);
2288 : }
2289 :
2290 4 : channel = params->channel;
2291 4 : if (!channel)
2292 0 : return -1;
2293 :
2294 : /* if a pointer to old_params is provided we save previous state */
2295 4 : if (old_params) {
2296 2 : old_params->channel = conf->channel;
2297 2 : old_params->ht_enabled = conf->ieee80211n;
2298 2 : old_params->sec_channel_offset = conf->secondary_channel;
2299 : }
2300 :
2301 4 : conf->channel = channel;
2302 4 : conf->ieee80211n = params->ht_enabled;
2303 4 : conf->secondary_channel = params->sec_channel_offset;
2304 :
2305 : /* TODO: maybe call here hostapd_config_check here? */
2306 :
2307 4 : return 0;
2308 : }
2309 :
2310 :
2311 2 : static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
2312 : struct csa_settings *settings)
2313 : {
2314 2 : struct hostapd_iface *iface = hapd->iface;
2315 : struct hostapd_freq_params old_freq;
2316 : int ret;
2317 :
2318 2 : os_memset(&old_freq, 0, sizeof(old_freq));
2319 2 : if (!iface || !iface->freq || hapd->csa_in_progress)
2320 0 : return -1;
2321 :
2322 2 : ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
2323 : &settings->freq_params,
2324 : &old_freq);
2325 2 : if (ret)
2326 0 : return ret;
2327 :
2328 2 : ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
2329 :
2330 : /* change back the configuration */
2331 2 : hostapd_change_config_freq(iface->bss[0], iface->conf,
2332 : &old_freq, NULL);
2333 :
2334 2 : if (ret)
2335 0 : return ret;
2336 :
2337 : /* set channel switch parameters for csa ie */
2338 2 : hapd->cs_freq_params = settings->freq_params;
2339 2 : hapd->cs_count = settings->cs_count;
2340 2 : hapd->cs_block_tx = settings->block_tx;
2341 :
2342 2 : ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa);
2343 2 : if (ret) {
2344 0 : free_beacon_data(&settings->beacon_after);
2345 0 : return ret;
2346 : }
2347 :
2348 2 : settings->counter_offset_beacon = hapd->cs_c_off_beacon;
2349 2 : settings->counter_offset_presp = hapd->cs_c_off_proberesp;
2350 :
2351 2 : return 0;
2352 : }
2353 :
2354 :
2355 2 : void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
2356 : {
2357 2 : os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params));
2358 2 : hapd->cs_count = 0;
2359 2 : hapd->cs_block_tx = 0;
2360 2 : hapd->cs_c_off_beacon = 0;
2361 2 : hapd->cs_c_off_proberesp = 0;
2362 2 : hapd->csa_in_progress = 0;
2363 2 : }
2364 :
2365 :
2366 2 : int hostapd_switch_channel(struct hostapd_data *hapd,
2367 : struct csa_settings *settings)
2368 : {
2369 : int ret;
2370 2 : ret = hostapd_fill_csa_settings(hapd, settings);
2371 2 : if (ret)
2372 0 : return ret;
2373 :
2374 2 : ret = hostapd_drv_switch_channel(hapd, settings);
2375 2 : free_beacon_data(&settings->beacon_csa);
2376 2 : free_beacon_data(&settings->beacon_after);
2377 :
2378 2 : if (ret) {
2379 : /* if we failed, clean cs parameters */
2380 1 : hostapd_cleanup_cs_params(hapd);
2381 1 : return ret;
2382 : }
2383 :
2384 1 : hapd->csa_in_progress = 1;
2385 1 : return 0;
2386 : }
2387 :
2388 :
2389 : void
2390 0 : hostapd_switch_channel_fallback(struct hostapd_iface *iface,
2391 : const struct hostapd_freq_params *freq_params)
2392 : {
2393 0 : int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
2394 : unsigned int i;
2395 :
2396 0 : wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
2397 :
2398 0 : if (freq_params->center_freq1)
2399 0 : vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
2400 0 : if (freq_params->center_freq2)
2401 0 : vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
2402 :
2403 0 : switch (freq_params->bandwidth) {
2404 : case 0:
2405 : case 20:
2406 : case 40:
2407 0 : vht_bw = VHT_CHANWIDTH_USE_HT;
2408 0 : break;
2409 : case 80:
2410 0 : if (freq_params->center_freq2)
2411 0 : vht_bw = VHT_CHANWIDTH_80P80MHZ;
2412 : else
2413 0 : vht_bw = VHT_CHANWIDTH_80MHZ;
2414 0 : break;
2415 : case 160:
2416 0 : vht_bw = VHT_CHANWIDTH_160MHZ;
2417 0 : break;
2418 : default:
2419 0 : wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
2420 : freq_params->bandwidth);
2421 0 : break;
2422 : }
2423 :
2424 0 : iface->freq = freq_params->freq;
2425 0 : iface->conf->channel = freq_params->channel;
2426 0 : iface->conf->secondary_channel = freq_params->sec_channel_offset;
2427 0 : iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
2428 0 : iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
2429 0 : iface->conf->vht_oper_chwidth = vht_bw;
2430 0 : iface->conf->ieee80211n = freq_params->ht_enabled;
2431 0 : iface->conf->ieee80211ac = freq_params->vht_enabled;
2432 :
2433 : /*
2434 : * cs_params must not be cleared earlier because the freq_params
2435 : * argument may actually point to one of these.
2436 : */
2437 0 : for (i = 0; i < iface->num_bss; i++)
2438 0 : hostapd_cleanup_cs_params(iface->bss[i]);
2439 :
2440 0 : hostapd_disable_iface(iface);
2441 0 : hostapd_enable_iface(iface);
2442 0 : }
2443 :
2444 : #endif /* NEED_AP_MLME */
|