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 #include <zephyr/zvfs/eventfd.h>
15
16 #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP)
17 #include <mbedtls/platform.h>
18 #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */
19 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA
20 #include "supp_psa_api.h"
21 #endif
22
23 #include <zephyr/net/wifi_mgmt.h>
24 #include <zephyr/net/wifi_nm.h>
25 #include <zephyr/net/socket.h>
26
27 static K_THREAD_STACK_DEFINE(supplicant_thread_stack,
28 CONFIG_WIFI_NM_WPA_SUPPLICANT_THREAD_STACK_SIZE);
29 static struct k_thread tid;
30
31 static K_THREAD_STACK_DEFINE(iface_wq_stack, CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_STACK_SIZE);
32
33 #define IFACE_NOTIFY_TIMEOUT_MS 1000
34 #define IFACE_NOTIFY_RETRY_MS 10
35
36 #include "supp_main.h"
37 #include "supp_api.h"
38 #include "supp_events.h"
39
40 #include "includes.h"
41 #include "common.h"
42 #include "eloop.h"
43 #include "wpa_supplicant/config.h"
44 #include "wpa_supplicant_i.h"
45 #include "fst/fst.h"
46 #include "includes.h"
47 #include "wpa_cli_zephyr.h"
48 #include "ctrl_iface_zephyr.h"
49 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
50 #include "hostapd.h"
51 #include "hapd_main.h"
52 #endif
53
54 static const struct wifi_mgmt_ops mgmt_ops = {
55 .get_version = supplicant_get_version,
56 .scan = supplicant_scan,
57 .connect = supplicant_connect,
58 .disconnect = supplicant_disconnect,
59 .iface_status = supplicant_status,
60 #ifdef CONFIG_NET_STATISTICS_WIFI
61 .get_stats = supplicant_get_stats,
62 .reset_stats = supplicant_reset_stats,
63 #endif
64 .cfg_11k = supplicant_11k_cfg,
65 .send_11k_neighbor_request = supplicant_11k_neighbor_request,
66 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
67 .candidate_scan = supplicant_candidate_scan,
68 .start_11r_roaming = supplicant_11r_roaming,
69 #endif
70 .set_power_save = supplicant_set_power_save,
71 .set_twt = supplicant_set_twt,
72 .get_power_save_config = supplicant_get_power_save_config,
73 .reg_domain = supplicant_reg_domain,
74 .mode = supplicant_mode,
75 .filter = supplicant_filter,
76 .channel = supplicant_channel,
77 .set_rts_threshold = supplicant_set_rts_threshold,
78 .get_rts_threshold = supplicant_get_rts_threshold,
79 .bss_support_neighbor_rep = supplicant_bss_support_neighbor_rep,
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 .set_bss_max_idle_period = supplicant_set_bss_max_idle_period,
88 #ifdef CONFIG_AP
89 .ap_enable = supplicant_ap_enable,
90 .ap_disable = supplicant_ap_disable,
91 .ap_sta_disconnect = supplicant_ap_sta_disconnect,
92 #endif /* CONFIG_AP */
93 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
94 .dpp_dispatch = supplicant_dpp_dispatch,
95 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
96 .pmksa_flush = supplicant_pmksa_flush,
97 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
98 .enterprise_creds = supplicant_add_enterprise_creds,
99 #endif
100 .config_params = supplicant_config_params,
101 };
102
103 DEFINE_WIFI_NM_INSTANCE(wifi_supplicant, &mgmt_ops);
104
105 #define WRITE_TIMEOUT 100 /* ms */
106 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
107 #define INTERFACE_EVENT_MASK (NET_EVENT_IF_ADMIN_UP | NET_EVENT_IF_ADMIN_DOWN)
108 #endif
109 struct supplicant_context {
110 struct wpa_global *supplicant;
111 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
112 struct hapd_interfaces hostapd;
113 #endif
114 struct net_mgmt_event_callback cb;
115 struct net_if *iface;
116 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
117 struct k_fifo fifo;
118 int sock;
119 struct k_work iface_work;
120 struct k_work_q iface_wq;
121 int (*iface_handler)(struct supplicant_context *ctx, struct net_if *iface);
122 };
123
get_default_context(void)124 static struct supplicant_context *get_default_context(void)
125 {
126 static struct supplicant_context ctx;
127
128 return &ctx;
129 }
130
zephyr_get_default_supplicant_context(void)131 struct wpa_global *zephyr_get_default_supplicant_context(void)
132 {
133 return get_default_context()->supplicant;
134 }
135
136 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
zephyr_get_default_hapd_context(void)137 struct hapd_interfaces *zephyr_get_default_hapd_context(void)
138 {
139 return &get_default_context()->hostapd;
140 }
141 #endif
142
get_workq(void)143 struct k_work_q *get_workq(void)
144 {
145 return &get_default_context()->iface_wq;
146 }
147
148 /* found in hostap/wpa_supplicant/ctrl_iface_zephyr.c */
149 extern int send_data(struct k_fifo *fifo, int sock, const char *buf, size_t len, int flags);
150
zephyr_wifi_send_event(const struct wpa_supplicant_event_msg * msg)151 int zephyr_wifi_send_event(const struct wpa_supplicant_event_msg *msg)
152 {
153 struct supplicant_context *ctx;
154 int ret;
155
156 /* TODO: Fix this to get the correct container */
157 ctx = get_default_context();
158
159 if (ctx->sock < 0) {
160 ret = -ENOENT;
161 goto out;
162 }
163
164 ret = send_data(&ctx->fifo, ctx->sock,
165 (const char *)msg, sizeof(*msg), 0);
166 if (ret != 0) {
167 ret = -EMSGSIZE;
168 LOG_WRN("Event partial send (%d)", ret);
169 goto out;
170 }
171
172 ret = 0;
173
174 out:
175 return ret;
176 }
177
178 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
send_event(const struct wpa_supplicant_event_msg * msg)179 static int send_event(const struct wpa_supplicant_event_msg *msg)
180 {
181 return zephyr_wifi_send_event(msg);
182 }
183
is_wanted_interface(struct net_if * iface)184 static bool is_wanted_interface(struct net_if *iface)
185 {
186 if (!net_if_is_wifi(iface)) {
187 return false;
188 }
189
190 /* TODO: check against a list of valid interfaces */
191
192 return true;
193 }
194 #endif
zephyr_get_handle_by_ifname(const char * ifname)195 struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname)
196 {
197 struct wpa_supplicant *wpa_s = NULL;
198 struct supplicant_context *ctx = get_default_context();
199
200 wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
201 if (!wpa_s) {
202 wpa_printf(MSG_ERROR, "%s: Unable to get wpa_s handle for %s\n", __func__, ifname);
203 return NULL;
204 }
205
206 return wpa_s;
207 }
208
get_iface_count(struct supplicant_context * ctx)209 static int get_iface_count(struct supplicant_context *ctx)
210 {
211 /* FIXME, should not access ifaces as it is supplicant internal data */
212 struct wpa_supplicant *wpa_s;
213 unsigned int count = 0;
214
215 for (wpa_s = ctx->supplicant->ifaces; wpa_s; wpa_s = wpa_s->next) {
216 count += 1;
217 }
218
219 return count;
220 }
221
zephyr_wpa_supplicant_msg(void * ctx,const char * txt,size_t len)222 static void zephyr_wpa_supplicant_msg(void *ctx, const char *txt, size_t len)
223 {
224 struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)ctx;
225
226 if (!ctx || !txt) {
227 return;
228 }
229
230 /* Only interested in CTRL-EVENTs */
231 if (strncmp(txt, "CTRL-EVENT", 10) == 0) {
232 if (strncmp(txt, "CTRL-EVENT-SIGNAL-CHANGE", 24) == 0) {
233 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
234 NET_EVENT_WIFI_CMD_SIGNAL_CHANGE,
235 (void *)txt, len);
236 } else {
237 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
238 NET_EVENT_WIFI_CMD_SUPPLICANT,
239 (void *)txt, len);
240 }
241 } else if (strncmp(txt, "RRM-NEIGHBOR-REP-RECEIVED", 25) == 0) {
242 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
243 NET_EVENT_WIFI_CMD_NEIGHBOR_REP_RECEIVED,
244 (void *)txt, len);
245 }
246 }
247
zephyr_hostap_msg_ifname_cb(void * ctx)248 static const char *zephyr_hostap_msg_ifname_cb(void *ctx)
249 {
250 if (ctx == NULL) {
251 return NULL;
252 }
253
254 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
255 if ((((struct wpa_supplicant *)ctx))->is_hostapd == 0) {
256 struct wpa_supplicant *wpa_s = ctx;
257
258 return wpa_s->ifname;
259 }
260
261 struct hostapd_data *hapd = ctx;
262
263 if (hapd && hapd->conf) {
264 return hapd->conf->iface;
265 }
266
267 return NULL;
268 #else
269 struct wpa_supplicant *wpa_s = ctx;
270
271 return wpa_s->ifname;
272 #endif
273 }
274
zephyr_hostap_ctrl_iface_msg_cb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)275 static void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type,
276 const char *txt, size_t len)
277 {
278 ARG_UNUSED(level);
279 ARG_UNUSED(type);
280
281 if (ctx == NULL) {
282 return;
283 }
284
285 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
286 if ((((struct wpa_supplicant *)ctx))->is_hostapd == 0) {
287 zephyr_wpa_supplicant_msg(ctx, txt, len);
288 } else {
289 zephyr_hostapd_msg(ctx, txt, len);
290 }
291 #else
292 zephyr_wpa_supplicant_msg(ctx, txt, len);
293 #endif
294 }
295
add_interface(struct supplicant_context * ctx,struct net_if * iface)296 static int add_interface(struct supplicant_context *ctx, struct net_if *iface)
297 {
298 struct wpa_supplicant *wpa_s;
299 char ifname[IFNAMSIZ + 1] = { 0 };
300 int ret, retry = 0, count = IFACE_NOTIFY_TIMEOUT_MS / IFACE_NOTIFY_RETRY_MS;
301
302 ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
303 if (ret < 0) {
304 LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface);
305 goto out;
306 }
307
308 LOG_DBG("Adding interface %s [%d] (%p)", ifname, net_if_get_by_iface(iface), iface);
309
310 ret = zephyr_wpa_cli_global_cmd_v("interface_add %s %s %s %s",
311 ifname, "zephyr", "zephyr", "zephyr");
312 if (ret) {
313 LOG_ERR("Failed to add interface %s", ifname);
314 goto out;
315 }
316
317 while (retry++ < count && !wpa_supplicant_get_iface(ctx->supplicant, ifname)) {
318 k_sleep(K_MSEC(IFACE_NOTIFY_RETRY_MS));
319 }
320
321 wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
322 if (wpa_s == NULL) {
323 LOG_ERR("Failed to add iface %s", ifname);
324 goto out;
325 }
326
327 wpa_s->conf->filter_ssids = 1;
328 wpa_s->conf->ap_scan = 1;
329
330 /* Default interface, kick start supplicant */
331 if (get_iface_count(ctx) > 0) {
332 ctx->iface = iface;
333 net_if_get_name(iface, ctx->if_name, CONFIG_NET_INTERFACE_NAME_LEN);
334 }
335
336 ret = zephyr_wpa_ctrl_init(wpa_s);
337 if (ret) {
338 LOG_ERR("Failed to initialize supplicant control interface");
339 goto out;
340 }
341
342 ret = wifi_nm_register_mgd_type_iface(wifi_nm_get_instance("wifi_supplicant"),
343 WIFI_TYPE_STA,
344 iface);
345 if (ret) {
346 LOG_ERR("Failed to register mgd iface with native stack %s (%d)",
347 ifname, ret);
348 goto out;
349 }
350
351 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_ADDED, 0);
352
353 if (get_iface_count(ctx) == 1) {
354 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_READY, 0);
355 }
356
357 wpa_msg_register_cb(zephyr_hostap_ctrl_iface_msg_cb);
358 ret = 0;
359
360 out:
361 return ret;
362 }
363 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
del_interface(struct supplicant_context * ctx,struct net_if * iface)364 static int del_interface(struct supplicant_context *ctx, struct net_if *iface)
365 {
366 struct wpa_supplicant_event_msg msg;
367 struct wpa_supplicant *wpa_s;
368 union wpa_event_data *event = NULL;
369 int ret, retry = 0, count = IFACE_NOTIFY_TIMEOUT_MS / IFACE_NOTIFY_RETRY_MS;
370 char ifname[IFNAMSIZ + 1] = { 0 };
371
372 ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
373 if (ret < 0) {
374 LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface);
375 goto out;
376 }
377
378 LOG_DBG("Removing interface %s %d (%p)", ifname, net_if_get_by_iface(iface), iface);
379
380 event = os_zalloc(sizeof(*event));
381 if (!event) {
382 ret = -ENOMEM;
383 LOG_ERR("Failed to allocate event data");
384 goto out;
385 }
386
387 wpa_s = wpa_supplicant_get_iface(ctx->supplicant, ifname);
388 if (!wpa_s) {
389 ret = -ENOENT;
390 LOG_ERR("Failed to get wpa_s handle for %s", ifname);
391 goto free;
392 }
393
394 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVING, 0);
395
396 if (sizeof(event->interface_status.ifname) < strlen(ifname)) {
397 wpa_printf(MSG_ERROR, "Interface name too long: %s (max: %zu)",
398 ifname, sizeof(event->interface_status.ifname));
399 goto free;
400 }
401
402 os_memcpy(event->interface_status.ifname, ifname, strlen(ifname));
403 event->interface_status.ievent = EVENT_INTERFACE_REMOVED;
404
405 msg.global = true;
406 msg.ctx = ctx->supplicant;
407 msg.event = EVENT_INTERFACE_STATUS;
408 msg.data = event;
409
410 ret = send_event(&msg);
411 if (ret) {
412 /* We failed notify WPA supplicant about interface removal.
413 * There is not much we can do, interface is still registered
414 * with WPA supplicant so we cannot unregister NM etc.
415 */
416 wpa_printf(MSG_ERROR, "Failed to send event: %d", ret);
417 goto free;
418 }
419
420 while (retry++ < count && wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
421 k_sleep(K_MSEC(IFACE_NOTIFY_RETRY_MS));
422 }
423
424 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
425 LOG_ERR("Failed to notify remove interface %s", ifname);
426 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED, -1);
427 goto out;
428 }
429
430 zephyr_wpa_ctrl_deinit(wpa_s);
431
432 ret = zephyr_wpa_cli_global_cmd_v("interface_remove %s", ifname);
433 if (ret) {
434 LOG_ERR("Failed to remove interface %s", ifname);
435 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED,
436 -EINVAL);
437 goto out;
438 }
439
440 ret = wifi_nm_unregister_mgd_iface(wifi_nm_get_instance("wifi_supplicant"), iface);
441 if (ret) {
442 LOG_ERR("Failed to unregister mgd iface %s with native stack (%d)",
443 ifname, ret);
444 goto out;
445 }
446
447 if (get_iface_count(ctx) == 0) {
448 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0);
449 }
450
451 supplicant_generate_state_event(ifname, NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED, 0);
452
453 return 0;
454
455 free:
456 if (event) {
457 os_free(event);
458 }
459 out:
460 return ret;
461 }
462 #endif
iface_work_handler(struct k_work * work)463 static void iface_work_handler(struct k_work *work)
464 {
465 struct supplicant_context *ctx = CONTAINER_OF(work, struct supplicant_context,
466 iface_work);
467 int ret;
468
469 ret = (*ctx->iface_handler)(ctx, ctx->iface);
470 if (ret < 0) {
471 LOG_ERR("Interface %d (%p) handler failed (%d)",
472 net_if_get_by_iface(ctx->iface), ctx->iface, ret);
473 }
474 }
475
476 /* As the mgmt thread stack is limited, use a separate work queue for any network
477 * interface add/delete.
478 */
submit_iface_work(struct supplicant_context * ctx,struct net_if * iface,int (* handler)(struct supplicant_context * ctx,struct net_if * iface))479 static void submit_iface_work(struct supplicant_context *ctx,
480 struct net_if *iface,
481 int (*handler)(struct supplicant_context *ctx,
482 struct net_if *iface))
483 {
484 ctx->iface_handler = handler;
485
486 k_work_submit_to_queue(&ctx->iface_wq, &ctx->iface_work);
487 }
488 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
interface_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)489 static void interface_handler(struct net_mgmt_event_callback *cb,
490 uint64_t mgmt_event, struct net_if *iface)
491 {
492 if ((mgmt_event & INTERFACE_EVENT_MASK) != mgmt_event) {
493 return;
494 }
495
496 if (!is_wanted_interface(iface)) {
497 LOG_DBG("Ignoring event (0x%" PRIx64 ") from interface %d (%p)",
498 mgmt_event, net_if_get_by_iface(iface), iface);
499 return;
500 }
501
502 if (mgmt_event == NET_EVENT_IF_ADMIN_UP) {
503 LOG_INF("Network interface %d (%p) up", net_if_get_by_iface(iface), iface);
504 add_interface(get_default_context(), iface);
505 return;
506 }
507
508 if (mgmt_event == NET_EVENT_IF_ADMIN_DOWN) {
509 LOG_INF("Network interface %d (%p) down", net_if_get_by_iface(iface), iface);
510 del_interface(get_default_context(), iface);
511 return;
512 }
513 }
514 #endif
515
iface_cb(struct net_if * iface,void * user_data)516 static void iface_cb(struct net_if *iface, void *user_data)
517 {
518 struct supplicant_context *ctx = user_data;
519 int ret;
520
521 if (!net_if_is_wifi(iface)) {
522 return;
523 }
524
525 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
526 if (wifi_nm_iface_is_sap(iface)) {
527 return;
528 }
529 #endif
530
531 if (!net_if_is_admin_up(iface)) {
532 return;
533 }
534
535 ret = add_interface(ctx, iface);
536 if (ret < 0) {
537 return;
538 }
539 }
540
setup_interface_monitoring(struct supplicant_context * ctx,struct net_if * iface)541 static int setup_interface_monitoring(struct supplicant_context *ctx, struct net_if *iface)
542 {
543 ARG_UNUSED(iface);
544 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON
545 net_mgmt_init_event_callback(&ctx->cb, interface_handler,
546 INTERFACE_EVENT_MASK);
547 net_mgmt_add_event_callback(&ctx->cb);
548 #endif
549 net_if_foreach(iface_cb, ctx);
550
551 return 0;
552 }
553
event_socket_handler(int sock,void * eloop_ctx,void * user_data)554 static void event_socket_handler(int sock, void *eloop_ctx, void *user_data)
555 {
556 struct supplicant_context *ctx = user_data;
557 struct wpa_supplicant_event_msg event_msg;
558 struct zephyr_msg *msg;
559 zvfs_eventfd_t value;
560
561 ARG_UNUSED(eloop_ctx);
562
563 do {
564 zvfs_eventfd_read(sock, &value);
565
566 msg = k_fifo_get(&ctx->fifo, K_NO_WAIT);
567 if (msg == NULL) {
568 LOG_ERR("fifo(event): %s", "empty");
569 return;
570 }
571
572 if (msg->data == NULL) {
573 LOG_ERR("fifo(event): %s", "no data");
574 goto out;
575 }
576
577 if (msg->len != sizeof(event_msg)) {
578 LOG_ERR("Received incomplete message: got: %d, expected:%d",
579 msg->len, sizeof(event_msg));
580 goto out;
581 }
582
583 memcpy(&event_msg, msg->data, sizeof(event_msg));
584
585 LOG_DBG("Passing message %d to wpa_supplicant", event_msg.event);
586
587 if (event_msg.global) {
588 wpa_supplicant_event_global(event_msg.ctx, event_msg.event,
589 event_msg.data);
590 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
591 } else if (event_msg.hostapd) {
592 hostapd_event(event_msg.ctx, event_msg.event, event_msg.data);
593 #endif
594 } else {
595 wpa_supplicant_event(event_msg.ctx, event_msg.event, event_msg.data);
596 }
597
598 if (event_msg.data) {
599 union wpa_event_data *data = event_msg.data;
600
601 /* Free up deep copied data */
602 if (event_msg.event == EVENT_AUTH) {
603 os_free((char *)data->auth.ies);
604 } else if (event_msg.event == EVENT_RX_MGMT) {
605 os_free((char *)data->rx_mgmt.frame);
606 } else if (event_msg.event == EVENT_TX_STATUS) {
607 os_free((char *)data->tx_status.data);
608 } else if (event_msg.event == EVENT_ASSOC) {
609 os_free((char *)data->assoc_info.addr);
610 os_free((char *)data->assoc_info.req_ies);
611 os_free((char *)data->assoc_info.resp_ies);
612 os_free((char *)data->assoc_info.resp_frame);
613 } else if (event_msg.event == EVENT_ASSOC_REJECT) {
614 os_free((char *)data->assoc_reject.bssid);
615 os_free((char *)data->assoc_reject.resp_ies);
616 } else if (event_msg.event == EVENT_DEAUTH) {
617 os_free((char *)data->deauth_info.addr);
618 os_free((char *)data->deauth_info.ie);
619 } else if (event_msg.event == EVENT_DISASSOC) {
620 os_free((char *)data->disassoc_info.addr);
621 os_free((char *)data->disassoc_info.ie);
622 } else if (event_msg.event == EVENT_UNPROT_DEAUTH) {
623 os_free((char *)data->unprot_deauth.sa);
624 os_free((char *)data->unprot_deauth.da);
625 } else if (event_msg.event == EVENT_UNPROT_DISASSOC) {
626 os_free((char *)data->unprot_disassoc.sa);
627 os_free((char *)data->unprot_disassoc.da);
628 }
629
630 os_free(event_msg.data);
631 }
632
633 out:
634 os_free(msg->data);
635 os_free(msg);
636
637 } while (!k_fifo_is_empty(&ctx->fifo));
638 }
639
register_supplicant_event_socket(struct supplicant_context * ctx)640 static int register_supplicant_event_socket(struct supplicant_context *ctx)
641 {
642 int ret;
643
644 ret = zvfs_eventfd(0, ZVFS_EFD_NONBLOCK);
645 if (ret < 0) {
646 ret = -errno;
647 LOG_ERR("Failed to initialize socket (%d)", ret);
648 return ret;
649 }
650
651 ctx->sock = ret;
652
653 k_fifo_init(&ctx->fifo);
654
655 eloop_register_read_sock(ctx->sock, event_socket_handler, NULL, ctx);
656
657 return 0;
658 }
659
handler(void)660 static void handler(void)
661 {
662 struct supplicant_context *ctx;
663 struct wpa_params params;
664 struct k_work_queue_config iface_wq_cfg = {
665 .name = "hostap_iface_wq",
666 };
667
668 #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP)
669 /* Needed for crypto operation as default is no-op and fails */
670 mbedtls_platform_set_calloc_free(calloc, free);
671 #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */
672
673 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA
674 supp_psa_crypto_init();
675 #endif
676
677 ctx = get_default_context();
678
679 k_work_queue_init(&ctx->iface_wq);
680 k_work_queue_start(&ctx->iface_wq, iface_wq_stack,
681 K_THREAD_STACK_SIZEOF(iface_wq_stack),
682 CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_PRIO,
683 &iface_wq_cfg);
684
685 k_work_init(&ctx->iface_work, iface_work_handler);
686
687 memset(¶ms, 0, sizeof(params));
688 params.wpa_debug_level = CONFIG_WIFI_NM_WPA_SUPPLICANT_DEBUG_LEVEL;
689
690 ctx->supplicant = wpa_supplicant_init(¶ms);
691 if (ctx->supplicant == NULL) {
692 LOG_ERR("Failed to initialize %s", "wpa_supplicant");
693 goto err;
694 }
695
696 LOG_INF("%s initialized", "wpa_supplicant");
697
698 if (fst_global_init()) {
699 LOG_ERR("Failed to initialize %s", "FST");
700 goto out;
701 }
702
703 #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
704 if (!fst_global_add_ctrl(fst_ctrl_cli)) {
705 LOG_WRN("Failed to add CLI FST ctrl");
706 }
707 #endif
708 zephyr_global_wpa_ctrl_init();
709
710 register_supplicant_event_socket(ctx);
711
712 submit_iface_work(ctx, NULL, setup_interface_monitoring);
713
714 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
715 zephyr_hostapd_init(&ctx->hostapd);
716 #endif
717 wpa_msg_register_ifname_cb(zephyr_hostap_msg_ifname_cb);
718
719 (void)wpa_supplicant_run(ctx->supplicant);
720
721 supplicant_generate_state_event(ctx->if_name, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0);
722
723 eloop_unregister_read_sock(ctx->sock);
724
725 zephyr_global_wpa_ctrl_deinit();
726
727 fst_global_deinit();
728
729 out:
730 wpa_supplicant_deinit(ctx->supplicant);
731
732 close(ctx->sock);
733
734 err:
735 os_free(params.pid_file);
736 }
737
init(void)738 static int init(void)
739 {
740 k_tid_t id;
741
742 /* We create a thread that handles all supplicant connections */
743 id = k_thread_create(&tid, supplicant_thread_stack,
744 K_THREAD_STACK_SIZEOF(supplicant_thread_stack),
745 (k_thread_entry_t)handler, NULL, NULL, NULL,
746 CONFIG_WIFI_NM_WPA_SUPPLICANT_PRIO, 0, K_NO_WAIT);
747
748 k_thread_name_set(id, "hostap_handler");
749
750 return 0;
751 }
752
753 SYS_INIT(init, APPLICATION, 0);
754
eapol_recv(struct net_if * iface,uint16_t ptype,struct net_pkt * pkt)755 static enum net_verdict eapol_recv(struct net_if *iface, uint16_t ptype,
756 struct net_pkt *pkt)
757 {
758 ARG_UNUSED(iface);
759 ARG_UNUSED(ptype);
760
761 net_pkt_set_family(pkt, AF_UNSPEC);
762
763 return NET_CONTINUE;
764 }
765
766 ETH_NET_L3_REGISTER(EAPOL, NET_ETH_PTYPE_EAPOL, eapol_recv);
767