1 /*
2  * hostapd / main()
3  * Copyright (c) 2002-2022, 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 #ifndef CONFIG_NATIVE_WINDOWS
11 #include <syslog.h>
12 #include <grp.h>
13 #endif /* CONFIG_NATIVE_WINDOWS */
14 
15 #include "utils/common.h"
16 #include "utils/eloop.h"
17 #include "utils/uuid.h"
18 #include "crypto/crypto.h"
19 #include "crypto/random.h"
20 #include "crypto/tls.h"
21 #include "common/version.h"
22 #include "common/dpp.h"
23 #include "drivers/driver.h"
24 #include "eap_server/eap.h"
25 #include "eap_server/tncs.h"
26 #include "ap/hostapd.h"
27 #include "ap/ap_config.h"
28 #include "ap/ap_drv_ops.h"
29 #include "ap/dpp_hostapd.h"
30 #include "fst/fst.h"
31 #include "config_file.h"
32 #include "eap_register.h"
33 #include "ctrl_iface.h"
34 
35 
36 struct hapd_global {
37 	void **drv_priv;
38 	size_t drv_count;
39 };
40 
41 static struct hapd_global global;
42 
43 
44 #ifndef CONFIG_NO_HOSTAPD_LOGGER
hostapd_logger_cb(void * ctx,const u8 * addr,unsigned int module,int level,const char * txt,size_t len)45 static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
46 			      int level, const char *txt, size_t len)
47 {
48 	struct hostapd_data *hapd = ctx;
49 	char *format, *module_str;
50 	int maxlen;
51 	int conf_syslog_level, conf_stdout_level;
52 	unsigned int conf_syslog, conf_stdout;
53 
54 	maxlen = len + 100;
55 	format = os_malloc(maxlen);
56 	if (!format)
57 		return;
58 
59 	if (hapd && hapd->conf) {
60 		conf_syslog_level = hapd->conf->logger_syslog_level;
61 		conf_stdout_level = hapd->conf->logger_stdout_level;
62 		conf_syslog = hapd->conf->logger_syslog;
63 		conf_stdout = hapd->conf->logger_stdout;
64 	} else {
65 		conf_syslog_level = conf_stdout_level = 0;
66 		conf_syslog = conf_stdout = (unsigned int) -1;
67 	}
68 
69 	switch (module) {
70 	case HOSTAPD_MODULE_IEEE80211:
71 		module_str = "IEEE 802.11";
72 		break;
73 	case HOSTAPD_MODULE_IEEE8021X:
74 		module_str = "IEEE 802.1X";
75 		break;
76 	case HOSTAPD_MODULE_RADIUS:
77 		module_str = "RADIUS";
78 		break;
79 	case HOSTAPD_MODULE_WPA:
80 		module_str = "WPA";
81 		break;
82 	case HOSTAPD_MODULE_DRIVER:
83 		module_str = "DRIVER";
84 		break;
85 	case HOSTAPD_MODULE_MLME:
86 		module_str = "MLME";
87 		break;
88 	default:
89 		module_str = NULL;
90 		break;
91 	}
92 
93 	if (hapd && hapd->conf && addr)
94 		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
95 			    hapd->conf->iface, MAC2STR(addr),
96 			    module_str ? " " : "", module_str ? module_str : "",
97 			    txt);
98 	else if (hapd && hapd->conf)
99 		os_snprintf(format, maxlen, "%s:%s%s %s",
100 			    hapd->conf->iface, module_str ? " " : "",
101 			    module_str ? module_str : "", txt);
102 	else if (addr)
103 		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
104 			    MAC2STR(addr), module_str ? " " : "",
105 			    module_str ? module_str : "", txt);
106 	else
107 		os_snprintf(format, maxlen, "%s%s%s",
108 			    module_str ? module_str : "",
109 			    module_str ? ": " : "", txt);
110 
111 #ifdef CONFIG_DEBUG_SYSLOG
112 	if (wpa_debug_syslog)
113 		conf_stdout = 0;
114 #endif /* CONFIG_DEBUG_SYSLOG */
115 	if ((conf_stdout & module) && level >= conf_stdout_level) {
116 		wpa_debug_print_timestamp();
117 		wpa_printf(MSG_INFO, "%s", format);
118 	}
119 
120 #ifndef CONFIG_NATIVE_WINDOWS
121 	if ((conf_syslog & module) && level >= conf_syslog_level) {
122 		int priority;
123 		switch (level) {
124 		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
125 		case HOSTAPD_LEVEL_DEBUG:
126 			priority = LOG_DEBUG;
127 			break;
128 		case HOSTAPD_LEVEL_INFO:
129 			priority = LOG_INFO;
130 			break;
131 		case HOSTAPD_LEVEL_NOTICE:
132 			priority = LOG_NOTICE;
133 			break;
134 		case HOSTAPD_LEVEL_WARNING:
135 			priority = LOG_WARNING;
136 			break;
137 		default:
138 			priority = LOG_INFO;
139 			break;
140 		}
141 		syslog(priority, "%s", format);
142 	}
143 #endif /* CONFIG_NATIVE_WINDOWS */
144 
145 	os_free(format);
146 }
147 #endif /* CONFIG_NO_HOSTAPD_LOGGER */
148 
149 
150 /**
151  * hostapd_driver_init - Preparate driver interface
152  */
hostapd_driver_init(struct hostapd_iface * iface)153 static int hostapd_driver_init(struct hostapd_iface *iface)
154 {
155 	struct wpa_init_params params;
156 	size_t i;
157 	struct hostapd_data *hapd = iface->bss[0];
158 	struct hostapd_bss_config *conf = hapd->conf;
159 	u8 *b = conf->bssid;
160 	struct wpa_driver_capa capa;
161 #ifdef CONFIG_IEEE80211BE
162 	struct hostapd_data *h_hapd = NULL;
163 	void *shared_hapd = NULL;
164 #endif /* CONFIG_IEEE80211BE */
165 
166 	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
167 		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
168 		return -1;
169 	}
170 
171 #ifdef CONFIG_IEEE80211BE
172 	if (conf->mld_ap) {
173 		if (!hapd->mld)
174 			hostapd_bss_setup_multi_link(hapd, iface->interfaces);
175 		h_hapd = hostapd_mld_get_first_bss(hapd);
176 	}
177 
178 	if (h_hapd) {
179 		hapd->drv_priv = h_hapd->drv_priv;
180 		hapd->interface_added = h_hapd->interface_added;
181 
182 		/*
183 		 * All interfaces participating in the AP MLD would have
184 		 * the same MLD address, which is the interface hardware
185 		 * address, while the interface address would be
186 		 * derived from the original interface address if BSSID
187 		 * is not configured, and otherwise it would be the
188 		 * configured BSSID.
189 		 */
190 		if (is_zero_ether_addr(b)) {
191 			os_memcpy(hapd->own_addr, h_hapd->mld->mld_addr,
192 				  ETH_ALEN);
193 			random_mac_addr_keep_oui(hapd->own_addr);
194 		} else {
195 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
196 		}
197 
198 		wpa_printf(MSG_DEBUG,
199 			   "Setup of non first link (%d) BSS of MLD %s",
200 			   hapd->mld_link_id, hapd->conf->iface);
201 
202 		goto setup_mld;
203 	}
204 #endif /* CONFIG_IEEE80211BE */
205 
206 	/* Initialize the driver interface */
207 	if (is_zero_ether_addr(b))
208 		b = NULL;
209 
210 	os_memset(&params, 0, sizeof(params));
211 	for (i = 0; wpa_drivers[i]; i++) {
212 		if (wpa_drivers[i] != hapd->driver)
213 			continue;
214 
215 		if (global.drv_priv[i] == NULL &&
216 		    wpa_drivers[i]->global_init) {
217 			global.drv_priv[i] =
218 				wpa_drivers[i]->global_init(iface->interfaces);
219 			if (global.drv_priv[i] == NULL) {
220 				wpa_printf(MSG_ERROR, "Failed to initialize "
221 					   "driver '%s'",
222 					   wpa_drivers[i]->name);
223 				return -1;
224 			}
225 		}
226 
227 		params.global_priv = global.drv_priv[i];
228 		break;
229 	}
230 	params.bssid = b;
231 #ifdef CONFIG_IEEE80211BE
232 	/*
233 	 * Use the configured MLD MAC address as the interface hardware address
234 	 * if this AP is a part of an AP MLD.
235 	 */
236 	if (hapd->conf->mld_ap) {
237 		if (!is_zero_ether_addr(hapd->conf->mld_addr))
238 			params.bssid = hapd->conf->mld_addr;
239 		else
240 			params.bssid = NULL;
241 	}
242 #endif /* CONFIG_IEEE80211BE */
243 
244 	params.ifname = hapd->conf->iface;
245 	params.driver_params = hapd->iconf->driver_params;
246 	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
247 
248 	params.num_bridge = hapd->iface->num_bss;
249 	params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
250 	if (params.bridge == NULL)
251 		return -1;
252 	for (i = 0; i < hapd->iface->num_bss; i++) {
253 		struct hostapd_data *bss = hapd->iface->bss[i];
254 		if (bss->conf->bridge[0])
255 			params.bridge[i] = bss->conf->bridge;
256 	}
257 
258 	params.own_addr = hapd->own_addr;
259 
260 #ifdef CONFIG_IEEE80211BE
261 	if (hapd->driver->can_share_drv &&
262 	    hapd->driver->can_share_drv(hapd, &params, &shared_hapd)) {
263 		char force_ifname[IFNAMSIZ];
264 		const u8 *addr = params.bssid;
265 		u8 if_addr[ETH_ALEN];
266 
267 		if (!shared_hapd) {
268 			wpa_printf(MSG_ERROR, "Failed to get the shared drv");
269 			os_free(params.bridge);
270 			return -1;
271 		}
272 
273 		/* Share an already initialized driver interface instance
274 		 * using an AP mode BSS in it instead of adding a new driver
275 		 * interface instance for the same driver. */
276 		if (hostapd_if_add(shared_hapd, WPA_IF_AP_BSS,
277 				   params.ifname, addr, hapd,
278 				   &hapd->drv_priv, force_ifname, if_addr,
279 				   params.num_bridge && params.bridge[0] ?
280 				   params.bridge[0] : NULL,
281 				   0)) {
282 			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
283 				   MACSTR ")", MAC2STR(hapd->own_addr));
284 			os_free(params.bridge);
285 			return -1;
286 		}
287 		os_free(params.bridge);
288 
289 		hapd->interface_added = 1;
290 		os_memcpy(params.own_addr, addr ? addr : if_addr, ETH_ALEN);
291 
292 		goto pre_setup_mld;
293 	}
294 #endif /* CONFIG_IEEE80211BE */
295 
296 	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
297 	os_free(params.bridge);
298 	if (hapd->drv_priv == NULL) {
299 		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
300 			   hapd->driver->name);
301 		hapd->driver = NULL;
302 		return -1;
303 	}
304 
305 #ifdef CONFIG_IEEE80211BE
306 pre_setup_mld:
307 	/*
308 	 * This is the first interface added to the AP MLD, so have the
309 	 * interface hardware address be the MLD address, while the link address
310 	 * would be derived from the original interface address if BSSID is not
311 	 * configured, and otherwise it would be the configured BSSID.
312 	 */
313 	if (hapd->conf->mld_ap) {
314 		os_memcpy(hapd->mld->mld_addr, hapd->own_addr, ETH_ALEN);
315 
316 		if (!b)
317 			random_mac_addr_keep_oui(hapd->own_addr);
318 		else
319 			os_memcpy(hapd->own_addr, b, ETH_ALEN);
320 
321 		wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
322 			   hapd->mld_link_id, hapd->conf->iface);
323 	}
324 
325 setup_mld:
326 #endif /* CONFIG_IEEE80211BE */
327 
328 	if (hapd->driver->get_capa &&
329 	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
330 		struct wowlan_triggers *triggs;
331 
332 		iface->drv_flags = capa.flags;
333 		iface->drv_flags2 = capa.flags2;
334 		iface->drv_rrm_flags = capa.rrm_flags;
335 		iface->probe_resp_offloads = capa.probe_resp_offloads;
336 		/*
337 		 * Use default extended capa values from per-radio information
338 		 */
339 		iface->extended_capa = capa.extended_capa;
340 		iface->extended_capa_mask = capa.extended_capa_mask;
341 		iface->extended_capa_len = capa.extended_capa_len;
342 		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
343 
344 		/*
345 		 * Override extended capa with per-interface type (AP), if
346 		 * available from the driver.
347 		 */
348 		hostapd_get_ext_capa(iface);
349 
350 		hostapd_get_mld_capa(iface);
351 
352 		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
353 		if (triggs && hapd->driver->set_wowlan) {
354 			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
355 				wpa_printf(MSG_ERROR, "set_wowlan failed");
356 		}
357 		os_free(triggs);
358 
359 		iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
360 		iface->ema_max_periodicity = capa.ema_max_periodicity;
361 	}
362 
363 #ifdef CONFIG_IEEE80211BE
364 	if (hapd->conf->mld_ap) {
365 		if (!(iface->drv_flags2 & WPA_DRIVER_FLAGS2_MLO)) {
366 			wpa_printf(MSG_INFO,
367 				   "MLD: Not supported by the driver");
368 			return -1;
369 		}
370 
371 		/* Initialize the BSS parameter change to 1 */
372 		hapd->eht_mld_bss_param_change = 1;
373 
374 		wpa_printf(MSG_DEBUG,
375 			   "MLD: Set link_id=%u, mld_addr=" MACSTR
376 			   ", own_addr=" MACSTR,
377 			   hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
378 			   MAC2STR(hapd->own_addr));
379 
380 		if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
381 					 hapd->own_addr)) {
382 			wpa_printf(MSG_ERROR,
383 				   "MLD: Failed to add link %d in MLD %s",
384 				   hapd->mld_link_id, hapd->conf->iface);
385 			return -1;
386 		}
387 		hostapd_mld_add_link(hapd);
388 	}
389 #endif /* CONFIG_IEEE80211BE */
390 
391 	return 0;
392 }
393 
394 
395 /**
396  * hostapd_interface_init - Read configuration file and init BSS data
397  *
398  * This function is used to parse configuration file for a full interface (one
399  * or more BSSes sharing the same radio) and allocate memory for the BSS
400  * interfaces. No actual driver operations are started.
401  */
402 static struct hostapd_iface *
hostapd_interface_init(struct hapd_interfaces * interfaces,const char * if_name,const char * config_fname,int debug)403 hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
404 		       const char *config_fname, int debug)
405 {
406 	struct hostapd_iface *iface;
407 	int k;
408 
409 	wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
410 	iface = hostapd_init(interfaces, config_fname);
411 	if (!iface)
412 		return NULL;
413 
414 	if (if_name) {
415 		os_strlcpy(iface->conf->bss[0]->iface, if_name,
416 			   sizeof(iface->conf->bss[0]->iface));
417 	}
418 
419 	iface->interfaces = interfaces;
420 
421 	for (k = 0; k < debug; k++) {
422 		if (iface->bss[0]->conf->logger_stdout_level > 0)
423 			iface->bss[0]->conf->logger_stdout_level--;
424 	}
425 
426 	if (iface->conf->bss[0]->iface[0] == '\0' &&
427 	    !hostapd_drv_none(iface->bss[0])) {
428 		wpa_printf(MSG_ERROR,
429 			   "Interface name not specified in %s, nor by '-i' parameter",
430 			   config_fname);
431 		hostapd_interface_deinit_free(iface);
432 		return NULL;
433 	}
434 
435 	return iface;
436 }
437 
438 
439 /**
440  * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
441  */
handle_term(int sig,void * signal_ctx)442 static void handle_term(int sig, void *signal_ctx)
443 {
444 	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
445 	eloop_terminate();
446 }
447 
448 
449 #ifndef CONFIG_NATIVE_WINDOWS
450 
handle_reload_iface(struct hostapd_iface * iface,void * ctx)451 static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
452 {
453 	if (hostapd_reload_config(iface) < 0) {
454 		wpa_printf(MSG_WARNING, "Failed to read new configuration "
455 			   "file - continuing with old.");
456 	}
457 	return 0;
458 }
459 
460 
461 /**
462  * handle_reload - SIGHUP handler to reload configuration
463  */
handle_reload(int sig,void * signal_ctx)464 static void handle_reload(int sig, void *signal_ctx)
465 {
466 	struct hapd_interfaces *interfaces = signal_ctx;
467 	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
468 		   sig);
469 	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
470 }
471 
472 
handle_dump_state(int sig,void * signal_ctx)473 static void handle_dump_state(int sig, void *signal_ctx)
474 {
475 	/* Not used anymore - ignore signal */
476 }
477 #endif /* CONFIG_NATIVE_WINDOWS */
478 
479 
hostapd_global_init(struct hapd_interfaces * interfaces,const char * entropy_file)480 static int hostapd_global_init(struct hapd_interfaces *interfaces,
481 			       const char *entropy_file)
482 {
483 	int i;
484 
485 	os_memset(&global, 0, sizeof(global));
486 
487 	hostapd_logger_register_cb(hostapd_logger_cb);
488 
489 	if (eap_server_register_methods()) {
490 		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
491 		return -1;
492 	}
493 
494 	if (eloop_init()) {
495 		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
496 		return -1;
497 	}
498 	interfaces->eloop_initialized = 1;
499 
500 	random_init(entropy_file);
501 
502 #ifndef CONFIG_NATIVE_WINDOWS
503 	eloop_register_signal(SIGHUP, handle_reload, interfaces);
504 	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
505 #endif /* CONFIG_NATIVE_WINDOWS */
506 	eloop_register_signal_terminate(handle_term, interfaces);
507 
508 #ifndef CONFIG_NATIVE_WINDOWS
509 	openlog("hostapd", 0, LOG_DAEMON);
510 #endif /* CONFIG_NATIVE_WINDOWS */
511 
512 	for (i = 0; wpa_drivers[i]; i++)
513 		global.drv_count++;
514 	if (global.drv_count == 0) {
515 		wpa_printf(MSG_ERROR, "No drivers enabled");
516 		return -1;
517 	}
518 	global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
519 	if (global.drv_priv == NULL)
520 		return -1;
521 
522 	return 0;
523 }
524 
525 
hostapd_global_deinit(const char * pid_file,int eloop_initialized)526 static void hostapd_global_deinit(const char *pid_file, int eloop_initialized)
527 {
528 	int i;
529 
530 	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
531 		if (!global.drv_priv[i])
532 			continue;
533 		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
534 	}
535 	os_free(global.drv_priv);
536 	global.drv_priv = NULL;
537 
538 #ifdef EAP_SERVER_TNC
539 	tncs_global_deinit();
540 #endif /* EAP_SERVER_TNC */
541 
542 	random_deinit();
543 
544 	if (eloop_initialized)
545 		eloop_destroy();
546 
547 #ifndef CONFIG_NATIVE_WINDOWS
548 	closelog();
549 #endif /* CONFIG_NATIVE_WINDOWS */
550 
551 	eap_server_unregister_methods();
552 
553 	os_daemonize_terminate(pid_file);
554 }
555 
556 
hostapd_global_run(struct hapd_interfaces * ifaces,int daemonize,const char * pid_file)557 static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
558 			      const char *pid_file)
559 {
560 #ifdef EAP_SERVER_TNC
561 	int tnc = 0;
562 	size_t i, k;
563 
564 	for (i = 0; !tnc && i < ifaces->count; i++) {
565 		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
566 			if (ifaces->iface[i]->bss[0]->conf->tnc) {
567 				tnc++;
568 				break;
569 			}
570 		}
571 	}
572 
573 	if (tnc && tncs_global_init() < 0) {
574 		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
575 		return -1;
576 	}
577 #endif /* EAP_SERVER_TNC */
578 
579 	if (daemonize) {
580 		if (os_daemonize(pid_file)) {
581 			wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
582 			return -1;
583 		}
584 		if (eloop_sock_requeue()) {
585 			wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s",
586 				   strerror(errno));
587 			return -1;
588 		}
589 	}
590 
591 	eloop_run();
592 
593 	return 0;
594 }
595 
596 
show_version(void)597 static void show_version(void)
598 {
599 	fprintf(stderr,
600 		"hostapd v%s\n"
601 		"User space daemon for IEEE 802.11 AP management,\n"
602 		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
603 		"Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi> "
604 		"and contributors\n",
605 		VERSION_STR);
606 }
607 
608 
usage(void)609 static void usage(void)
610 {
611 	show_version();
612 	fprintf(stderr,
613 		"\n"
614 		"usage: hostapd [-hdBKtvq] [-P <PID file>] [-e <entropy file>] "
615 		"\\\n"
616 		"         [-g <global ctrl_iface>] [-G <group>]\\\n"
617 		"         [-i <comma-separated list of interface names>]\\\n"
618 		"         <configuration file(s)>\n"
619 		"\n"
620 		"options:\n"
621 		"   -h   show this usage\n"
622 		"   -d   show more debug messages (-dd for even more)\n"
623 		"   -B   run daemon in the background\n"
624 		"   -e   entropy file\n"
625 		"   -g   global control interface path\n"
626 		"   -G   group for control interfaces\n"
627 		"   -P   PID file\n"
628 		"   -K   include key data in debug messages\n"
629 #ifdef CONFIG_DEBUG_FILE
630 		"   -f   log output to debug file instead of stdout\n"
631 #endif /* CONFIG_DEBUG_FILE */
632 #ifdef CONFIG_DEBUG_LINUX_TRACING
633 		"   -T   record to Linux tracing in addition to logging\n"
634 		"        (records all messages regardless of debug verbosity)\n"
635 #endif /* CONFIG_DEBUG_LINUX_TRACING */
636 		"   -i   list of interface names to use\n"
637 #ifdef CONFIG_DEBUG_SYSLOG
638 		"   -s   log output to syslog instead of stdout\n"
639 #endif /* CONFIG_DEBUG_SYSLOG */
640 		"   -S   start all the interfaces synchronously\n"
641 		"   -t   include timestamps in some debug messages\n"
642 		"   -v   show hostapd version\n"
643 		"   -q   show less debug messages (-qq for even less)\n");
644 
645 	exit(1);
646 }
647 
648 
hostapd_msg_ifname_cb(void * ctx)649 static const char * hostapd_msg_ifname_cb(void *ctx)
650 {
651 	struct hostapd_data *hapd = ctx;
652 	if (hapd && hapd->conf)
653 		return hapd->conf->iface;
654 	return NULL;
655 }
656 
657 
hostapd_get_global_ctrl_iface(struct hapd_interfaces * interfaces,const char * path)658 static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
659 					 const char *path)
660 {
661 #ifndef CONFIG_CTRL_IFACE_UDP
662 	char *pos;
663 #endif /* !CONFIG_CTRL_IFACE_UDP */
664 
665 	os_free(interfaces->global_iface_path);
666 	interfaces->global_iface_path = os_strdup(path);
667 	if (interfaces->global_iface_path == NULL)
668 		return -1;
669 
670 #ifndef CONFIG_CTRL_IFACE_UDP
671 	pos = os_strrchr(interfaces->global_iface_path, '/');
672 	if (pos == NULL) {
673 		wpa_printf(MSG_ERROR, "No '/' in the global control interface "
674 			   "file");
675 		os_free(interfaces->global_iface_path);
676 		interfaces->global_iface_path = NULL;
677 		return -1;
678 	}
679 
680 	*pos = '\0';
681 	interfaces->global_iface_name = pos + 1;
682 #endif /* !CONFIG_CTRL_IFACE_UDP */
683 
684 	return 0;
685 }
686 
687 
hostapd_get_ctrl_iface_group(struct hapd_interfaces * interfaces,const char * group)688 static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
689 					const char *group)
690 {
691 #ifndef CONFIG_NATIVE_WINDOWS
692 	struct group *grp;
693 	grp = getgrnam(group);
694 	if (grp == NULL) {
695 		wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
696 		return -1;
697 	}
698 	interfaces->ctrl_iface_group = grp->gr_gid;
699 #endif /* CONFIG_NATIVE_WINDOWS */
700 	return 0;
701 }
702 
703 
hostapd_get_interface_names(char *** if_names,size_t * if_names_size,char * arg)704 static int hostapd_get_interface_names(char ***if_names,
705 				       size_t *if_names_size,
706 				       char *arg)
707 {
708 	char *if_name, *tmp, **nnames;
709 	size_t i;
710 
711 	if (!arg)
712 		return -1;
713 	if_name = strtok_r(arg, ",", &tmp);
714 
715 	while (if_name) {
716 		nnames = os_realloc_array(*if_names, 1 + *if_names_size,
717 					  sizeof(char *));
718 		if (!nnames)
719 			goto fail;
720 		*if_names = nnames;
721 
722 		(*if_names)[*if_names_size] = os_strdup(if_name);
723 		if (!(*if_names)[*if_names_size])
724 			goto fail;
725 		(*if_names_size)++;
726 		if_name = strtok_r(NULL, ",", &tmp);
727 	}
728 
729 	return 0;
730 
731 fail:
732 	for (i = 0; i < *if_names_size; i++)
733 		os_free((*if_names)[i]);
734 	os_free(*if_names);
735 	*if_names = NULL;
736 	*if_names_size = 0;
737 	return -1;
738 }
739 
740 
741 #ifdef CONFIG_WPS
gen_uuid(const char * txt_addr)742 static int gen_uuid(const char *txt_addr)
743 {
744 	u8 addr[ETH_ALEN];
745 	u8 uuid[UUID_LEN];
746 	char buf[100];
747 
748 	if (hwaddr_aton(txt_addr, addr) < 0)
749 		return -1;
750 
751 	uuid_gen_mac_addr(addr, uuid);
752 	if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
753 		return -1;
754 
755 	printf("%s\n", buf);
756 
757 	return 0;
758 }
759 #endif /* CONFIG_WPS */
760 
761 
762 #ifndef HOSTAPD_CLEANUP_INTERVAL
763 #define HOSTAPD_CLEANUP_INTERVAL 10
764 #endif /* HOSTAPD_CLEANUP_INTERVAL */
765 
hostapd_periodic_call(struct hostapd_iface * iface,void * ctx)766 static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
767 {
768 	hostapd_periodic_iface(iface);
769 	return 0;
770 }
771 
772 
773 /* Periodic cleanup tasks */
hostapd_periodic(void * eloop_ctx,void * timeout_ctx)774 static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
775 {
776 	struct hapd_interfaces *interfaces = eloop_ctx;
777 
778 	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
779 			       hostapd_periodic, interfaces, NULL);
780 	hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
781 }
782 
783 
hostapd_global_cleanup_mld(struct hapd_interfaces * interfaces)784 static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
785 {
786 #ifdef CONFIG_IEEE80211BE
787 	size_t i;
788 
789 	if (!interfaces || !interfaces->mld)
790 		return;
791 
792 	for (i = 0; i < interfaces->mld_count; i++) {
793 		if (!interfaces->mld[i])
794 			continue;
795 
796 		interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]);
797 		os_free(interfaces->mld[i]);
798 		interfaces->mld[i] = NULL;
799 	}
800 
801 	os_free(interfaces->mld);
802 	interfaces->mld = NULL;
803 	interfaces->mld_count = 0;
804 #endif /* CONFIG_IEEE80211BE */
805 }
806 
807 
main(int argc,char * argv[])808 int main(int argc, char *argv[])
809 {
810 	struct hapd_interfaces interfaces;
811 	int ret = 1;
812 	size_t i, j;
813 	int c, debug = 0, daemonize = 0;
814 	char *pid_file = NULL;
815 	const char *log_file = NULL;
816 	const char *entropy_file = NULL;
817 	char **bss_config = NULL, **tmp_bss;
818 	size_t num_bss_configs = 0;
819 #ifdef CONFIG_DEBUG_LINUX_TRACING
820 	int enable_trace_dbg = 0;
821 #endif /* CONFIG_DEBUG_LINUX_TRACING */
822 	int start_ifaces_in_sync = 0;
823 	char **if_names = NULL;
824 	size_t if_names_size = 0;
825 #ifdef CONFIG_DPP
826 	struct dpp_global_config dpp_conf;
827 #endif /* CONFIG_DPP */
828 
829 	if (os_program_init())
830 		return -1;
831 
832 	os_memset(&interfaces, 0, sizeof(interfaces));
833 	interfaces.reload_config = hostapd_reload_config;
834 	interfaces.config_read_cb = hostapd_config_read;
835 	interfaces.for_each_interface = hostapd_for_each_interface;
836 	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
837 	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
838 	interfaces.driver_init = hostapd_driver_init;
839 	interfaces.global_iface_path = NULL;
840 	interfaces.global_iface_name = NULL;
841 	interfaces.global_ctrl_sock = -1;
842 #ifdef CONFIG_IEEE80211BE
843 	interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init;
844 	interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit;
845 #endif /* CONFIG_IEEE80211BE */
846 	dl_list_init(&interfaces.global_ctrl_dst);
847 #ifdef CONFIG_ETH_P_OUI
848 	dl_list_init(&interfaces.eth_p_oui);
849 #endif /* CONFIG_ETH_P_OUI */
850 #ifdef CONFIG_DPP
851 	os_memset(&dpp_conf, 0, sizeof(dpp_conf));
852 	dpp_conf.cb_ctx = &interfaces;
853 #ifdef CONFIG_DPP2
854 	dpp_conf.remove_bi = hostapd_dpp_remove_bi;
855 #endif /* CONFIG_DPP2 */
856 	interfaces.dpp = dpp_global_init(&dpp_conf);
857 	if (!interfaces.dpp)
858 		return -1;
859 #endif /* CONFIG_DPP */
860 
861 	for (;;) {
862 		c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
863 		if (c < 0)
864 			break;
865 		switch (c) {
866 		case 'h':
867 			usage();
868 			break;
869 		case 'd':
870 			debug++;
871 			if (wpa_debug_level > 0)
872 				wpa_debug_level--;
873 			break;
874 		case 'B':
875 			daemonize++;
876 			break;
877 		case 'e':
878 			entropy_file = optarg;
879 			break;
880 		case 'f':
881 			log_file = optarg;
882 			break;
883 		case 'K':
884 			wpa_debug_show_keys++;
885 			break;
886 		case 'P':
887 			os_free(pid_file);
888 			pid_file = os_rel2abs_path(optarg);
889 			break;
890 		case 't':
891 			wpa_debug_timestamp++;
892 			break;
893 #ifdef CONFIG_DEBUG_LINUX_TRACING
894 		case 'T':
895 			enable_trace_dbg = 1;
896 			break;
897 #endif /* CONFIG_DEBUG_LINUX_TRACING */
898 		case 'v':
899 			show_version();
900 			exit(1);
901 		case 'g':
902 			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
903 				return -1;
904 			break;
905 		case 'G':
906 			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
907 				return -1;
908 			break;
909 		case 'b':
910 			tmp_bss = os_realloc_array(bss_config,
911 						   num_bss_configs + 1,
912 						   sizeof(char *));
913 			if (tmp_bss == NULL)
914 				goto out;
915 			bss_config = tmp_bss;
916 			bss_config[num_bss_configs++] = optarg;
917 			break;
918 #ifdef CONFIG_DEBUG_SYSLOG
919 		case 's':
920 			wpa_debug_syslog = 1;
921 			break;
922 #endif /* CONFIG_DEBUG_SYSLOG */
923 		case 'S':
924 			start_ifaces_in_sync = 1;
925 			break;
926 #ifdef CONFIG_WPS
927 		case 'u':
928 			return gen_uuid(optarg);
929 #endif /* CONFIG_WPS */
930 		case 'i':
931 			if (hostapd_get_interface_names(&if_names,
932 							&if_names_size, optarg))
933 				goto out;
934 			break;
935 		case 'q':
936 			wpa_debug_level++;
937 			break;
938 		default:
939 			usage();
940 			break;
941 		}
942 	}
943 
944 	if (optind == argc && interfaces.global_iface_path == NULL &&
945 	    num_bss_configs == 0)
946 		usage();
947 
948 	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
949 
950 	if (log_file)
951 		wpa_debug_open_file(log_file);
952 	if (!log_file && !wpa_debug_syslog)
953 		wpa_debug_setup_stdout();
954 #ifdef CONFIG_DEBUG_SYSLOG
955 	if (wpa_debug_syslog)
956 		wpa_debug_open_syslog();
957 #endif /* CONFIG_DEBUG_SYSLOG */
958 #ifdef CONFIG_DEBUG_LINUX_TRACING
959 	if (enable_trace_dbg) {
960 		int tret = wpa_debug_open_linux_tracing();
961 		if (tret) {
962 			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
963 			return -1;
964 		}
965 	}
966 #endif /* CONFIG_DEBUG_LINUX_TRACING */
967 
968 	interfaces.count = argc - optind;
969 	if (interfaces.count || num_bss_configs) {
970 		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
971 					     sizeof(struct hostapd_iface *));
972 		if (interfaces.iface == NULL) {
973 			wpa_printf(MSG_ERROR, "malloc failed");
974 			return -1;
975 		}
976 	}
977 
978 	if (hostapd_global_init(&interfaces, entropy_file)) {
979 		wpa_printf(MSG_ERROR, "Failed to initialize global context");
980 		return -1;
981 	}
982 
983 	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
984 			       hostapd_periodic, &interfaces, NULL);
985 
986 	if (fst_global_init()) {
987 		wpa_printf(MSG_ERROR,
988 			   "Failed to initialize global FST context");
989 		goto out;
990 	}
991 
992 #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
993 	if (!fst_global_add_ctrl(fst_ctrl_cli))
994 		wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
995 #endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
996 
997 	/* Allocate and parse configuration for full interface files */
998 	for (i = 0; i < interfaces.count; i++) {
999 		char *if_name = NULL;
1000 
1001 		if (i < if_names_size)
1002 			if_name = if_names[i];
1003 
1004 		interfaces.iface[i] = hostapd_interface_init(&interfaces,
1005 							     if_name,
1006 							     argv[optind + i],
1007 							     debug);
1008 		if (!interfaces.iface[i]) {
1009 			wpa_printf(MSG_ERROR, "Failed to initialize interface");
1010 			goto out;
1011 		}
1012 		if (start_ifaces_in_sync)
1013 			interfaces.iface[i]->need_to_start_in_sync = 1;
1014 	}
1015 
1016 	/* Allocate and parse configuration for per-BSS files */
1017 	for (i = 0; i < num_bss_configs; i++) {
1018 		struct hostapd_iface *iface;
1019 		char *fname;
1020 
1021 		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
1022 		fname = os_strchr(bss_config[i], ':');
1023 		if (fname == NULL) {
1024 			wpa_printf(MSG_ERROR,
1025 				   "Invalid BSS config identifier '%s'",
1026 				   bss_config[i]);
1027 			goto out;
1028 		}
1029 		*fname++ = '\0';
1030 		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
1031 						   fname, debug);
1032 		if (iface == NULL)
1033 			goto out;
1034 		for (j = 0; j < interfaces.count; j++) {
1035 			if (interfaces.iface[j] == iface)
1036 				break;
1037 		}
1038 		if (j == interfaces.count) {
1039 			struct hostapd_iface **tmp;
1040 			tmp = os_realloc_array(interfaces.iface,
1041 					       interfaces.count + 1,
1042 					       sizeof(struct hostapd_iface *));
1043 			if (tmp == NULL) {
1044 				hostapd_interface_deinit_free(iface);
1045 				goto out;
1046 			}
1047 			interfaces.iface = tmp;
1048 			interfaces.iface[interfaces.count++] = iface;
1049 		}
1050 	}
1051 
1052 	/*
1053 	 * Enable configured interfaces. Depending on channel configuration,
1054 	 * this may complete full initialization before returning or use a
1055 	 * callback mechanism to complete setup in case of operations like HT
1056 	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
1057 	 * In such case, the interface will be enabled from eloop context within
1058 	 * hostapd_global_run().
1059 	 */
1060 	interfaces.terminate_on_error = interfaces.count;
1061 	for (i = 0; i < interfaces.count; i++) {
1062 		if (hostapd_driver_init(interfaces.iface[i]) ||
1063 		    hostapd_setup_interface(interfaces.iface[i]))
1064 			goto out;
1065 	}
1066 
1067 	hostapd_global_ctrl_iface_init(&interfaces);
1068 
1069 	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
1070 		wpa_printf(MSG_ERROR, "Failed to start eloop");
1071 		goto out;
1072 	}
1073 
1074 	ret = 0;
1075 
1076  out:
1077 	hostapd_global_ctrl_iface_deinit(&interfaces);
1078 	/* Deinitialize all interfaces */
1079 	for (i = 0; i < interfaces.count; i++) {
1080 		if (!interfaces.iface[i])
1081 			continue;
1082 		interfaces.iface[i]->driver_ap_teardown =
1083 			!!(interfaces.iface[i]->drv_flags &
1084 			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
1085 		hostapd_interface_deinit_free(interfaces.iface[i]);
1086 		interfaces.iface[i] = NULL;
1087 	}
1088 	os_free(interfaces.iface);
1089 	interfaces.iface = NULL;
1090 	interfaces.count = 0;
1091 
1092 	hostapd_global_cleanup_mld(&interfaces);
1093 
1094 #ifdef CONFIG_DPP
1095 	dpp_global_deinit(interfaces.dpp);
1096 #endif /* CONFIG_DPP */
1097 
1098 	if (interfaces.eloop_initialized)
1099 		eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
1100 	hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
1101 	os_free(pid_file);
1102 
1103 	wpa_debug_close_syslog();
1104 	if (log_file)
1105 		wpa_debug_close_file();
1106 	wpa_debug_close_linux_tracing();
1107 
1108 	os_free(bss_config);
1109 
1110 	for (i = 0; i < if_names_size; i++)
1111 		os_free(if_names[i]);
1112 	os_free(if_names);
1113 
1114 	fst_global_deinit();
1115 
1116 	crypto_unload();
1117 	os_program_deinit();
1118 
1119 	return ret;
1120 }
1121