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