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