1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA.
3  * Copyright 2024 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(wifi_supplicant, CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL);
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/init.h>
13 #include <poll.h>
14 
15 #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP)
16 #include <mbedtls/platform.h>
17 #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */
18 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA
19 #include "supp_psa_api.h"
20 #endif
21 
22 #include <zephyr/net/wifi_mgmt.h>
23 #include <zephyr/net/wifi_nm.h>
24 #include <zephyr/net/socket.h>
25 
26 static K_THREAD_STACK_DEFINE(supplicant_thread_stack,
27 			     CONFIG_WIFI_NM_WPA_SUPPLICANT_THREAD_STACK_SIZE);
28 static struct k_thread tid;
29 
30 static K_THREAD_STACK_DEFINE(iface_wq_stack, CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_STACK_SIZE);
31 
32 #define IFACE_NOTIFY_TIMEOUT_MS 1000
33 #define IFACE_NOTIFY_RETRY_MS 10
34 
35 #include "supp_main.h"
36 #include "supp_api.h"
37 #include "supp_events.h"
38 
39 #include "includes.h"
40 #include "common.h"
41 #include "eloop.h"
42 #include "wpa_supplicant/config.h"
43 #include "wpa_supplicant_i.h"
44 #include "fst/fst.h"
45 #include "includes.h"
46 #include "wpa_cli_zephyr.h"
47 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
48 #include "hostapd.h"
49 #include "hostapd_cli_zephyr.h"
50 #include "eap_register.h"
51 #include "ap_drv_ops.h"
52 #include "l2_packet/l2_packet.h"
53 #endif
54 
55 static const struct wifi_mgmt_ops mgmt_ops = {
56 	.get_version = supplicant_get_version,
57 	.scan = supplicant_scan,
58 	.connect = supplicant_connect,
59 	.disconnect = supplicant_disconnect,
60 	.iface_status = supplicant_status,
61 #ifdef CONFIG_NET_STATISTICS_WIFI
62 	.get_stats = supplicant_get_stats,
63 	.reset_stats = supplicant_reset_stats,
64 #endif
65 	.cfg_11k = supplicant_11k_cfg,
66 	.send_11k_neighbor_request = supplicant_11k_neighbor_request,
67 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
68 	.candidate_scan = supplicant_candidate_scan,
69 	.start_11r_roaming = supplicant_11r_roaming,
70 #endif
71 	.set_power_save = supplicant_set_power_save,
72 	.set_twt = supplicant_set_twt,
73 	.get_power_save_config = supplicant_get_power_save_config,
74 	.reg_domain = supplicant_reg_domain,
75 	.mode = supplicant_mode,
76 	.filter = supplicant_filter,
77 	.channel = supplicant_channel,
78 	.set_rts_threshold = supplicant_set_rts_threshold,
79 	.get_rts_threshold = supplicant_get_rts_threshold,
80 	.bss_ext_capab = supplicant_bss_ext_capab,
81 	.legacy_roam = supplicant_legacy_roam,
82 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
83 	.btm_query = supplicant_btm_query,
84 #endif
85 	.get_conn_params = supplicant_get_wifi_conn_params,
86 	.wps_config = supplicant_wps_config,
87 #ifdef CONFIG_AP
88 	.ap_enable = supplicant_ap_enable,
89 	.ap_disable = supplicant_ap_disable,
90 	.ap_sta_disconnect = supplicant_ap_sta_disconnect,
91 #endif /* CONFIG_AP */
92 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
93 	.dpp_dispatch = supplicant_dpp_dispatch,
94 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
95 	.pmksa_flush = supplicant_pmksa_flush,
96 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
97 	.enterprise_creds = supplicant_add_enterprise_creds,
98 #endif
99 };
100 
101 DEFINE_WIFI_NM_INSTANCE(wifi_supplicant, &mgmt_ops);
102 
103 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
104 static const struct wifi_mgmt_ops mgmt_ap_ops = {
105 	.ap_enable = supplicant_ap_enable,
106 	.ap_disable = supplicant_ap_disable,
107 	.ap_sta_disconnect = supplicant_ap_sta_disconnect,
108 	.iface_status = supplicant_ap_status,
109 #ifdef CONFIG_WIFI_NM_HOSTAPD_WPS
110 	.wps_config = supplicant_ap_wps_config,
111 #endif
112 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
113 	.dpp_dispatch = hapd_dpp_dispatch,
114 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
115 	.ap_config_params = supplicant_ap_config_params,
116 	.set_rts_threshold = supplicant_set_rts_threshold,
117 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
118 	.enterprise_creds = supplicant_add_enterprise_creds,
119 #endif
120 	.set_btwt = supplicant_set_btwt,
121 };
122 
123 DEFINE_WIFI_NM_INSTANCE(hostapd, &mgmt_ap_ops);
124 #endif
125 
126 #define WRITE_TIMEOUT 100 /* ms */
127 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
128 #define INTERFACE_EVENT_MASK (NET_EVENT_IF_ADMIN_UP | NET_EVENT_IF_ADMIN_DOWN)
129 #endif
130 struct supplicant_context {
131 	struct wpa_global *supplicant;
132 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
133 	struct hapd_interfaces hostapd;
134 #endif
135 	struct net_mgmt_event_callback cb;
136 	struct net_if *iface;
137 	char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
138 	int event_socketpair[2];
139 	struct k_work iface_work;
140 	struct k_work_q iface_wq;
141 	int (*iface_handler)(struct supplicant_context *ctx, struct net_if *iface);
142 };
143 
144 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
145 struct hapd_global {
146 	void **drv_priv;
147 	size_t drv_count;
148 };
149 
150 static struct hapd_global hglobal;
151 
152 #ifndef HOSTAPD_CLEANUP_INTERVAL
153 #define HOSTAPD_CLEANUP_INTERVAL 10
154 #endif /* HOSTAPD_CLEANUP_INTERVAL */
155 
156 static void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type,
157 					    const char *txt, size_t len);
158 
hostapd_periodic_call(struct hostapd_iface * iface,void * ctx)159 static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
160 {
161 	hostapd_periodic_iface(iface);
162 	return 0;
163 }
164 
165 /* Periodic cleanup tasks */
hostapd_periodic(void * eloop_ctx,void * timeout_ctx)166 static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
167 {
168 	struct hapd_interfaces *interfaces = eloop_ctx;
169 
170 	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
171 			       hostapd_periodic, interfaces, NULL);
172 	hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
173 }
174 #endif
175 
get_default_context(void)176 static struct supplicant_context *get_default_context(void)
177 {
178 	static struct supplicant_context ctx;
179 
180 	return &ctx;
181 }
182 
zephyr_get_default_supplicant_context(void)183 struct wpa_global *zephyr_get_default_supplicant_context(void)
184 {
185 	return get_default_context()->supplicant;
186 }
187 
get_workq(void)188 struct k_work_q *get_workq(void)
189 {
190 	return &get_default_context()->iface_wq;
191 }
192 
zephyr_wifi_send_event(const struct wpa_supplicant_event_msg * msg)193 int zephyr_wifi_send_event(const struct wpa_supplicant_event_msg *msg)
194 {
195 	struct supplicant_context *ctx;
196 	struct pollfd fds[1];
197 	int ret;
198 
199 	/* TODO: Fix this to get the correct container */
200 	ctx = get_default_context();
201 
202 	if (ctx->event_socketpair[1] < 0) {
203 		ret = -ENOENT;
204 		goto out;
205 	}
206 
207 	fds[0].fd = ctx->event_socketpair[0];
208 	fds[0].events = POLLOUT;
209 	fds[0].revents = 0;
210 
211 	ret = zsock_poll(fds, 1, WRITE_TIMEOUT);
212 	if (ret < 0) {
213 		ret = -errno;
214 		LOG_ERR("Cannot write event (%d)", ret);
215 		goto out;
216 	}
217 
218 	ret = zsock_send(ctx->event_socketpair[1], msg, sizeof(*msg), 0);
219 	if (ret < 0) {
220 		ret = -errno;
221 		LOG_WRN("Event send failed (%d)", ret);
222 		goto out;
223 	}
224 
225 	if (ret != sizeof(*msg)) {
226 		ret = -EMSGSIZE;
227 		LOG_WRN("Event partial send (%d)", ret);
228 		goto out;
229 	}
230 
231 	ret = 0;
232 
233 out:
234 	return ret;
235 }
236 
237 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
send_event(const struct wpa_supplicant_event_msg * msg)238 static int send_event(const struct wpa_supplicant_event_msg *msg)
239 {
240 	return zephyr_wifi_send_event(msg);
241 }
242 
is_wanted_interface(struct net_if * iface)243 static bool is_wanted_interface(struct net_if *iface)
244 {
245 	if (!net_if_is_wifi(iface)) {
246 		return false;
247 	}
248 
249 	/* TODO: check against a list of valid interfaces */
250 
251 	return true;
252 }
253 #endif
zephyr_get_handle_by_ifname(const char * ifname)254 struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname)
255 {
256 	struct wpa_supplicant *wpa_s = NULL;
257 	struct supplicant_context *ctx = get_default_context();
258 
259 	wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
260 	if (!wpa_s) {
261 		wpa_printf(MSG_ERROR, "%s: Unable to get wpa_s handle for %s\n", __func__, ifname);
262 		return NULL;
263 	}
264 
265 	return wpa_s;
266 }
267 
268 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
zephyr_get_hapd_handle_by_ifname(const char * ifname)269 struct hostapd_iface *zephyr_get_hapd_handle_by_ifname(const char *ifname)
270 {
271 	struct hostapd_data *hapd = NULL;
272 	struct supplicant_context *ctx = get_default_context();
273 
274 	hapd = hostapd_get_iface(&ctx->hostapd, ifname);
275 	if (!hapd) {
276 		wpa_printf(MSG_ERROR, "%s: Unable to get hapd handle for %s\n", __func__, ifname);
277 		return NULL;
278 	}
279 
280 	return hapd->iface;
281 }
282 #endif
283 
get_iface_count(struct supplicant_context * ctx)284 static int get_iface_count(struct supplicant_context *ctx)
285 {
286 	/* FIXME, should not access ifaces as it is supplicant internal data */
287 	struct wpa_supplicant *wpa_s;
288 	unsigned int count = 0;
289 
290 	for (wpa_s = ctx->supplicant->ifaces; wpa_s; wpa_s = wpa_s->next) {
291 		count += 1;
292 	}
293 
294 	return count;
295 }
296 
add_interface(struct supplicant_context * ctx,struct net_if * iface)297 static int add_interface(struct supplicant_context *ctx, struct net_if *iface)
298 {
299 	struct wpa_supplicant *wpa_s;
300 	char ifname[IFNAMSIZ + 1] = { 0 };
301 	int ret, retry = 0, count = IFACE_NOTIFY_TIMEOUT_MS / IFACE_NOTIFY_RETRY_MS;
302 
303 	ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
304 	if (ret < 0) {
305 		LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface);
306 		goto out;
307 	}
308 
309 	LOG_DBG("Adding interface %s [%d] (%p)", ifname, net_if_get_by_iface(iface), iface);
310 
311 	ret = zephyr_wpa_cli_global_cmd_v("interface_add %s %s %s %s",
312 					  ifname, "zephyr", "zephyr", "zephyr");
313 	if (ret) {
314 		LOG_ERR("Failed to add interface %s", ifname);
315 		goto out;
316 	}
317 
318 	while (retry++ < count && !wpa_supplicant_get_iface(ctx->supplicant, ifname)) {
319 		k_sleep(K_MSEC(IFACE_NOTIFY_RETRY_MS));
320 	}
321 
322 	wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
323 	if (wpa_s == NULL) {
324 		LOG_ERR("Failed to add iface %s", ifname);
325 		goto out;
326 	}
327 
328 	wpa_s->conf->filter_ssids = 1;
329 	wpa_s->conf->ap_scan = 1;
330 
331 	/* Default interface, kick start supplicant */
332 	if (get_iface_count(ctx) > 0) {
333 		ctx->iface = iface;
334 		net_if_get_name(iface, ctx->if_name, CONFIG_NET_INTERFACE_NAME_LEN);
335 	}
336 
337 	ret = zephyr_wpa_ctrl_init(wpa_s);
338 	if (ret) {
339 		LOG_ERR("Failed to initialize supplicant control interface");
340 		goto out;
341 	}
342 
343 	ret = wifi_nm_register_mgd_type_iface(wifi_nm_get_instance("wifi_supplicant"),
344 					      WIFI_TYPE_STA,
345 					      iface);
346 	if (ret) {
347 		LOG_ERR("Failed to register mgd iface with native stack %s (%d)",
348 			ifname, ret);
349 		goto out;
350 	}
351 
352 	supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_ADDED, 0);
353 
354 	if (get_iface_count(ctx) == 1) {
355 		supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_READY, 0);
356 	}
357 
358 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
359 	wpa_msg_register_cb(zephyr_hostap_ctrl_iface_msg_cb);
360 #endif
361 	ret = 0;
362 
363 out:
364 	return ret;
365 }
366 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
del_interface(struct supplicant_context * ctx,struct net_if * iface)367 static int del_interface(struct supplicant_context *ctx, struct net_if *iface)
368 {
369 	struct wpa_supplicant_event_msg msg;
370 	struct wpa_supplicant *wpa_s;
371 	union wpa_event_data *event = NULL;
372 	int ret, retry = 0, count = IFACE_NOTIFY_TIMEOUT_MS / IFACE_NOTIFY_RETRY_MS;
373 	char ifname[IFNAMSIZ + 1] = { 0 };
374 
375 	ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
376 	if (ret < 0) {
377 		LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface);
378 		goto out;
379 	}
380 
381 	LOG_DBG("Removing interface %s %d (%p)", ifname, net_if_get_by_iface(iface), iface);
382 
383 	event = os_zalloc(sizeof(*event));
384 	if (!event) {
385 		ret = -ENOMEM;
386 		LOG_ERR("Failed to allocate event data");
387 		goto out;
388 	}
389 
390 	wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
391 	if (!wpa_s) {
392 		ret = -ENOENT;
393 		LOG_ERR("Failed to get wpa_s handle for %s", ifname);
394 		goto free;
395 	}
396 
397 	supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVING, 0);
398 
399 	if (sizeof(event->interface_status.ifname) < strlen(ifname)) {
400 		wpa_printf(MSG_ERROR, "Interface name too long: %s (max: %zu)",
401 			ifname, sizeof(event->interface_status.ifname));
402 		goto free;
403 	}
404 
405 	os_memcpy(event->interface_status.ifname, ifname, strlen(ifname));
406 	event->interface_status.ievent = EVENT_INTERFACE_REMOVED;
407 
408 	msg.global = true;
409 	msg.ctx = ctx->supplicant;
410 	msg.event = EVENT_INTERFACE_STATUS;
411 	msg.data = event;
412 
413 	ret = send_event(&msg);
414 	if (ret) {
415 		/* We failed notify WPA supplicant about interface removal.
416 		 * There is not much we can do, interface is still registered
417 		 * with WPA supplicant so we cannot unregister NM etc.
418 		 */
419 		wpa_printf(MSG_ERROR, "Failed to send event: %d", ret);
420 		goto free;
421 	}
422 
423 	while (retry++ < count && wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
424 		k_sleep(K_MSEC(IFACE_NOTIFY_RETRY_MS));
425 	}
426 
427 	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
428 		LOG_ERR("Failed to notify remove interface %s", ifname);
429 		supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED, -1);
430 		goto out;
431 	}
432 
433 	zephyr_wpa_ctrl_deinit(wpa_s);
434 
435 	ret = zephyr_wpa_cli_global_cmd_v("interface_remove %s", ifname);
436 	if (ret) {
437 		LOG_ERR("Failed to remove interface %s", ifname);
438 		supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED,
439 					  -EINVAL);
440 		goto out;
441 	}
442 
443 	ret = wifi_nm_unregister_mgd_iface(wifi_nm_get_instance("wifi_supplicant"), iface);
444 	if (ret) {
445 		LOG_ERR("Failed to unregister mgd iface %s with native stack (%d)",
446 			ifname, ret);
447 		goto out;
448 	}
449 
450 	if (get_iface_count(ctx) == 0) {
451 		supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0);
452 	}
453 
454 	supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED, 0);
455 
456 	return 0;
457 
458 free:
459 	if (event) {
460 		os_free(event);
461 	}
462 out:
463 	return ret;
464 }
465 #endif
iface_work_handler(struct k_work * work)466 static void iface_work_handler(struct k_work *work)
467 {
468 	struct supplicant_context *ctx = CONTAINER_OF(work, struct supplicant_context,
469 						      iface_work);
470 	int ret;
471 
472 	ret = (*ctx->iface_handler)(ctx, ctx->iface);
473 	if (ret < 0) {
474 		LOG_ERR("Interface %d (%p) handler failed (%d)",
475 			net_if_get_by_iface(ctx->iface), ctx->iface, ret);
476 	}
477 }
478 
479 /* As the mgmt thread stack is limited, use a separate work queue for any network
480  * interface add/delete.
481  */
submit_iface_work(struct supplicant_context * ctx,struct net_if * iface,int (* handler)(struct supplicant_context * ctx,struct net_if * iface))482 static void submit_iface_work(struct supplicant_context *ctx,
483 			      struct net_if *iface,
484 			      int (*handler)(struct supplicant_context *ctx,
485 					     struct net_if *iface))
486 {
487 	ctx->iface_handler = handler;
488 
489 	k_work_submit_to_queue(&ctx->iface_wq, &ctx->iface_work);
490 }
491 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
interface_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)492 static void interface_handler(struct net_mgmt_event_callback *cb,
493 			      uint32_t mgmt_event, struct net_if *iface)
494 {
495 	if ((mgmt_event & INTERFACE_EVENT_MASK) != mgmt_event) {
496 		return;
497 	}
498 
499 	if (!is_wanted_interface(iface)) {
500 		LOG_DBG("Ignoring event (0x%02x) from interface %d (%p)",
501 			mgmt_event, net_if_get_by_iface(iface), iface);
502 		return;
503 	}
504 
505 	if (mgmt_event == NET_EVENT_IF_ADMIN_UP) {
506 		LOG_INF("Network interface %d (%p) up", net_if_get_by_iface(iface), iface);
507 		add_interface(get_default_context(), iface);
508 		return;
509 	}
510 
511 	if (mgmt_event == NET_EVENT_IF_ADMIN_DOWN) {
512 		LOG_INF("Network interface %d (%p) down", net_if_get_by_iface(iface), iface);
513 		del_interface(get_default_context(), iface);
514 		return;
515 	}
516 }
517 #endif
518 
iface_cb(struct net_if * iface,void * user_data)519 static void iface_cb(struct net_if *iface, void *user_data)
520 {
521 	struct supplicant_context *ctx = user_data;
522 	int ret;
523 
524 	if (!net_if_is_wifi(iface)) {
525 		return;
526 	}
527 
528 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
529 	if (wifi_nm_iface_is_sap(iface)) {
530 		return;
531 	}
532 #endif
533 
534 	if (!net_if_is_admin_up(iface)) {
535 		return;
536 	}
537 
538 	ret = add_interface(ctx, iface);
539 	if (ret < 0) {
540 		return;
541 	}
542 }
543 
setup_interface_monitoring(struct supplicant_context * ctx,struct net_if * iface)544 static int setup_interface_monitoring(struct supplicant_context *ctx, struct net_if *iface)
545 {
546 	ARG_UNUSED(iface);
547 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
548 	net_mgmt_init_event_callback(&ctx->cb, interface_handler,
549 				     INTERFACE_EVENT_MASK);
550 	net_mgmt_add_event_callback(&ctx->cb);
551 #endif
552 	net_if_foreach(iface_cb, ctx);
553 
554 	return 0;
555 }
556 
event_socket_handler(int sock,void * eloop_ctx,void * user_data)557 static void event_socket_handler(int sock, void *eloop_ctx, void *user_data)
558 {
559 	struct supplicant_context *ctx = user_data;
560 	struct wpa_supplicant_event_msg msg;
561 	int ret;
562 
563 	ARG_UNUSED(eloop_ctx);
564 	ARG_UNUSED(ctx);
565 
566 	ret = zsock_recv(sock, &msg, sizeof(msg), 0);
567 	if (ret < 0) {
568 		LOG_ERR("Failed to recv the message (%d)", -errno);
569 		return;
570 	}
571 
572 	if (ret != sizeof(msg)) {
573 		LOG_ERR("Received incomplete message: got: %d, expected:%d",
574 			ret, sizeof(msg));
575 		return;
576 	}
577 
578 	LOG_DBG("Passing message %d to wpa_supplicant", msg.event);
579 
580 	if (msg.global) {
581 		wpa_supplicant_event_global(msg.ctx, msg.event, msg.data);
582 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
583 	} else if (msg.hostapd) {
584 		hostapd_event(msg.ctx, msg.event, msg.data);
585 #endif
586 	} else {
587 		wpa_supplicant_event(msg.ctx, msg.event, msg.data);
588 	}
589 
590 	if (msg.data) {
591 		union wpa_event_data *data = msg.data;
592 
593 		/* Free up deep copied data */
594 		if (msg.event == EVENT_AUTH) {
595 			os_free((char *)data->auth.ies);
596 		} else if (msg.event == EVENT_RX_MGMT) {
597 			os_free((char *)data->rx_mgmt.frame);
598 		} else if (msg.event == EVENT_TX_STATUS) {
599 			os_free((char *)data->tx_status.data);
600 		} else if (msg.event == EVENT_ASSOC) {
601 			os_free((char *)data->assoc_info.addr);
602 			os_free((char *)data->assoc_info.req_ies);
603 			os_free((char *)data->assoc_info.resp_ies);
604 			os_free((char *)data->assoc_info.resp_frame);
605 		} else if (msg.event == EVENT_ASSOC_REJECT) {
606 			os_free((char *)data->assoc_reject.bssid);
607 			os_free((char *)data->assoc_reject.resp_ies);
608 		} else if (msg.event == EVENT_DEAUTH) {
609 			os_free((char *)data->deauth_info.addr);
610 			os_free((char *)data->deauth_info.ie);
611 		} else if (msg.event == EVENT_DISASSOC) {
612 			os_free((char *)data->disassoc_info.addr);
613 			os_free((char *)data->disassoc_info.ie);
614 		} else if (msg.event == EVENT_UNPROT_DEAUTH) {
615 			os_free((char *)data->unprot_deauth.sa);
616 			os_free((char *)data->unprot_deauth.da);
617 		} else if (msg.event == EVENT_UNPROT_DISASSOC) {
618 			os_free((char *)data->unprot_disassoc.sa);
619 			os_free((char *)data->unprot_disassoc.da);
620 		}
621 
622 		os_free(msg.data);
623 	}
624 }
625 
register_supplicant_event_socket(struct supplicant_context * ctx)626 static int register_supplicant_event_socket(struct supplicant_context *ctx)
627 {
628 	int ret;
629 
630 	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->event_socketpair);
631 	if (ret < 0) {
632 		ret = -errno;
633 		LOG_ERR("Failed to initialize socket (%d)", ret);
634 		return ret;
635 	}
636 
637 	eloop_register_read_sock(ctx->event_socketpair[0], event_socket_handler, NULL, ctx);
638 
639 	return 0;
640 }
641 
642 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
hostapd_get_interface(const char * ifname)643 struct hostapd_iface *hostapd_get_interface(const char *ifname)
644 {
645 	struct supplicant_context *ctx;
646 
647 	ctx = get_default_context();
648 	(void)ifname;
649 	return ctx->hostapd.iface[0];
650 }
651 
hostapd_event_eapol_rx_cb(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)652 static void hostapd_event_eapol_rx_cb(void *ctx, const u8 *src_addr,
653 				       const u8 *buf, size_t len)
654 {
655 	hostapd_event_eapol_rx(ctx, src_addr, buf, len, FRAME_ENCRYPTION_UNKNOWN, -1);
656 }
657 
hostapd_enable_iface_cb(struct hostapd_iface * hapd_iface)658 static int hostapd_enable_iface_cb(struct hostapd_iface *hapd_iface)
659 {
660 	struct hostapd_data *bss;
661 
662 	wpa_printf(MSG_DEBUG, "Enable interface %s", hapd_iface->conf->bss[0]->iface);
663 
664 	bss = hapd_iface->bss[0];
665 
666 	bss->conf->start_disabled = 0;
667 
668 	if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
669 		wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
670 		return -1;
671 	}
672 
673 	l2_packet_deinit(bss->l2);
674 	bss->l2 = l2_packet_init(bss->conf->iface, bss->conf->bssid, ETH_P_EAPOL,
675 				 &hostapd_event_eapol_rx_cb, bss, 0);
676 	if (bss->l2 == NULL) {
677 		wpa_printf(MSG_ERROR, "Failed to initialize l2 for hostapd interface");
678 		return -1;
679 	}
680 
681 	if (hostapd_setup_interface(hapd_iface)) {
682 		wpa_printf(MSG_ERROR, "Failed to initialize hostapd interface");
683 		return -1;
684 	}
685 
686 	return 0;
687 }
688 
hostapd_disable_iface_cb(struct hostapd_iface * hapd_iface)689 static int hostapd_disable_iface_cb(struct hostapd_iface *hapd_iface)
690 {
691 	size_t j;
692 	struct hostapd_data *hapd = NULL;
693 
694 	wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
695 
696 	hapd_iface->driver_ap_teardown = !!(hapd_iface->drv_flags
697 					    & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
698 
699 #ifdef NEED_AP_MLME
700 	for (j = 0; j < hapd_iface->num_bss; j++) {
701 		hostapd_cleanup_cs_params(hapd_iface->bss[j]);
702 	}
703 #endif /* NEED_AP_MLME */
704 
705 	/* Same as hostapd_interface_deinit() without deinitializing control
706 	 * interface
707 	 */
708 	for (j = 0; j < hapd_iface->num_bss; j++) {
709 		hapd = hapd_iface->bss[j];
710 		hostapd_bss_deinit_no_free(hapd);
711 		hostapd_free_hapd_data(hapd);
712 	}
713 
714 	hostapd_drv_stop_ap(hapd);
715 
716 	hostapd_cleanup_iface_partial(hapd_iface);
717 
718 	wpa_printf(MSG_DEBUG, "Interface %s disabled", hapd_iface->bss[0]->conf->iface);
719 	hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED);
720 	supplicant_send_wifi_mgmt_ap_status(hapd_iface,
721 					    NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT,
722 					    WIFI_STATUS_AP_SUCCESS);
723 	hostapd_config_free(hapd_iface->conf);
724 	hapd_iface->conf = hapd_iface->interfaces->config_read_cb(hapd_iface->config_fname);
725 	for (j = 0; j < hapd_iface->num_bss; j++) {
726 		hapd = hapd_iface->bss[j];
727 		hapd->iconf = hapd_iface->conf;
728 		hapd->conf = hapd_iface->conf->bss[j];
729 		hapd->driver = hapd_iface->conf->driver;
730 	}
731 
732 	return 0;
733 }
734 
hostapd_global_init(struct hapd_interfaces * interfaces,const char * entropy_file)735 static int hostapd_global_init(struct hapd_interfaces *interfaces, const char *entropy_file)
736 {
737 	int i;
738 
739 	os_memset(&hglobal, 0, sizeof(struct hapd_global));
740 
741 	if (eap_server_register_methods()) {
742 		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
743 		return -1;
744 	}
745 
746 	interfaces->eloop_initialized = 1;
747 
748 	for (i = 0; wpa_drivers[i]; i++) {
749 		hglobal.drv_count++;
750 	}
751 
752 	if (hglobal.drv_count == 0) {
753 		wpa_printf(MSG_ERROR, "No drivers enabled");
754 		return -1;
755 	}
756 	hglobal.drv_priv = os_calloc(hglobal.drv_count, sizeof(void *));
757 	if (hglobal.drv_priv == NULL) {
758 		return -1;
759 	}
760 
761 	return 0;
762 }
763 
hostapd_driver_init(struct hostapd_iface * iface)764 static int hostapd_driver_init(struct hostapd_iface *iface)
765 {
766 	struct wpa_init_params params;
767 	size_t i;
768 	struct hostapd_data *hapd       = iface->bss[0];
769 	struct hostapd_bss_config *conf = hapd->conf;
770 	u8 *b                           = conf->bssid;
771 	struct wpa_driver_capa capa;
772 
773 	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
774 		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
775 		return -1;
776 	}
777 
778 	/* Initialize the driver interface */
779 	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) {
780 		b = NULL;
781 	}
782 
783 	os_memset(&params, 0, sizeof(params));
784 	for (i = 0; wpa_drivers[i]; i++) {
785 		if (wpa_drivers[i] != hapd->driver)
786 			continue;
787 
788 		if (hglobal.drv_priv[i] == NULL && wpa_drivers[i]->global_init) {
789 			hglobal.drv_priv[i] = wpa_drivers[i]->global_init(iface->interfaces);
790 			if (hglobal.drv_priv[i] == NULL) {
791 				wpa_printf(MSG_ERROR, "Failed to initialize driver '%s'",
792 					   wpa_drivers[i]->name);
793 				return -1;
794 			}
795 			hglobal.drv_count++;
796 		}
797 
798 		params.global_priv = hglobal.drv_priv[i];
799 		break;
800 	}
801 	params.bssid              = b;
802 	params.ifname             = hapd->conf->iface;
803 	params.driver_params      = hapd->iconf->driver_params;
804 	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
805 	params.num_bridge         = hapd->iface->num_bss;
806 	params.bridge             = os_calloc(hapd->iface->num_bss, sizeof(char *));
807 	if (params.bridge == NULL) {
808 		return -1;
809 	}
810 	for (i = 0; i < hapd->iface->num_bss; i++) {
811 		struct hostapd_data *bss = hapd->iface->bss[i];
812 
813 		if (bss->conf->bridge[0]) {
814 			params.bridge[i] = bss->conf->bridge;
815 		}
816 	}
817 
818 	params.own_addr = hapd->own_addr;
819 
820 	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
821 	os_free(params.bridge);
822 	if (hapd->drv_priv == NULL) {
823 		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
824 			   hapd->driver->name);
825 		hapd->driver = NULL;
826 		return -1;
827 	}
828 
829 	if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
830 		struct wowlan_triggers *triggs;
831 
832 		iface->drv_flags           = capa.flags;
833 		iface->drv_flags2          = capa.flags2;
834 		iface->probe_resp_offloads = capa.probe_resp_offloads;
835 		/*
836 		 * Use default extended capa values from per-radio information
837 		 */
838 		iface->extended_capa         = capa.extended_capa;
839 		iface->extended_capa_mask    = capa.extended_capa_mask;
840 		iface->extended_capa_len     = capa.extended_capa_len;
841 		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
842 
843 		/*
844 		 * Override extended capa with per-interface type (AP), if
845 		 * available from the driver.
846 		 */
847 		hostapd_get_ext_capa(iface);
848 
849 		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
850 		if (triggs && hapd->driver->set_wowlan) {
851 			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) {
852 				wpa_printf(MSG_ERROR, "set_wowlan failed");
853 			}
854 		}
855 		os_free(triggs);
856 	}
857 
858 	return 0;
859 }
860 
hostapd_config_read2(const char * fname)861 struct hostapd_config *hostapd_config_read2(const char *fname)
862 {
863 	struct hostapd_config *conf;
864 	const struct device *dev;
865 	char ifname[IFNAMSIZ + 1] = {0};
866 	int errors = 0;
867 	size_t i;
868 	int aCWmin = 4, aCWmax = 10;
869 	/* background traffic */
870 	struct hostapd_wmm_ac_params ac_bk = {aCWmin, aCWmax, 9, 0, 0};
871 	/* best effort traffic */
872 	struct hostapd_wmm_ac_params ac_be = {aCWmin, aCWmax - 4, 5, 0, 0};
873 	/* video traffic */
874 	struct hostapd_wmm_ac_params ac_vi = {aCWmin - 1, aCWmin, 3,
875 					      3008 / 32, 0};
876 	/* voice traffic */
877 	struct hostapd_wmm_ac_params ac_vo = {aCWmin - 2, aCWmin - 1, 3,
878 					      1504 / 32, 0};
879 
880 	dev = net_if_get_device(net_if_get_wifi_sap());
881 	strncpy(ifname, dev->name, IFNAMSIZ);
882 	ifname[IFNAMSIZ] = '\0';
883 
884 	conf = hostapd_config_defaults();
885 	if (conf == NULL) {
886 		return NULL;
887 	}
888 
889 	conf->wmm_ac_params[0] = ac_be;
890 	conf->wmm_ac_params[1] = ac_bk;
891 	conf->wmm_ac_params[2] = ac_vi;
892 	conf->wmm_ac_params[3] = ac_vo;
893 
894 	/* set default driver based on configuration */
895 	conf->driver = wpa_drivers[0];
896 	if (conf->driver == NULL) {
897 		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
898 		hostapd_config_free(conf);
899 		return NULL;
900 	}
901 	conf->last_bss = conf->bss[0];
902 	struct hostapd_bss_config *bss;
903 
904 	bss                 = conf->last_bss;
905 	bss->start_disabled = 1;
906 	bss->max_num_sta    = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA;
907 	bss->dtim_period    = 1;
908 	os_strlcpy(conf->bss[0]->iface, ifname, sizeof(conf->bss[0]->iface));
909 	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
910 	bss->logger_stdout       = 0xffff;
911 	bss->nas_identifier      = os_strdup("ap.example.com");
912 	os_memcpy(conf->country, "US ", 3);
913 	conf->hw_mode        = HOSTAPD_MODE_IEEE80211G;
914 	bss->wps_state       = WPS_STATE_CONFIGURED;
915 	bss->eap_server      = 1;
916 #ifdef CONFIG_WPS
917 	bss->ap_setup_locked = 1;
918 #endif
919 	conf->channel        = 1;
920 	conf->acs            = conf->channel == 0;
921 #ifdef CONFIG_ACS
922 	conf->acs_num_scans  = 1;
923 #endif
924 	conf->ieee80211n     = 1;
925 	conf->ieee80211h     = 0;
926 	conf->ieee80211d     = 1;
927 	conf->acs_exclude_dfs = 1;
928 	conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
929 	bss->auth_algs = 1;
930 	bss->okc = 1;
931 	conf->no_pri_sec_switch = 1;
932 	conf->ht_op_mode_fixed  = 1;
933 	conf->ieee80211ac       = 1;
934 	conf->vht_oper_chwidth  = CHANWIDTH_USE_HT;
935 	conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
936 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX
937 	conf->ieee80211ax       = 1;
938 	conf->he_oper_chwidth   = CHANWIDTH_USE_HT;
939 	conf->he_phy_capab.he_su_beamformer = 0;
940 	conf->he_phy_capab.he_su_beamformee = 1;
941 	conf->he_phy_capab.he_mu_beamformer = 0;
942 	conf->he_op.he_bss_color = 1;
943 	conf->he_op.he_default_pe_duration  = 0;
944 	/* Set default basic MCS/NSS set to single stream MCS 0-7 */
945 	conf->he_op.he_basic_mcs_nss_set    = 0xfffc;
946 #endif
947 
948 	for (i = 0; i < conf->num_bss; i++) {
949 		hostapd_set_security_params(conf->bss[i], 1);
950 	}
951 
952 	if (hostapd_config_check(conf, 1)) {
953 		errors++;
954 	}
955 
956 #ifndef WPA_IGNORE_CONFIG_ERRORS
957 	if (errors) {
958 		wpa_printf(MSG_ERROR, "%d errors found in configuration file '%s'",
959 			   errors, fname);
960 		hostapd_config_free(conf);
961 		conf = NULL;
962 	}
963 #endif /* WPA_IGNORE_CONFIG_ERRORS */
964 	return conf;
965 }
966 
hostapd_interface_init(struct hapd_interfaces * interfaces,const char * if_name,const char * config_fname,int debug)967 static struct hostapd_iface *hostapd_interface_init(struct hapd_interfaces *interfaces,
968 						    const char *if_name,
969 						    const char *config_fname,
970 						    int debug)
971 {
972 	struct hostapd_iface *iface;
973 	int k;
974 
975 	wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
976 	iface = hostapd_init(interfaces, config_fname);
977 	if (!iface) {
978 		return NULL;
979 	}
980 
981 	if (if_name) {
982 		os_strlcpy(iface->conf->bss[0]->iface, if_name,
983 			   sizeof(iface->conf->bss[0]->iface));
984 	}
985 
986 	iface->interfaces = interfaces;
987 
988 	for (k = 0; k < debug; k++) {
989 		if (iface->bss[0]->conf->logger_stdout_level > 0) {
990 			iface->bss[0]->conf->logger_stdout_level--;
991 		}
992 	}
993 
994 	if (iface->conf->bss[0]->iface[0] == '\0' &&
995 	    !hostapd_drv_none(iface->bss[0])) {
996 		wpa_printf(MSG_ERROR,
997 			   "Interface name not specified in %s, nor by '-i' parameter",
998 			   config_fname);
999 		hostapd_interface_deinit_free(iface);
1000 		return NULL;
1001 	}
1002 
1003 	iface->bss[0]->is_hostapd = 1;
1004 
1005 	return iface;
1006 }
1007 
zephyr_hostapd_init(struct supplicant_context * ctx)1008 static void zephyr_hostapd_init(struct supplicant_context *ctx)
1009 {
1010 	struct hapd_interfaces *interfaces = &ctx->hostapd;
1011 	size_t i;
1012 	int ret, debug = 0;
1013 	struct net_if *iface;
1014 	char ifname[IFNAMSIZ + 1] = { 0 };
1015 	const char *entropy_file = NULL;
1016 	size_t num_bss_configs = 0;
1017 	int start_ifaces_in_sync = 0;
1018 #ifdef CONFIG_DPP
1019 	struct dpp_global_config dpp_conf;
1020 #endif /* CONFIG_DPP */
1021 
1022 	os_memset(interfaces, 0, sizeof(struct hapd_interfaces));
1023 	interfaces->reload_config      = hostapd_reload_config;
1024 	interfaces->config_read_cb     = hostapd_config_read2;
1025 	interfaces->for_each_interface = hostapd_for_each_interface;
1026 	interfaces->driver_init        = hostapd_driver_init;
1027 	interfaces->global_ctrl_sock   = -1;
1028 	dl_list_init(&interfaces->global_ctrl_dst);
1029 #ifdef CONFIG_DPP
1030 	os_memset(&dpp_conf, 0, sizeof(dpp_conf));
1031 	dpp_conf.cb_ctx = interfaces;
1032 	interfaces->dpp = dpp_global_init(&dpp_conf);
1033 	if (!interfaces->dpp) {
1034 		return;
1035 	}
1036 #endif /* CONFIG_DPP */
1037 
1038 	interfaces->count = 1;
1039 	if (interfaces->count || num_bss_configs) {
1040 		interfaces->iface = os_calloc(interfaces->count + num_bss_configs,
1041 					      sizeof(struct hostapd_iface *));
1042 		if (interfaces->iface == NULL) {
1043 			wpa_printf(MSG_ERROR, "malloc failed");
1044 			return;
1045 		}
1046 	}
1047 
1048 	if (hostapd_global_init(interfaces, entropy_file)) {
1049 		wpa_printf(MSG_ERROR, "Failed to initialize global context");
1050 		return;
1051 	}
1052 
1053 	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
1054 			       hostapd_periodic, interfaces, NULL);
1055 
1056 	iface = net_if_get_wifi_sap();
1057 	ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
1058 	if (ret < 0) {
1059 		LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface);
1060 		goto out;
1061 	}
1062 
1063 	for (i = 0; i < interfaces->count; i++) {
1064 		interfaces->iface[i] = hostapd_interface_init(interfaces, ifname,
1065 							      "hostapd.conf", debug);
1066 		if (!interfaces->iface[i]) {
1067 			wpa_printf(MSG_ERROR, "Failed to initialize interface");
1068 			goto out;
1069 		}
1070 		if (start_ifaces_in_sync) {
1071 			interfaces->iface[i]->need_to_start_in_sync = 0;
1072 		}
1073 	}
1074 
1075 	/*
1076 	 * Enable configured interfaces. Depending on channel configuration,
1077 	 * this may complete full initialization before returning or use a
1078 	 * callback mechanism to complete setup in case of operations like HT
1079 	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
1080 	 * In such case, the interface will be enabled from eloop context within
1081 	 * hostapd_global_run().
1082 	 */
1083 	interfaces->terminate_on_error = 0;
1084 	for (i = 0; i < interfaces->count; i++) {
1085 		if (hostapd_driver_init(interfaces->iface[i])) {
1086 			goto out;
1087 		}
1088 
1089 		interfaces->iface[i]->enable_iface_cb  = hostapd_enable_iface_cb;
1090 		interfaces->iface[i]->disable_iface_cb = hostapd_disable_iface_cb;
1091 		zephyr_hostapd_ctrl_init((void *)interfaces->iface[i]->bss[0]);
1092 	}
1093 
1094 out:
1095 	return;
1096 }
1097 
zephyr_hostap_msg_ifname_cb(void * ctx)1098 static const char *zephyr_hostap_msg_ifname_cb(void *ctx)
1099 {
1100 	if (ctx == NULL) {
1101 		return NULL;
1102 	}
1103 
1104 	if ((*((int *)ctx)) == 0) {
1105 		struct wpa_supplicant *wpa_s = ctx;
1106 
1107 		return wpa_s->ifname;
1108 	}
1109 
1110 	struct hostapd_data *hapd = ctx;
1111 
1112 	if (hapd && hapd->conf) {
1113 		return hapd->conf->iface;
1114 	}
1115 
1116 	return NULL;
1117 }
1118 
zephyr_hostap_ctrl_iface_msg_cb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)1119 static void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type,
1120 					    const char *txt, size_t len)
1121 {
1122 	if (ctx == NULL) {
1123 		return;
1124 	}
1125 
1126 	if ((*((int *)ctx)) == 0) {
1127 		wpa_supplicant_msg_send(ctx, level, type, txt, len);
1128 	} else {
1129 		hostapd_msg_send(ctx, level, type, txt, len);
1130 	}
1131 }
1132 #endif
1133 
handler(void)1134 static void handler(void)
1135 {
1136 	struct supplicant_context *ctx;
1137 	struct wpa_params params;
1138 
1139 #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP)
1140 	/* Needed for crypto operation as default is no-op and fails */
1141 	mbedtls_platform_set_calloc_free(calloc, free);
1142 #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */
1143 
1144 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA
1145 	supp_psa_crypto_init();
1146 #endif
1147 
1148 	ctx = get_default_context();
1149 
1150 	k_work_queue_init(&ctx->iface_wq);
1151 	k_work_queue_start(&ctx->iface_wq, iface_wq_stack,
1152 			   K_THREAD_STACK_SIZEOF(iface_wq_stack),
1153 			   CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_PRIO,
1154 			   NULL);
1155 
1156 	k_work_init(&ctx->iface_work, iface_work_handler);
1157 
1158 	memset(&params, 0, sizeof(params));
1159 	params.wpa_debug_level = CONFIG_WIFI_NM_WPA_SUPPLICANT_DEBUG_LEVEL;
1160 
1161 	ctx->supplicant = wpa_supplicant_init(&params);
1162 	if (ctx->supplicant == NULL) {
1163 		LOG_ERR("Failed to initialize %s", "wpa_supplicant");
1164 		goto err;
1165 	}
1166 
1167 	LOG_INF("%s initialized", "wpa_supplicant");
1168 
1169 	if (fst_global_init()) {
1170 		LOG_ERR("Failed to initialize %s", "FST");
1171 		goto out;
1172 	}
1173 
1174 #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
1175 	if (!fst_global_add_ctrl(fst_ctrl_cli)) {
1176 		LOG_WRN("Failed to add CLI FST ctrl");
1177 	}
1178 #endif
1179 	zephyr_global_wpa_ctrl_init();
1180 
1181 	register_supplicant_event_socket(ctx);
1182 
1183 	submit_iface_work(ctx, NULL, setup_interface_monitoring);
1184 
1185 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
1186 	zephyr_hostapd_init(ctx);
1187 	wpa_msg_register_ifname_cb(zephyr_hostap_msg_ifname_cb);
1188 #endif
1189 
1190 	(void)wpa_supplicant_run(ctx->supplicant);
1191 
1192 	supplicant_generate_state_event(ctx->if_name, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0);
1193 
1194 	eloop_unregister_read_sock(ctx->event_socketpair[0]);
1195 
1196 	zephyr_global_wpa_ctrl_deinit();
1197 
1198 	fst_global_deinit();
1199 
1200 out:
1201 	wpa_supplicant_deinit(ctx->supplicant);
1202 
1203 	zsock_close(ctx->event_socketpair[0]);
1204 	zsock_close(ctx->event_socketpair[1]);
1205 
1206 err:
1207 	os_free(params.pid_file);
1208 }
1209 
init(void)1210 static int init(void)
1211 {
1212 	/* We create a thread that handles all supplicant connections */
1213 	k_thread_create(&tid, supplicant_thread_stack,
1214 			K_THREAD_STACK_SIZEOF(supplicant_thread_stack),
1215 			(k_thread_entry_t)handler, NULL, NULL, NULL,
1216 			CONFIG_WIFI_NM_WPA_SUPPLICANT_PRIO, 0, K_NO_WAIT);
1217 
1218 	return 0;
1219 }
1220 
1221 SYS_INIT(init, APPLICATION, 0);
1222