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