1 /**
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 * Copyright 2024 NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 #include <stdarg.h>
8
9 #include <zephyr/logging/log.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/net/wifi_mgmt.h>
12
13 #include "includes.h"
14 #include "common.h"
15 #include "common/defs.h"
16 #include "common/ieee802_11_defs.h"
17 #include "common/ieee802_11_common.h"
18 #include "wpa_supplicant/config.h"
19 #include "wpa_supplicant_i.h"
20 #include "driver_i.h"
21
22 #include "supp_main.h"
23 #include "supp_api.h"
24 #include "wpa_cli_zephyr.h"
25 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
26 #include "hostapd.h"
27 #include "hostapd_cli_zephyr.h"
28 #include "ap_drv_ops.h"
29 #endif
30 #include "supp_events.h"
31 #include "wpa_supplicant/bss.h"
32
33 extern struct k_sem wpa_supplicant_ready_sem;
34 extern struct wpa_global *global;
35
36 /* save the last wifi connection parameters */
37 static struct wifi_connect_req_params last_wifi_conn_params;
38
39 enum requested_ops {
40 CONNECT = 0,
41 DISCONNECT,
42 WPS_PBC,
43 WPS_PIN,
44 };
45
46 enum status_thread_state {
47 STATUS_THREAD_STOPPED = 0,
48 STATUS_THREAD_RUNNING,
49 };
50
51 #define OP_STATUS_POLLING_INTERVAL 1
52
53 #define CONNECTION_SUCCESS 0
54 #define CONNECTION_FAILURE 1
55 #define CONNECTION_TERMINATED 2
56
57 #define DISCONNECT_TIMEOUT_MS 5000
58
59 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
60 static struct wifi_enterprise_creds_params enterprise_creds;
61 #endif
62
63 K_MUTEX_DEFINE(wpa_supplicant_mutex);
64
65 extern struct k_work_q *get_workq(void);
66
67 struct wpa_supp_api_ctrl {
68 const struct device *dev;
69 enum requested_ops requested_op;
70 enum status_thread_state status_thread_state;
71 int connection_timeout; /* in seconds */
72 struct k_work_sync sync;
73 bool terminate;
74 };
75
76 static struct wpa_supp_api_ctrl wpas_api_ctrl;
77
78 static void supp_shell_connect_status(struct k_work *work);
79
80 static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work,
81 supp_shell_connect_status);
82
83 #define wpa_cli_cmd_v(cmd, ...) ({ \
84 bool status; \
85 \
86 if (zephyr_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
87 wpa_printf(MSG_ERROR, \
88 "Failed to execute wpa_cli command: %s", \
89 cmd); \
90 status = false; \
91 } else { \
92 status = true; \
93 } \
94 \
95 status; \
96 })
97
get_wpa_s_handle(const struct device * dev)98 static struct wpa_supplicant *get_wpa_s_handle(const struct device *dev)
99 {
100 struct net_if *iface = net_if_lookup_by_dev(dev);
101 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
102 struct wpa_supplicant *wpa_s;
103 int ret;
104
105 if (!iface) {
106 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
107 return NULL;
108 }
109
110 ret = net_if_get_name(iface, if_name, sizeof(if_name));
111 if (!ret) {
112 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
113 return NULL;
114 }
115
116 wpa_s = zephyr_get_handle_by_ifname(if_name);
117 if (!wpa_s) {
118 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
119 return NULL;
120 }
121
122 return wpa_s;
123 }
124
125 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
126 #define hostapd_cli_cmd_v(cmd, ...) ({ \
127 bool status; \
128 \
129 if (zephyr_hostapd_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \
130 wpa_printf(MSG_ERROR, \
131 "Failed to execute wpa_cli command: %s", \
132 cmd); \
133 status = false; \
134 } else { \
135 status = true; \
136 } \
137 \
138 status; \
139 })
140
get_hostapd_handle(const struct device * dev)141 static inline struct hostapd_iface *get_hostapd_handle(const struct device *dev)
142 {
143 struct net_if *iface = net_if_lookup_by_dev(dev);
144 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
145 struct hostapd_iface *hapd;
146 int ret;
147
148 if (!iface) {
149 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
150 return NULL;
151 }
152
153 ret = net_if_get_name(iface, if_name, sizeof(if_name));
154 if (!ret) {
155 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
156 return NULL;
157 }
158
159 hapd = zephyr_get_hapd_handle_by_ifname(if_name);
160 if (!hapd) {
161 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
162 return NULL;
163 }
164
165 return hapd;
166 }
167 #endif
168
169 #define WPA_SUPP_STATE_POLLING_MS 10
wait_for_disconnect_complete(const struct device * dev)170 static int wait_for_disconnect_complete(const struct device *dev)
171 {
172 int ret = 0;
173 int attempts = 0;
174 struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
175 unsigned int max_attempts = DISCONNECT_TIMEOUT_MS / WPA_SUPP_STATE_POLLING_MS;
176
177 if (!wpa_s) {
178 ret = -ENODEV;
179 wpa_printf(MSG_ERROR, "Failed to get wpa_s handle");
180 goto out;
181 }
182
183 while (wpa_s->wpa_state != WPA_DISCONNECTED) {
184 if (attempts++ > max_attempts) {
185 ret = -ETIMEDOUT;
186 wpa_printf(MSG_WARNING, "Failed to disconnect from network");
187 break;
188 }
189
190 k_sleep(K_MSEC(WPA_SUPP_STATE_POLLING_MS));
191 }
192 out:
193 return ret;
194 }
195
supp_shell_connect_status(struct k_work * work)196 static void supp_shell_connect_status(struct k_work *work)
197 {
198 static int seconds_counter;
199 int status = CONNECTION_SUCCESS;
200 int conn_result = CONNECTION_FAILURE;
201 struct wpa_supplicant *wpa_s;
202 struct wpa_supp_api_ctrl *ctrl = &wpas_api_ctrl;
203
204 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
205
206 if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) {
207 status = CONNECTION_TERMINATED;
208 goto out;
209 }
210
211 wpa_s = get_wpa_s_handle(ctrl->dev);
212 if (!wpa_s) {
213 status = CONNECTION_FAILURE;
214 goto out;
215 }
216
217 if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) {
218 if (ctrl->connection_timeout > 0 &&
219 seconds_counter++ > ctrl->connection_timeout) {
220 if (!wpa_cli_cmd_v("disconnect")) {
221 goto out;
222 }
223
224 conn_result = -ETIMEDOUT;
225 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
226 NET_EVENT_WIFI_CMD_CONNECT_RESULT,
227 (void *)&conn_result, sizeof(int));
228 status = CONNECTION_FAILURE;
229 goto out;
230 }
231
232 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work,
233 K_SECONDS(OP_STATUS_POLLING_INTERVAL));
234 ctrl->status_thread_state = STATUS_THREAD_RUNNING;
235 k_mutex_unlock(&wpa_supplicant_mutex);
236 return;
237 }
238 out:
239 seconds_counter = 0;
240
241 ctrl->status_thread_state = STATUS_THREAD_STOPPED;
242 k_mutex_unlock(&wpa_supplicant_mutex);
243 }
244
get_mode_by_band(struct wpa_supplicant * wpa_s,uint8_t band)245 static struct hostapd_hw_modes *get_mode_by_band(struct wpa_supplicant *wpa_s, uint8_t band)
246 {
247 enum hostapd_hw_mode hw_mode;
248 bool is_6ghz = (band == WIFI_FREQ_BAND_6_GHZ) ? true : false;
249
250 if (band == WIFI_FREQ_BAND_2_4_GHZ) {
251 hw_mode = HOSTAPD_MODE_IEEE80211G;
252 } else if ((band == WIFI_FREQ_BAND_5_GHZ) ||
253 (band == WIFI_FREQ_BAND_6_GHZ)) {
254 hw_mode = HOSTAPD_MODE_IEEE80211A;
255 } else {
256 return NULL;
257 }
258
259 return get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, is_6ghz);
260 }
261
wpa_supp_supported_channels(struct wpa_supplicant * wpa_s,uint8_t band,char ** chan_list)262 static int wpa_supp_supported_channels(struct wpa_supplicant *wpa_s, uint8_t band, char **chan_list)
263 {
264 struct hostapd_hw_modes *mode = NULL;
265 int i;
266 int offset, retval;
267 int size;
268 char *_chan_list;
269
270 mode = get_mode_by_band(wpa_s, band);
271 if (!mode) {
272 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
273 return -EINVAL;
274 }
275
276 size = ((mode->num_channels) * CHAN_NUM_LEN) + 1;
277 _chan_list = os_malloc(size);
278 if (!_chan_list) {
279 wpa_printf(MSG_ERROR, "Mem alloc failed for channel list");
280 return -ENOMEM;
281 }
282
283 retval = 0;
284 offset = 0;
285 for (i = 0; i < mode->num_channels; i++) {
286 retval = snprintf(_chan_list + offset, CHAN_NUM_LEN, " %d",
287 mode->channels[i].freq);
288 offset += retval;
289 }
290 *chan_list = _chan_list;
291
292 return 0;
293 }
294
wpa_supp_band_chan_compat(struct wpa_supplicant * wpa_s,uint8_t band,uint8_t channel)295 static int wpa_supp_band_chan_compat(struct wpa_supplicant *wpa_s, uint8_t band, uint8_t channel)
296 {
297 struct hostapd_hw_modes *mode = NULL;
298 int i;
299
300 mode = get_mode_by_band(wpa_s, band);
301 if (!mode) {
302 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
303 return -EINVAL;
304 }
305
306 for (i = 0; i < mode->num_channels; i++) {
307 if (mode->channels[i].chan == channel) {
308 return mode->channels[i].freq;
309 }
310 }
311
312 wpa_printf(MSG_ERROR, "Channel %d not supported for band %d", channel, band);
313
314 return -EINVAL;
315 }
316
wpa_supp_restart_status_work(void)317 static inline void wpa_supp_restart_status_work(void)
318 {
319 /* Terminate synchronously */
320 wpas_api_ctrl.terminate = 1;
321 k_work_flush_delayable(&wpa_supp_status_work, &wpas_api_ctrl.sync);
322 wpas_api_ctrl.terminate = 0;
323
324 /* Start afresh */
325 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work, K_MSEC(10));
326 }
327
chan_to_freq(int chan)328 static inline int chan_to_freq(int chan)
329 {
330 /* We use global channel list here and also use the widest
331 * op_class for 5GHz channels as there is no user input
332 * for these (yet).
333 */
334 int freq = -1;
335 int op_classes[] = {81, 82, 128};
336 int op_classes_size = ARRAY_SIZE(op_classes);
337
338 for (int i = 0; i < op_classes_size; i++) {
339 freq = ieee80211_chan_to_freq(NULL, op_classes[i], chan);
340 if (freq > 0) {
341 break;
342 }
343 }
344
345 if (freq <= 0) {
346 wpa_printf(MSG_ERROR, "Invalid channel %d", chan);
347 return -1;
348 }
349
350 return freq;
351 }
352
wpas_band_to_zephyr(enum wpa_radio_work_band band)353 static inline enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band)
354 {
355 switch (band) {
356 case BAND_2_4_GHZ:
357 return WIFI_FREQ_BAND_2_4_GHZ;
358 case BAND_5_GHZ:
359 return WIFI_FREQ_BAND_5_GHZ;
360 default:
361 return WIFI_FREQ_BAND_UNKNOWN;
362 }
363 }
364
wpas_key_mgmt_to_zephyr(int key_mgmt,int proto,int pwe)365 static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(int key_mgmt, int proto, int pwe)
366 {
367 switch (key_mgmt) {
368 case WPA_KEY_MGMT_IEEE8021X:
369 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
370 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
371 return WIFI_SECURITY_TYPE_EAP_TLS;
372 case WPA_KEY_MGMT_NONE:
373 return WIFI_SECURITY_TYPE_NONE;
374 case WPA_KEY_MGMT_PSK:
375 if (proto == WPA_PROTO_RSN) {
376 return WIFI_SECURITY_TYPE_PSK;
377 } else {
378 return WIFI_SECURITY_TYPE_WPA_PSK;
379 }
380 case WPA_KEY_MGMT_PSK_SHA256:
381 return WIFI_SECURITY_TYPE_PSK_SHA256;
382 case WPA_KEY_MGMT_SAE:
383 if (pwe == 1) {
384 return WIFI_SECURITY_TYPE_SAE_H2E;
385 } else if (pwe == 2) {
386 return WIFI_SECURITY_TYPE_SAE_AUTO;
387 } else {
388 return WIFI_SECURITY_TYPE_SAE_HNP;
389 }
390 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK:
391 return WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL;
392 case WPA_KEY_MGMT_FT_PSK:
393 return WIFI_SECURITY_TYPE_FT_PSK;
394 case WPA_KEY_MGMT_FT_SAE:
395 return WIFI_SECURITY_TYPE_FT_SAE;
396 case WPA_KEY_MGMT_FT_IEEE8021X:
397 return WIFI_SECURITY_TYPE_FT_EAP;
398 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
399 return WIFI_SECURITY_TYPE_FT_EAP_SHA384;
400 default:
401 return WIFI_SECURITY_TYPE_UNKNOWN;
402 }
403 }
404
405 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_config_process_blob(struct wpa_config * config,char * name,uint8_t * data,uint32_t data_len)406 static int wpas_config_process_blob(struct wpa_config *config, char *name, uint8_t *data,
407 uint32_t data_len)
408 {
409 struct wpa_config_blob *blob;
410
411 if (!data || !data_len) {
412 return -1;
413 }
414
415 blob = os_zalloc(sizeof(*blob));
416 if (blob == NULL) {
417 return -1;
418 }
419
420 blob->data = os_zalloc(data_len);
421 if (blob->data == NULL) {
422 os_free(blob);
423 return -1;
424 }
425
426 blob->name = os_strdup(name);
427
428 if (blob->name == NULL) {
429 wpa_config_free_blob(blob);
430 return -1;
431 }
432
433 os_memcpy(blob->data, data, data_len);
434 blob->len = data_len;
435
436 wpa_config_set_blob(config, blob);
437
438 return 0;
439 }
440 #endif
441
442 #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
443 defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
supplicant_add_enterprise_creds(const struct device * dev,struct wifi_enterprise_creds_params * creds)444 int supplicant_add_enterprise_creds(const struct device *dev,
445 struct wifi_enterprise_creds_params *creds)
446 {
447 int ret = 0;
448
449 if (!creds) {
450 ret = -1;
451 wpa_printf(MSG_ERROR, "enterprise creds is NULL");
452 goto out;
453 }
454
455 memcpy((void *)&enterprise_creds, (void *)creds,
456 sizeof(struct wifi_enterprise_creds_params));
457
458 out:
459 return ret;
460 }
461
462 static const struct wifi_cipher_desc ciphers[] = {
463 {WPA_CAPA_ENC_GCMP_256, "GCMP-256"},
464 {WPA_CAPA_ENC_CCMP, "CCMP"},
465 {WPA_CAPA_ENC_GCMP, "GCMP"},
466 };
467
468 static const struct wifi_cipher_desc ciphers_group_mgmt[] = {
469 {WPA_CAPA_ENC_BIP, "AES-128-CMAC"},
470 {WPA_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128"},
471 {WPA_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256"},
472 };
473
474 static struct wifi_eap_config eap_config[] = {
475 {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
476 {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP",
477 "auth=MSCHAPV2"},
478 {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP",
479 "auth=GTC"},
480 {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS",
481 "auth=MSCHAPV2"},
482 {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP",
483 "auth=TLS"},
484 {WIFI_SECURITY_TYPE_EAP_TLS_SHA256, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
485 };
486
process_cipher_config(struct wifi_connect_req_params * params,struct wifi_eap_cipher_config * cipher_config)487 int process_cipher_config(struct wifi_connect_req_params *params,
488 struct wifi_eap_cipher_config *cipher_config)
489 {
490 unsigned int cipher_capa;
491 unsigned int gropu_mgmt_cipher_capa;
492 unsigned int index;
493
494 if (params->suiteb_type == WIFI_SUITEB) {
495 cipher_capa = WPA_CAPA_ENC_GCMP;
496 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_128;
497 cipher_config->key_mgmt = "WPA-EAP-SUITE-B";
498 cipher_config->openssl_ciphers = "SUITEB128";
499 cipher_config->tls_flags = "[SUITEB]";
500 } else if (params->suiteb_type == WIFI_SUITEB_192) {
501 cipher_capa = WPA_CAPA_ENC_GCMP_256;
502 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_256;
503 if (params->ft_used) {
504 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384";
505 } else {
506 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192";
507 }
508 cipher_config->openssl_ciphers = "SUITEB192";
509 cipher_config->tls_flags = "[SUITEB]";
510 } else {
511 cipher_capa = WPA_CAPA_ENC_CCMP;
512 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
513 if (params->ft_used) {
514 cipher_config->key_mgmt = "WPA-EAP FT-EAP";
515 } else {
516 cipher_config->key_mgmt = "WPA-EAP";
517 }
518 }
519
520 if (params->security == WIFI_SECURITY_TYPE_EAP_TLS_SHA256) {
521 cipher_config->key_mgmt = "WPA-EAP-SHA256";
522 }
523
524 for (index = 0; index < ARRAY_SIZE(ciphers); index++) {
525 if (cipher_capa == ciphers[index].capa) {
526 cipher_config->group_cipher = ciphers[index].name;
527 cipher_config->pairwise_cipher = ciphers[index].name;
528 break;
529 }
530 }
531
532 if (index == ARRAY_SIZE(ciphers)) {
533 wpa_printf(MSG_ERROR, "Get ciphers error");
534 goto out;
535 }
536
537 for (index = 0; index < ARRAY_SIZE(ciphers_group_mgmt); index++) {
538 if (gropu_mgmt_cipher_capa == ciphers_group_mgmt[index].capa) {
539 cipher_config->group_mgmt_cipher = ciphers_group_mgmt[index].name;
540 break;
541 }
542 }
543
544 if (index == ARRAY_SIZE(ciphers_group_mgmt)) {
545 wpa_printf(MSG_ERROR, "Get group mgmt ciphers error");
546 goto out;
547 }
548
549 return 0;
550 out:
551 return -EINVAL;
552 }
553
is_eap_valid_security(int security)554 static int is_eap_valid_security(int security)
555 {
556 return (security == WIFI_SECURITY_TYPE_EAP_TLS ||
557 security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
558 security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
559 security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
560 security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS ||
561 security == WIFI_SECURITY_TYPE_EAP_TLS_SHA256);
562 }
563 #endif
564
565 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
hapd_process_cert_data(struct hostapd_bss_config * conf,char * type,uint8_t * data,uint32_t data_len)566 static int hapd_process_cert_data(struct hostapd_bss_config *conf,
567 char *type, uint8_t *data, uint32_t data_len)
568 {
569 if (os_strcmp(type, "ca_cert_blob") == 0) {
570 conf->ca_cert_blob = data;
571 conf->ca_cert_blob_len = data_len;
572 } else if (os_strcmp(type, "server_cert_blob") == 0) {
573 conf->server_cert_blob = data;
574 conf->server_cert_blob_len = data_len;
575 } else if (os_strcmp(type, "private_key_blob") == 0) {
576 conf->private_key_blob = data;
577 conf->private_key_blob_len = data_len;
578 } else if (os_strcmp(type, "dh_blob") == 0) {
579 conf->dh_blob = data;
580 conf->dh_blob_len = data_len;
581 } else {
582 wpa_printf(MSG_ERROR, "input type error");
583 return -ENOTSUP;
584 }
585
586 return 0;
587 }
588
hapd_get_eap_config(struct wifi_connect_req_params * params,struct wifi_eap_config * eap_cfg)589 static int hapd_get_eap_config(struct wifi_connect_req_params *params,
590 struct wifi_eap_config *eap_cfg)
591 {
592 unsigned int index = 0;
593
594 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
595 if (params->security == eap_config[index].type) {
596 memcpy(eap_cfg, &eap_config[index], sizeof(struct wifi_eap_config));
597 break;
598 }
599 }
600
601 if (index == ARRAY_SIZE(eap_config)) {
602 wpa_printf(MSG_ERROR, "Get eap method type with security type: %d",
603 params->security);
604 return -ENOTSUP;
605 }
606
607 return 0;
608 }
609
hostapd_process_eap_user_phase1(struct wifi_connect_req_params * params,struct hostapd_eap_user ** pnew_user)610 static struct hostapd_eap_user *hostapd_process_eap_user_phase1(
611 struct wifi_connect_req_params *params, struct hostapd_eap_user **pnew_user)
612 {
613 struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
614 struct wifi_eap_config eap_cfg;
615
616 user = os_zalloc(sizeof(*user));
617 if (user == NULL) {
618 wpa_printf(MSG_ERROR, "EAP user allocation failed");
619 goto failed;
620 }
621
622 user->force_version = -1;
623 if (params->eap_ver >= 0) {
624 user->force_version = params->eap_ver;
625 }
626
627 if (hapd_get_eap_config(params, &eap_cfg)) {
628 goto failed;
629 }
630
631 user->methods[0].method = eap_cfg.eap_type_phase1;
632 user->methods[0].vendor = 0;
633
634 if (tail == NULL) {
635 tail = new_user = user;
636 } else {
637 tail->next = user;
638 tail = user;
639 }
640
641 *pnew_user = new_user;
642
643 return tail;
644
645 failed:
646 if (user) {
647 hostapd_config_free_eap_user(user);
648 }
649
650 return NULL;
651 }
652
hostapd_process_eap_user(struct wifi_connect_req_params * params,struct hostapd_bss_config * conf)653 static int hostapd_process_eap_user(struct wifi_connect_req_params *params,
654 struct hostapd_bss_config *conf)
655 {
656 struct hostapd_eap_user *user = NULL, *tail = NULL, *user_list = NULL;
657 int i, nusers = params->nusers;
658 const char *identity, *password;
659 struct wifi_eap_config eap_cfg;
660 int ret = 0;
661
662 if (hapd_get_eap_config(params, &eap_cfg)) {
663 goto failed;
664 }
665
666 if (eap_cfg.phase2 != NULL) {
667 tail = hostapd_process_eap_user_phase1(params, &user_list);
668 }
669
670 if (eap_cfg.phase2 != NULL && !nusers) {
671 wpa_printf(MSG_ERROR, "EAP users not found.");
672 goto failed;
673 }
674
675 for (i = 0; i < nusers; i++) {
676 user = os_zalloc(sizeof(*user));
677 if (user == NULL) {
678 wpa_printf(MSG_ERROR, "EAP user allocation failed");
679 goto failed;
680 }
681
682 user->force_version = -1;
683 if (params->eap_ver >= 0) {
684 user->force_version = params->eap_ver;
685 }
686
687 identity = params->identities[i];
688 password = params->passwords[i];
689
690 user->identity = os_memdup(identity, os_strlen(identity));
691 if (user->identity == NULL) {
692 wpa_printf(MSG_ERROR,
693 "Failed to allocate "
694 "memory for EAP identity");
695 goto failed;
696 }
697 user->identity_len = os_strlen(identity);
698
699 user->methods[0].method = eap_cfg.eap_type_phase1;
700 user->methods[0].vendor = 0;
701
702 if (eap_cfg.phase2 != NULL) {
703 user->methods[0].method = eap_cfg.eap_type_phase2;
704 user->password = os_memdup(password, os_strlen(password));
705 if (user->password == NULL) {
706 wpa_printf(MSG_ERROR,
707 "Failed to allocate "
708 "memory for EAP password");
709 goto failed;
710 }
711 user->password_len = os_strlen(password);
712
713 user->phase2 = 1;
714 }
715
716 if (params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) {
717 user->ttls_auth |= 0x1E;
718 }
719
720 if (tail == NULL) {
721 tail = user_list = user;
722 } else {
723 tail->next = user;
724 tail = user;
725 }
726
727 continue;
728
729 failed:
730 if (user) {
731 hostapd_config_free_eap_user(user);
732 }
733
734 ret = -1;
735 break;
736 }
737
738 if (ret == 0) {
739 hostapd_config_free_eap_users(conf->eap_user);
740 conf->eap_user = user_list;
741 } else {
742 hostapd_config_free_eap_users(user_list);
743 }
744
745 return ret;
746 }
747
hapd_process_enterprise_config(struct hostapd_iface * iface,struct wifi_connect_req_params * params)748 int hapd_process_enterprise_config(struct hostapd_iface *iface,
749 struct wifi_connect_req_params *params)
750 {
751 struct wifi_eap_cipher_config cipher_config = {
752 NULL, "DEFAULT:!EXP:!LOW", "CCMP", "CCMP", "AES-128-CMAC", NULL};
753 int ret = 0;
754
755 if (process_cipher_config(params, &cipher_config)) {
756 goto out;
757 }
758
759 if (!hostapd_cli_cmd_v("set wpa %d", WPA_PROTO_RSN)) {
760 goto out;
761 }
762
763 if (!hostapd_cli_cmd_v("set wpa_key_mgmt %s", cipher_config.key_mgmt)) {
764 goto out;
765 }
766
767 if (!hostapd_cli_cmd_v("set rsn_pairwise %s", cipher_config.pairwise_cipher)) {
768 goto out;
769 }
770
771 if (!hostapd_cli_cmd_v("set wpa_pairwise %s", cipher_config.pairwise_cipher)) {
772 goto out;
773 }
774
775 if (!hostapd_cli_cmd_v("set group_cipher %s", cipher_config.group_cipher)) {
776 goto out;
777 }
778
779 if (!hostapd_cli_cmd_v("set group_mgmt_cipher %s", cipher_config.group_mgmt_cipher)) {
780 goto out;
781 }
782
783 if (cipher_config.tls_flags != NULL) {
784 if (!hostapd_cli_cmd_v("set tls_flags %s", cipher_config.tls_flags)) {
785 goto out;
786 }
787 }
788
789 if (!hostapd_cli_cmd_v("set ieee8021x %d", 1)) {
790 goto out;
791 }
792
793 if (!hostapd_cli_cmd_v("set eapol_version %d", 2)) {
794 goto out;
795 }
796
797 if (!hostapd_cli_cmd_v("set eap_server %d", 1)) {
798 goto out;
799 }
800
801 if (hapd_process_cert_data(iface->bss[0]->conf, "ca_cert_blob",
802 enterprise_creds.ca_cert, enterprise_creds.ca_cert_len)) {
803 goto out;
804 }
805
806 if (hapd_process_cert_data(iface->bss[0]->conf, "server_cert_blob",
807 enterprise_creds.server_cert, enterprise_creds.server_cert_len)) {
808 goto out;
809 }
810
811 if (hapd_process_cert_data(iface->bss[0]->conf, "private_key_blob",
812 enterprise_creds.server_key, enterprise_creds.server_key_len)) {
813 goto out;
814 }
815
816 if (hapd_process_cert_data(iface->bss[0]->conf, "dh_blob",
817 enterprise_creds.dh_param, enterprise_creds.dh_param_len)) {
818 goto out;
819 }
820
821 if (!hostapd_cli_cmd_v("set private_key_passwd %s", params->key_passwd)) {
822 goto out;
823 }
824
825 if (hostapd_process_eap_user(params, iface->bss[0]->conf)) {
826 goto out;
827 }
828
829 return ret;
830 out:
831 return -1;
832 }
833 #endif
834
835 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_remove_certs(struct wpa_supplicant * wpa_s)836 static void wpas_remove_certs(struct wpa_supplicant *wpa_s)
837 {
838 wpa_config_remove_blob(wpa_s->conf, "ca_cert");
839 wpa_config_remove_blob(wpa_s->conf, "client_cert");
840 wpa_config_remove_blob(wpa_s->conf, "private_key");
841 wpa_config_remove_blob(wpa_s->conf, "ca_cert2");
842 wpa_config_remove_blob(wpa_s->conf, "client_cert2");
843 wpa_config_remove_blob(wpa_s->conf, "private_key2");
844 }
845 #endif
846
wpas_add_and_config_network(struct wpa_supplicant * wpa_s,struct wifi_connect_req_params * params,bool mode_ap)847 static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
848 struct wifi_connect_req_params *params,
849 bool mode_ap)
850 {
851 struct add_network_resp resp = {0};
852 char *chan_list = NULL;
853 struct net_eth_addr mac = {0};
854 int ret = 0;
855 uint8_t ssid_null_terminated[WIFI_SSID_MAX_LEN + 1];
856 uint8_t psk_null_terminated[WIFI_PSK_MAX_LEN + 1];
857 uint8_t sae_null_terminated[WIFI_SAE_PSWD_MAX_LEN + 1];
858 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
859 struct wifi_eap_cipher_config cipher_config = {NULL, "DEFAULT:!EXP:!LOW", "CCMP",
860 "CCMP", "AES-128-CMAC", NULL};
861 char *method = NULL;
862 char phase1[128] = {0};
863 char *phase2 = NULL;
864 unsigned int index;
865
866 wpas_remove_certs(wpa_s);
867 #endif
868
869 if (!wpa_cli_cmd_v("remove_network all")) {
870 goto out;
871 }
872
873 ret = z_wpa_ctrl_add_network(&resp);
874 if (ret) {
875 wpa_printf(MSG_ERROR, "Failed to add network");
876 goto out;
877 }
878
879 wpa_printf(MSG_DEBUG, "NET added: %d", resp.network_id);
880
881 if (mode_ap) {
882 if (!wpa_cli_cmd_v("set_network %d mode 2", resp.network_id)) {
883 goto out;
884 }
885 }
886
887 if (params->ssid_length > WIFI_SSID_MAX_LEN) {
888 wpa_printf(MSG_ERROR, "SSID too long (max %d characters)", WIFI_SSID_MAX_LEN);
889 goto out;
890 }
891
892 strncpy(ssid_null_terminated, params->ssid, WIFI_SSID_MAX_LEN);
893 ssid_null_terminated[params->ssid_length] = '\0';
894
895 if (!wpa_cli_cmd_v("set_network %d ssid \"%s\"",
896 resp.network_id, ssid_null_terminated)) {
897 goto out;
898 }
899
900 if (!wpa_cli_cmd_v("set_network %d scan_ssid 1", resp.network_id)) {
901 goto out;
902 }
903
904 if (!wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id)) {
905 goto out;
906 }
907
908 if (!wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id)) {
909 goto out;
910 }
911
912 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
913 ret = wpa_supp_supported_channels(wpa_s, params->band, &chan_list);
914 if (ret < 0) {
915 goto rem_net;
916 }
917
918 if (chan_list) {
919 if (!wpa_cli_cmd_v("set_network %d scan_freq%s", resp.network_id,
920 chan_list)) {
921 os_free(chan_list);
922 goto out;
923 }
924
925 os_free(chan_list);
926 }
927 }
928
929 if (params->security != WIFI_SECURITY_TYPE_NONE) {
930 if (params->psk) {
931 if ((params->psk_length < WIFI_PSK_MIN_LEN) ||
932 (params->psk_length > WIFI_PSK_MAX_LEN)) {
933 wpa_printf(MSG_ERROR,
934 "Passphrase should be in range (%d-%d) characters",
935 WIFI_PSK_MIN_LEN, WIFI_PSK_MAX_LEN);
936 goto out;
937 }
938 strncpy(psk_null_terminated, params->psk, WIFI_PSK_MAX_LEN);
939 psk_null_terminated[params->psk_length] = '\0';
940 }
941
942 /* SAP - only open and WPA2-PSK are supported for now */
943 if (mode_ap && params->security != WIFI_SECURITY_TYPE_PSK) {
944 ret = -1;
945 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
946 params->security);
947 goto rem_net;
948 }
949
950 /* Except for WPA-PSK, rest all are under WPA2 */
951 if (params->security != WIFI_SECURITY_TYPE_WPA_PSK) {
952 if (!wpa_cli_cmd_v("set_network %d proto RSN",
953 resp.network_id)) {
954 goto out;
955 }
956 }
957
958 if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
959 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
960 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
961 if (params->sae_password) {
962 if ((params->sae_password_length < WIFI_PSK_MIN_LEN) ||
963 (params->sae_password_length > WIFI_SAE_PSWD_MAX_LEN)) {
964 wpa_printf(MSG_ERROR,
965 "Passphrase should be in range (%d-%d) characters",
966 WIFI_PSK_MIN_LEN, WIFI_SAE_PSWD_MAX_LEN);
967 goto out;
968 }
969 strncpy(sae_null_terminated, params->sae_password,
970 WIFI_SAE_PSWD_MAX_LEN);
971 sae_null_terminated[params->sae_password_length] = '\0';
972 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
973 resp.network_id, sae_null_terminated)) {
974 goto out;
975 }
976 } else {
977 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
978 resp.network_id, psk_null_terminated)) {
979 goto out;
980 }
981 }
982
983 if (params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
984 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
985 if (!wpa_cli_cmd_v("set sae_pwe %d",
986 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
987 ? 1
988 : 2)) {
989 goto out;
990 }
991 }
992
993 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE%s", resp.network_id,
994 params->ft_used ? " FT-SAE" : "")) {
995 goto out;
996 }
997 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
998 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
999 resp.network_id, psk_null_terminated)) {
1000 goto out;
1001 }
1002
1003 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256",
1004 resp.network_id)) {
1005 goto out;
1006 }
1007 } else if (params->security == WIFI_SECURITY_TYPE_PSK ||
1008 params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
1009 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
1010 resp.network_id, psk_null_terminated)) {
1011 goto out;
1012 }
1013
1014 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK%s",
1015 resp.network_id, params->ft_used ? " FT-PSK" : "")) {
1016 goto out;
1017 }
1018
1019 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
1020 if (!wpa_cli_cmd_v("set_network %d proto WPA",
1021 resp.network_id)) {
1022 goto out;
1023 }
1024 }
1025 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
1026 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id,
1027 psk_null_terminated)) {
1028 goto out;
1029 }
1030
1031 if (params->sae_password) {
1032 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1033 resp.network_id, sae_null_terminated)) {
1034 goto out;
1035 }
1036 } else {
1037 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
1038 resp.network_id, psk_null_terminated)) {
1039 goto out;
1040 }
1041 }
1042
1043 if (!wpa_cli_cmd_v("set sae_pwe 2")) {
1044 goto out;
1045 }
1046
1047 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK SAE",
1048 resp.network_id)) {
1049 goto out;
1050 }
1051 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1052 } else if (is_eap_valid_security(params->security)) {
1053 if (process_cipher_config(params, &cipher_config)) {
1054 goto out;
1055 }
1056
1057 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
1058 if (params->security == eap_config[index].type) {
1059 method = eap_config[index].method;
1060 phase2 = eap_config[index].phase2;
1061 break;
1062 }
1063 }
1064
1065 if (index == ARRAY_SIZE(eap_config)) {
1066 wpa_printf(MSG_ERROR, "Get eap method error with security type: %d",
1067 params->security);
1068 goto out;
1069 }
1070
1071 if (params->suiteb_type == WIFI_SUITEB_192) {
1072 if (params->TLS_cipher == WIFI_EAP_TLS_ECC_P384) {
1073 if (!wpa_cli_cmd_v("set_network %d openssl_ciphers \"%s\"",
1074 resp.network_id,
1075 cipher_config.openssl_ciphers))
1076 goto out;
1077 } else if (params->TLS_cipher == WIFI_EAP_TLS_RSA_3K) {
1078 snprintf(phase1, sizeof(phase1), "tls_suiteb=1");
1079 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"",
1080 resp.network_id, &phase1[0]))
1081 goto out;
1082 }
1083 }
1084
1085 if (!wpa_cli_cmd_v("set_network %d key_mgmt %s", resp.network_id,
1086 cipher_config.key_mgmt)) {
1087 goto out;
1088 }
1089
1090 if (!wpa_cli_cmd_v("set openssl_ciphers \"%s\"",
1091 cipher_config.openssl_ciphers)) {
1092 goto out;
1093 }
1094
1095 if (!wpa_cli_cmd_v("set_network %d group %s", resp.network_id,
1096 cipher_config.group_cipher)) {
1097 goto out;
1098 }
1099
1100 if (!wpa_cli_cmd_v("set_network %d pairwise %s", resp.network_id,
1101 cipher_config.pairwise_cipher)) {
1102 goto out;
1103 }
1104
1105 if (!wpa_cli_cmd_v("set_network %d group_mgmt %s", resp.network_id,
1106 cipher_config.group_mgmt_cipher)) {
1107 goto out;
1108 }
1109
1110 if (!wpa_cli_cmd_v("set_network %d proto RSN",
1111 resp.network_id)) {
1112 goto out;
1113 }
1114
1115 if (method != NULL) {
1116 if (!wpa_cli_cmd_v("set_network %d eap %s", resp.network_id,
1117 method)) {
1118 goto out;
1119 }
1120 }
1121
1122 if (params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
1123 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
1124 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
1125 snprintk(phase1, sizeof(phase1),
1126 "peapver=%d peaplabel=0 crypto_binding=0",
1127 params->eap_ver);
1128
1129 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"", resp.network_id,
1130 &phase1[0])) {
1131 goto out;
1132 }
1133 }
1134
1135 if (phase2 != NULL) {
1136 if (!wpa_cli_cmd_v("set_network %d phase2 \"%s\"", resp.network_id,
1137 phase2)) {
1138 goto out;
1139 }
1140 }
1141
1142 if (params->eap_id_length > 0) {
1143 if (!wpa_cli_cmd_v("set_network %d identity \"%s\"",
1144 resp.network_id, params->eap_identity)) {
1145 goto out;
1146 }
1147 }
1148
1149 if (params->eap_passwd_length > 0) {
1150 if (!wpa_cli_cmd_v("set_network %d password \"%s\"",
1151 resp.network_id, params->eap_password)) {
1152 goto out;
1153 }
1154 }
1155
1156 if (!wpa_cli_cmd_v("set_network %d anonymous_identity \"%s\"",
1157 resp.network_id, params->anon_id)) {
1158 goto out;
1159 }
1160
1161 if (wpas_config_process_blob(wpa_s->conf, "ca_cert",
1162 enterprise_creds.ca_cert,
1163 enterprise_creds.ca_cert_len)) {
1164 goto out;
1165 }
1166
1167 if (!wpa_cli_cmd_v("set_network %d ca_cert \"blob://ca_cert\"",
1168 resp.network_id)) {
1169 goto out;
1170 }
1171
1172 if (wpas_config_process_blob(wpa_s->conf, "client_cert",
1173 enterprise_creds.client_cert,
1174 enterprise_creds.client_cert_len)) {
1175 goto out;
1176 }
1177
1178 if (!wpa_cli_cmd_v("set_network %d client_cert \"blob://client_cert\"",
1179 resp.network_id)) {
1180 goto out;
1181 }
1182
1183 if (wpas_config_process_blob(wpa_s->conf, "private_key",
1184 enterprise_creds.client_key,
1185 enterprise_creds.client_key_len)) {
1186 goto out;
1187 }
1188
1189 if (!wpa_cli_cmd_v("set_network %d private_key \"blob://private_key\"",
1190 resp.network_id)) {
1191 goto out;
1192 }
1193
1194 if (!wpa_cli_cmd_v("set_network %d private_key_passwd \"%s\"",
1195 resp.network_id, params->key_passwd)) {
1196 goto out;
1197 }
1198
1199 if (wpas_config_process_blob(wpa_s->conf, "ca_cert2",
1200 enterprise_creds.ca_cert2,
1201 enterprise_creds.ca_cert2_len)) {
1202 goto out;
1203 }
1204
1205 if (!wpa_cli_cmd_v("set_network %d ca_cert2 \"blob://ca_cert2\"",
1206 resp.network_id)) {
1207 goto out;
1208 }
1209
1210 if (wpas_config_process_blob(wpa_s->conf, "client_cert2",
1211 enterprise_creds.client_cert2,
1212 enterprise_creds.client_cert2_len)) {
1213 goto out;
1214 }
1215
1216 if (!wpa_cli_cmd_v("set_network %d client_cert2 \"blob://client_cert2\"",
1217 resp.network_id)) {
1218 goto out;
1219 }
1220
1221 if (wpas_config_process_blob(wpa_s->conf, "private_key2",
1222 enterprise_creds.client_key2,
1223 enterprise_creds.client_key2_len)) {
1224 goto out;
1225 }
1226
1227 if (!wpa_cli_cmd_v("set_network %d private_key2 \"blob://private_key2\"",
1228 resp.network_id)) {
1229 goto out;
1230 }
1231
1232 if (!wpa_cli_cmd_v("set_network %d private_key2_passwd \"%s\"",
1233 resp.network_id, params->key2_passwd)) {
1234 goto out;
1235 }
1236 #endif
1237 } else {
1238 ret = -1;
1239 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
1240 params->security);
1241 goto rem_net;
1242 }
1243
1244 if (params->mfp) {
1245 if (!wpa_cli_cmd_v("set_network %d ieee80211w %d",
1246 resp.network_id, params->mfp)) {
1247 goto out;
1248 }
1249 }
1250 }
1251
1252 if (params->channel != WIFI_CHANNEL_ANY) {
1253 int freq;
1254
1255 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
1256 freq = wpa_supp_band_chan_compat(wpa_s, params->band, params->channel);
1257 if (freq < 0) {
1258 goto rem_net;
1259 }
1260 } else {
1261 freq = chan_to_freq(params->channel);
1262 if (freq < 0) {
1263 ret = -1;
1264 wpa_printf(MSG_ERROR, "Invalid channel %d",
1265 params->channel);
1266 goto rem_net;
1267 }
1268 }
1269
1270 if (mode_ap) {
1271 if (!wpa_cli_cmd_v("set_network %d frequency %d",
1272 resp.network_id, freq)) {
1273 goto out;
1274 }
1275 } else {
1276 if (!wpa_cli_cmd_v("set_network %d scan_freq %d",
1277 resp.network_id, freq)) {
1278 goto out;
1279 }
1280 }
1281 }
1282
1283 memcpy((void *)&mac, params->bssid, WIFI_MAC_ADDR_LEN);
1284 if (net_eth_is_addr_broadcast(&mac) ||
1285 net_eth_is_addr_multicast(&mac)) {
1286 wpa_printf(MSG_ERROR, "Invalid BSSID. Configuration "
1287 "of multicast or broadcast MAC is not allowed.");
1288 ret = -EINVAL;
1289 goto rem_net;
1290 }
1291
1292 if (!net_eth_is_addr_unspecified(&mac)) {
1293 char bssid_str[MAC_STR_LEN] = {0};
1294
1295 snprintf(bssid_str, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
1296 params->bssid[0], params->bssid[1], params->bssid[2],
1297 params->bssid[3], params->bssid[4], params->bssid[5]);
1298
1299 if (!wpa_cli_cmd_v("set_network %d bssid %s",
1300 resp.network_id, bssid_str)) {
1301 goto out;
1302 }
1303 }
1304
1305 /* enable and select network */
1306 if (!wpa_cli_cmd_v("enable_network %d", resp.network_id)) {
1307 goto out;
1308 }
1309
1310 if (!wpa_cli_cmd_v("select_network %d", resp.network_id)) {
1311 goto out;
1312 }
1313
1314 memset(&last_wifi_conn_params, 0, sizeof(struct wifi_connect_req_params));
1315 memcpy((void *)&last_wifi_conn_params, params, sizeof(struct wifi_connect_req_params));
1316 return 0;
1317
1318 rem_net:
1319 if (!wpa_cli_cmd_v("remove_network %d", resp.network_id)) {
1320 goto out;
1321 }
1322
1323 out:
1324 return ret;
1325 }
1326
wpas_disconnect_network(const struct device * dev,int cur_mode)1327 static int wpas_disconnect_network(const struct device *dev, int cur_mode)
1328 {
1329 struct net_if *iface = net_if_lookup_by_dev(dev);
1330 struct wpa_supplicant *wpa_s;
1331 bool is_ap = false;
1332 int ret = 0;
1333
1334 if (!iface) {
1335 ret = -ENOENT;
1336 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1337 return ret;
1338 }
1339
1340 wpa_s = get_wpa_s_handle(dev);
1341 if (!wpa_s) {
1342 ret = -1;
1343 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1344 goto out;
1345 }
1346
1347 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1348
1349 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != cur_mode) {
1350 ret = -EBUSY;
1351 wpa_printf(MSG_ERROR, "Interface %s is not in %s mode", dev->name,
1352 cur_mode == WPAS_MODE_INFRA ? "STA" : "AP");
1353 goto out;
1354 }
1355
1356 is_ap = (cur_mode == WPAS_MODE_AP);
1357
1358 wpas_api_ctrl.dev = dev;
1359 wpas_api_ctrl.requested_op = DISCONNECT;
1360
1361 if (!wpa_cli_cmd_v("disconnect")) {
1362 goto out;
1363 }
1364
1365 out:
1366 k_mutex_unlock(&wpa_supplicant_mutex);
1367
1368 if (ret) {
1369 wpa_printf(MSG_ERROR, "Disconnect failed: %s", strerror(-ret));
1370 return ret;
1371 }
1372
1373 wpa_supp_restart_status_work();
1374
1375 ret = wait_for_disconnect_complete(dev);
1376 #ifdef CONFIG_AP
1377 if (is_ap) {
1378 supplicant_send_wifi_mgmt_ap_status(wpa_s,
1379 NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT,
1380 ret == 0 ? WIFI_STATUS_AP_SUCCESS : WIFI_STATUS_AP_FAIL);
1381 } else {
1382 #else
1383 {
1384 #endif /* CONFIG_AP */
1385 wifi_mgmt_raise_disconnect_complete_event(iface, ret);
1386 }
1387
1388 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1389 wpas_remove_certs(wpa_s);
1390 #endif
1391
1392 if (!wpa_cli_cmd_v("remove_network all")) {
1393 wpa_printf(MSG_ERROR, "Failed to remove all networks");
1394 }
1395
1396 return ret;
1397 }
1398
1399 /* Public API */
1400 int supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params)
1401 {
1402 struct wpa_supplicant *wpa_s;
1403 int ret = 0;
1404
1405 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
1406 wpa_printf(MSG_ERROR,
1407 "Interface %s is down, dropping connect",
1408 dev->name);
1409 return -1;
1410 }
1411
1412 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1413
1414 wpa_s = get_wpa_s_handle(dev);
1415 if (!wpa_s) {
1416 ret = -1;
1417 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1418 goto out;
1419 }
1420
1421 /* Allow connect in STA mode only even if we are connected already */
1422 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != WPAS_MODE_INFRA) {
1423 ret = -EBUSY;
1424 wpa_printf(MSG_ERROR, "Interface %s is not in STA mode", dev->name);
1425 goto out;
1426 }
1427
1428 ret = wpas_add_and_config_network(wpa_s, params, false);
1429 if (ret) {
1430 wpa_printf(MSG_ERROR, "Failed to add and configure network for STA mode: %d", ret);
1431 goto out;
1432 }
1433
1434 wpas_api_ctrl.dev = dev;
1435 wpas_api_ctrl.requested_op = CONNECT;
1436 wpas_api_ctrl.connection_timeout = params->timeout;
1437
1438 out:
1439 k_mutex_unlock(&wpa_supplicant_mutex);
1440
1441 if (!ret) {
1442 wpa_supp_restart_status_work();
1443 }
1444
1445 return ret;
1446 }
1447
1448 int supplicant_disconnect(const struct device *dev)
1449 {
1450 return wpas_disconnect_network(dev, WPAS_MODE_INFRA);
1451 }
1452
1453 static enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option)
1454 {
1455 switch (supp_mfp_option) {
1456 case NO_MGMT_FRAME_PROTECTION:
1457 return WIFI_MFP_DISABLE;
1458 case MGMT_FRAME_PROTECTION_OPTIONAL:
1459 return WIFI_MFP_OPTIONAL;
1460 case MGMT_FRAME_PROTECTION_REQUIRED:
1461 return WIFI_MFP_REQUIRED;
1462 default:
1463 wpa_printf(MSG_ERROR, "Invalid mfp mapping %d", supp_mfp_option);
1464 break;
1465 }
1466
1467 return WIFI_MFP_DISABLE;
1468 }
1469
1470 static enum wifi_iface_mode get_iface_mode(enum wpas_mode supp_mode)
1471 {
1472 switch (supp_mode) {
1473 case WPAS_MODE_INFRA:
1474 return WIFI_MODE_INFRA;
1475 case WPAS_MODE_IBSS:
1476 return WIFI_MODE_IBSS;
1477 case WPAS_MODE_AP:
1478 return WIFI_MODE_AP;
1479 case WPAS_MODE_P2P_GO:
1480 return WIFI_MODE_P2P_GO;
1481 case WPAS_MODE_P2P_GROUP_FORMATION:
1482 return WIFI_MODE_P2P_GROUP_FORMATION;
1483 case WPAS_MODE_MESH:
1484 return WIFI_MODE_MESH;
1485 default:
1486 break;
1487 }
1488
1489 return WIFI_MODE_UNKNOWN;
1490 }
1491
1492 int supplicant_status(const struct device *dev, struct wifi_iface_status *status)
1493 {
1494 struct net_if *iface = net_if_lookup_by_dev(dev);
1495 struct wpa_supplicant *wpa_s;
1496 int ret = -1;
1497 struct wpa_signal_info *si = NULL;
1498 struct wpa_conn_info *conn_info = NULL;
1499
1500 if (!iface) {
1501 ret = -ENOENT;
1502 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1503 return ret;
1504 }
1505
1506 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1507
1508 wpa_s = get_wpa_s_handle(dev);
1509 if (!wpa_s) {
1510 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1511 goto out;
1512 }
1513
1514 si = os_zalloc(sizeof(struct wpa_signal_info));
1515 if (!si) {
1516 wpa_printf(MSG_ERROR, "Failed to allocate memory for signal info");
1517 goto out;
1518 }
1519
1520 status->state = wpa_s->wpa_state; /* 1-1 Mapping */
1521
1522 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1523 struct wpa_ssid *ssid = wpa_s->current_ssid;
1524 u8 channel;
1525 struct signal_poll_resp signal_poll;
1526 u8 *_ssid = ssid->ssid;
1527 size_t ssid_len = ssid->ssid_len;
1528 struct status_resp cli_status;
1529 int proto;
1530 int key_mgmt;
1531 int sae_pwe;
1532
1533 if (!ssid) {
1534 wpa_printf(MSG_ERROR, "Failed to get current ssid");
1535 goto out;
1536 }
1537
1538 proto = ssid->proto;
1539 key_mgmt = ssid->key_mgmt;
1540 sae_pwe = wpa_s->conf->sae_pwe;
1541 os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN);
1542 status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq));
1543 status->security = wpas_key_mgmt_to_zephyr(key_mgmt, proto, sae_pwe);
1544 status->mfp = get_mfp(ssid->ieee80211w);
1545 ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel);
1546 status->channel = channel;
1547
1548 if (ssid_len == 0) {
1549 int _res = z_wpa_ctrl_status(&cli_status);
1550
1551 if (_res < 0) {
1552 ssid_len = 0;
1553 } else {
1554 ssid_len = cli_status.ssid_len;
1555 }
1556
1557 _ssid = cli_status.ssid;
1558 }
1559
1560 os_memcpy(status->ssid, _ssid, ssid_len);
1561 status->ssid_len = ssid_len;
1562 status->iface_mode = get_iface_mode(ssid->mode);
1563
1564 if (wpa_s->connection_set == 1) {
1565 status->link_mode = wpa_s->connection_he ? WIFI_6 :
1566 wpa_s->connection_vht ? WIFI_5 :
1567 wpa_s->connection_ht ? WIFI_4 :
1568 wpa_s->connection_g ? WIFI_3 :
1569 wpa_s->connection_a ? WIFI_2 :
1570 wpa_s->connection_b ? WIFI_1 :
1571 WIFI_0;
1572 } else {
1573 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
1574 }
1575
1576 status->rssi = -WPA_INVALID_NOISE;
1577 if (status->iface_mode == WIFI_MODE_INFRA) {
1578 ret = z_wpa_ctrl_signal_poll(&signal_poll);
1579 if (!ret) {
1580 status->rssi = signal_poll.rssi;
1581 status->current_phy_tx_rate = signal_poll.current_txrate;
1582 } else {
1583 wpa_printf(MSG_WARNING, "%s: Failed to read signal poll info",
1584 __func__);
1585 }
1586 }
1587
1588 conn_info = os_zalloc(sizeof(struct wpa_conn_info));
1589 if (!conn_info) {
1590 wpa_printf(MSG_ERROR, "%s:Failed to allocate memory\n",
1591 __func__);
1592 ret = -ENOMEM;
1593 goto out;
1594 }
1595
1596 ret = wpa_drv_get_conn_info(wpa_s, conn_info);
1597 if (!ret) {
1598 status->beacon_interval = conn_info->beacon_interval;
1599 status->dtim_period = conn_info->dtim_period;
1600 status->twt_capable = conn_info->twt_capable;
1601 } else {
1602 wpa_printf(MSG_WARNING, "%s: Failed to get connection info\n",
1603 __func__);
1604
1605 status->beacon_interval = 0;
1606 status->dtim_period = 0;
1607 status->twt_capable = false;
1608 ret = 0;
1609 }
1610
1611 os_free(conn_info);
1612 } else {
1613 ret = 0;
1614 }
1615
1616 out:
1617 os_free(si);
1618 k_mutex_unlock(&wpa_supplicant_mutex);
1619 return ret;
1620 }
1621
1622 /* Below APIs are not natively supported by WPA supplicant, so,
1623 * these are just wrappers around driver offload APIs. But it is
1624 * transparent to the user.
1625 *
1626 * In the future these might be implemented natively by the WPA
1627 * supplicant.
1628 */
1629
1630 static const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev)
1631 {
1632 struct net_wifi_mgmt_offload *api = (struct net_wifi_mgmt_offload *)dev->api;
1633
1634 return api ? api->wifi_mgmt_api : NULL;
1635 }
1636
1637 int supplicant_get_version(const struct device *dev, struct wifi_version *params)
1638 {
1639 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1640
1641 if (!wifi_mgmt_api || !wifi_mgmt_api->get_version) {
1642 wpa_printf(MSG_ERROR, "get_version not supported");
1643 return -ENOTSUP;
1644 }
1645
1646 return wifi_mgmt_api->get_version(dev, params);
1647 }
1648
1649 int supplicant_scan(const struct device *dev, struct wifi_scan_params *params,
1650 scan_result_cb_t cb)
1651 {
1652 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1653
1654 if (!wifi_mgmt_api || !wifi_mgmt_api->scan) {
1655 wpa_printf(MSG_ERROR, "Scan not supported");
1656 return -ENOTSUP;
1657 }
1658
1659 return wifi_mgmt_api->scan(dev, params, cb);
1660 }
1661
1662 #ifdef CONFIG_NET_STATISTICS_WIFI
1663 int supplicant_get_stats(const struct device *dev, struct net_stats_wifi *stats)
1664 {
1665 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1666
1667 if (!wifi_mgmt_api || !wifi_mgmt_api->get_stats) {
1668 wpa_printf(MSG_ERROR, "Get stats not supported");
1669 return -ENOTSUP;
1670 }
1671
1672 return wifi_mgmt_api->get_stats(dev, stats);
1673 }
1674
1675 int supplicant_reset_stats(const struct device *dev)
1676 {
1677 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1678
1679 if (!wifi_mgmt_api || !wifi_mgmt_api->reset_stats) {
1680 wpa_printf(MSG_WARNING, "Reset stats not supported");
1681 return -ENOTSUP;
1682 }
1683
1684 return wifi_mgmt_api->reset_stats(dev);
1685 }
1686 #endif /* CONFIG_NET_STATISTICS_WIFI */
1687
1688 int supplicant_pmksa_flush(const struct device *dev)
1689 {
1690 struct wpa_supplicant *wpa_s;
1691 int ret = 0;
1692
1693 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1694
1695 wpa_s = get_wpa_s_handle(dev);
1696 if (!wpa_s) {
1697 ret = -1;
1698 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1699 goto out;
1700 }
1701
1702 if (!wpa_cli_cmd_v("pmksa_flush")) {
1703 ret = -1;
1704 wpa_printf(MSG_ERROR, "pmksa_flush failed");
1705 goto out;
1706 }
1707
1708 out:
1709 k_mutex_unlock(&wpa_supplicant_mutex);
1710 return ret;
1711 }
1712
1713 int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params)
1714 {
1715 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1716
1717 if (!wifi_mgmt_api || !wifi_mgmt_api->cfg_11k) {
1718 wpa_printf(MSG_ERROR, "cfg 11k not supported");
1719 return -ENOTSUP;
1720 }
1721
1722 return wifi_mgmt_api->cfg_11k(dev, params);
1723 }
1724
1725 int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params)
1726 {
1727 int ssid_len = strlen(params->ssid);
1728
1729 if (params != NULL && ssid_len > 0) {
1730 if (ssid_len > WIFI_SSID_MAX_LEN) {
1731 wpa_printf(MSG_ERROR, "%s: ssid too long %u",
1732 __func__, ssid_len);
1733 return -1;
1734 }
1735
1736 if (!wpa_cli_cmd_v("neighbor_rep_request ssid %s",
1737 params->ssid)) {
1738 wpa_printf(MSG_ERROR,
1739 "%s: cli cmd <neighbor_rep_request ssid %s> fail",
1740 __func__, params->ssid);
1741 return -1;
1742 }
1743 } else {
1744 if (!wpa_cli_cmd_v("neighbor_rep_request")) {
1745 wpa_printf(MSG_ERROR,
1746 "%s: cli cmd <neighbor_rep_request> fail",
1747 __func__);
1748 return -1;
1749 }
1750 }
1751
1752 return 0;
1753 }
1754
1755 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
1756 #define SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE 100
1757 int supplicant_candidate_scan(const struct device *dev, struct wifi_scan_params *params)
1758 {
1759 int i = 0;
1760 char cmd[SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE] = {0};
1761 char *pos = cmd;
1762 char *end = pos + SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE;
1763 int freq = 0;
1764
1765 strcpy(pos, "freq=");
1766 pos += 5;
1767 while (params->band_chan[i].channel) {
1768 if (i > 0) {
1769 pos += snprintf(pos, end - pos, ",");
1770 }
1771 freq = chan_to_freq(params->band_chan[i].channel);
1772 pos += snprintf(pos, end - pos, "%d", freq);
1773 i++;
1774 }
1775
1776 if (!wpa_cli_cmd_v("scan %s", cmd)) {
1777 wpa_printf(MSG_ERROR,
1778 "%s: cli cmd <scan %s> fail",
1779 __func__, cmd);
1780 return -1;
1781 }
1782
1783 return 0;
1784 }
1785
1786 int supplicant_11r_roaming(const struct device *dev)
1787 {
1788 struct wpa_supplicant *wpa_s;
1789 int ret = 0;
1790
1791 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1792
1793 wpa_s = get_wpa_s_handle(dev);
1794 if (!wpa_s) {
1795 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1796 ret = -1;
1797 goto out;
1798 }
1799
1800 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1801 wpa_s->wpa_state < WPA_COMPLETED)) {
1802 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1803 ret = 0;
1804 goto out;
1805 }
1806
1807 if (!wpa_cli_cmd_v("reassociate")) {
1808 wpa_printf(MSG_ERROR, "%s: cli cmd <reassociate> fail",
1809 __func__);
1810 ret = -1;
1811 goto out;
1812 }
1813
1814 out:
1815 k_mutex_unlock(&wpa_supplicant_mutex);
1816 return ret;
1817 }
1818 #endif
1819
1820 int supplicant_set_power_save(const struct device *dev, struct wifi_ps_params *params)
1821 {
1822 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1823
1824 if (!wifi_mgmt_api || !wifi_mgmt_api->set_power_save) {
1825 wpa_printf(MSG_ERROR, "Set power save not supported");
1826 return -ENOTSUP;
1827 }
1828
1829 return wifi_mgmt_api->set_power_save(dev, params);
1830 }
1831
1832 int supplicant_set_twt(const struct device *dev, struct wifi_twt_params *params)
1833 {
1834 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1835
1836 if (!wifi_mgmt_api || !wifi_mgmt_api->set_twt) {
1837 wpa_printf(MSG_ERROR, "Set TWT not supported");
1838 return -ENOTSUP;
1839 }
1840
1841 return wifi_mgmt_api->set_twt(dev, params);
1842 }
1843
1844 int supplicant_set_btwt(const struct device *dev, struct wifi_twt_params *params)
1845 {
1846 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1847
1848 if (!wifi_mgmt_api || !wifi_mgmt_api->set_btwt) {
1849 wpa_printf(MSG_ERROR, "Set Broadcast TWT not supported");
1850 return -ENOTSUP;
1851 }
1852
1853 return wifi_mgmt_api->set_btwt(dev, params);
1854 }
1855
1856 int supplicant_get_power_save_config(const struct device *dev,
1857 struct wifi_ps_config *config)
1858 {
1859 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1860
1861 if (!wifi_mgmt_api || !wifi_mgmt_api->get_power_save_config) {
1862 wpa_printf(MSG_ERROR, "Get power save config not supported");
1863 return -ENOTSUP;
1864 }
1865
1866 return wifi_mgmt_api->get_power_save_config(dev, config);
1867 }
1868
1869 int supplicant_reg_domain(const struct device *dev,
1870 struct wifi_reg_domain *reg_domain)
1871 {
1872 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1873 struct wpa_supplicant *wpa_s;
1874 int ret = -1;
1875
1876 if (!wifi_mgmt_api || !wifi_mgmt_api->reg_domain) {
1877 wpa_printf(MSG_ERROR, "Regulatory domain not supported");
1878 return -ENOTSUP;
1879 }
1880
1881 if (reg_domain->oper == WIFI_MGMT_GET) {
1882 return wifi_mgmt_api->reg_domain(dev, reg_domain);
1883 }
1884
1885 if (reg_domain->oper == WIFI_MGMT_SET) {
1886 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1887
1888 wpa_s = get_wpa_s_handle(dev);
1889 if (!wpa_s) {
1890 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1891 goto out;
1892 }
1893
1894 if (!wpa_cli_cmd_v("set country %s", reg_domain->country_code)) {
1895 goto out;
1896 }
1897
1898 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
1899 if (!hostapd_cli_cmd_v("set country_code %s", reg_domain->country_code)) {
1900 goto out;
1901 }
1902 #endif
1903
1904 ret = 0;
1905
1906 out:
1907 k_mutex_unlock(&wpa_supplicant_mutex);
1908 }
1909
1910 return ret;
1911 }
1912
1913 int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode)
1914 {
1915 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1916
1917 if (!wifi_mgmt_api || !wifi_mgmt_api->mode) {
1918 wpa_printf(MSG_ERROR, "Setting mode not supported");
1919 return -ENOTSUP;
1920 }
1921
1922 return wifi_mgmt_api->mode(dev, mode);
1923 }
1924
1925 int supplicant_filter(const struct device *dev, struct wifi_filter_info *filter)
1926 {
1927 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1928
1929 if (!wifi_mgmt_api || !wifi_mgmt_api->filter) {
1930 wpa_printf(MSG_ERROR, "Setting filter not supported");
1931 return -ENOTSUP;
1932 }
1933
1934 return wifi_mgmt_api->filter(dev, filter);
1935 }
1936
1937 int supplicant_channel(const struct device *dev, struct wifi_channel_info *channel)
1938 {
1939 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1940
1941 if (!wifi_mgmt_api || !wifi_mgmt_api->channel) {
1942 wpa_printf(MSG_ERROR, "Setting channel not supported");
1943 return -ENOTSUP;
1944 }
1945
1946 return wifi_mgmt_api->channel(dev, channel);
1947 }
1948
1949 int supplicant_set_rts_threshold(const struct device *dev, unsigned int rts_threshold)
1950 {
1951 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1952
1953 if (!wifi_mgmt_api || !wifi_mgmt_api->set_rts_threshold) {
1954 wpa_printf(MSG_ERROR, "Set RTS not supported");
1955 return -ENOTSUP;
1956 }
1957
1958 return wifi_mgmt_api->set_rts_threshold(dev, rts_threshold);
1959 }
1960
1961 int supplicant_get_rts_threshold(const struct device *dev, unsigned int *rts_threshold)
1962 {
1963 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1964
1965 if (!wifi_mgmt_api || !wifi_mgmt_api->get_rts_threshold) {
1966 wpa_printf(MSG_ERROR, "Get RTS not supported");
1967 return -ENOTSUP;
1968 }
1969
1970 return wifi_mgmt_api->get_rts_threshold(dev, rts_threshold);
1971 }
1972
1973 int supplicant_bss_ext_capab(const struct device *dev, int capab)
1974 {
1975 struct wpa_supplicant *wpa_s;
1976 int is_support = 0;
1977
1978 wpa_s = get_wpa_s_handle(dev);
1979 if (!wpa_s) {
1980 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1981 return 0;
1982 }
1983
1984 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1985 is_support = wpa_bss_ext_capab(wpa_s->current_bss, capab);
1986 k_mutex_unlock(&wpa_supplicant_mutex);
1987
1988 return is_support;
1989 }
1990
1991 int supplicant_legacy_roam(const struct device *dev)
1992 {
1993 int ret = -1;
1994
1995 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1996 if (!wpa_cli_cmd_v("scan")) {
1997 goto out;
1998 }
1999
2000 ret = 0;
2001
2002 out:
2003 k_mutex_unlock(&wpa_supplicant_mutex);
2004
2005 return ret;
2006 }
2007
2008 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
2009 int supplicant_btm_query(const struct device *dev, uint8_t reason)
2010 {
2011 struct wpa_supplicant *wpa_s;
2012 int ret = -1;
2013
2014 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2015
2016 wpa_s = get_wpa_s_handle(dev);
2017 if (!wpa_s) {
2018 ret = -1;
2019 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2020 goto out;
2021 }
2022
2023 if (!wpa_cli_cmd_v("wnm_bss_query %d", reason)) {
2024 goto out;
2025 }
2026
2027 ret = 0;
2028
2029 out:
2030 k_mutex_unlock(&wpa_supplicant_mutex);
2031
2032 return ret;
2033 }
2034 #endif
2035
2036 int supplicant_get_wifi_conn_params(const struct device *dev,
2037 struct wifi_connect_req_params *params)
2038 {
2039 struct wpa_supplicant *wpa_s;
2040 int ret = 0;
2041
2042 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2043
2044 wpa_s = get_wpa_s_handle(dev);
2045 if (!wpa_s) {
2046 ret = -1;
2047 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2048 goto out;
2049 }
2050
2051 memcpy(params, &last_wifi_conn_params, sizeof(struct wifi_connect_req_params));
2052 out:
2053 k_mutex_unlock(&wpa_supplicant_mutex);
2054 return ret;
2055 }
2056
2057 static int supplicant_wps_pbc(const struct device *dev)
2058 {
2059 struct wpa_supplicant *wpa_s;
2060 int ret = -1;
2061
2062 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2063
2064 wpa_s = get_wpa_s_handle(dev);
2065 if (!wpa_s) {
2066 ret = -1;
2067 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2068 goto out;
2069 }
2070
2071 if (!wpa_cli_cmd_v("wps_pbc")) {
2072 goto out;
2073 }
2074
2075 wpas_api_ctrl.dev = dev;
2076 wpas_api_ctrl.requested_op = WPS_PBC;
2077
2078 ret = 0;
2079
2080 out:
2081 k_mutex_unlock(&wpa_supplicant_mutex);
2082
2083 return ret;
2084 }
2085
2086 static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
2087 {
2088 struct wpa_supplicant *wpa_s;
2089 char *get_pin_cmd = "WPS_PIN get";
2090 int ret = -1;
2091
2092 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2093
2094 wpa_s = get_wpa_s_handle(dev);
2095 if (!wpa_s) {
2096 ret = -1;
2097 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2098 goto out;
2099 }
2100
2101 if (params->oper == WIFI_WPS_PIN_GET) {
2102 if (zephyr_wpa_cli_cmd_resp(get_pin_cmd, params->pin)) {
2103 goto out;
2104 }
2105 } else if (params->oper == WIFI_WPS_PIN_SET) {
2106 if (!wpa_cli_cmd_v("wps_check_pin %s", params->pin)) {
2107 goto out;
2108 }
2109
2110 if (!wpa_cli_cmd_v("wps_pin any %s", params->pin)) {
2111 goto out;
2112 }
2113
2114 wpas_api_ctrl.dev = dev;
2115 wpas_api_ctrl.requested_op = WPS_PIN;
2116 } else {
2117 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2118 goto out;
2119 }
2120
2121 ret = 0;
2122
2123 out:
2124 k_mutex_unlock(&wpa_supplicant_mutex);
2125
2126 return ret;
2127 }
2128
2129 int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2130 {
2131 int ret = 0;
2132
2133 if (params->oper == WIFI_WPS_PBC) {
2134 ret = supplicant_wps_pbc(dev);
2135 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2136 ret = supplicant_wps_pin(dev, params);
2137 }
2138
2139 return ret;
2140 }
2141
2142 #ifdef CONFIG_AP
2143 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2144 int hapd_state(const struct device *dev, int *state)
2145 {
2146 struct hostapd_iface *iface;
2147 int ret = 0;
2148
2149 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2150
2151 iface = get_hostapd_handle(dev);
2152 if (!iface) {
2153 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2154 ret = -ENOENT;
2155 goto out;
2156 }
2157
2158 *state = iface->state;
2159
2160 out:
2161 k_mutex_unlock(&wpa_supplicant_mutex);
2162 return ret;
2163 }
2164
2165 static int hapd_config_chan_center_seg0(struct wifi_connect_req_params *params)
2166 {
2167 int ret = 0;
2168 uint8_t center_freq_seg0_idx = 0;
2169 uint8_t oper_chwidth = CHANWIDTH_USE_HT;
2170 const uint8_t *center_freq = NULL;
2171 static const uint8_t center_freq_40MHz[] = {38, 46, 54, 62, 102, 110,
2172 118, 126, 134, 142, 151, 159};
2173 static const uint8_t center_freq_80MHz[] = {42, 58, 106, 122, 138, 155};
2174 uint8_t index, index_max, chan_idx, ch_offset = 0;
2175
2176 /* Unless ACS is being used, both "channel" and "vht_oper_centr_freq_seg0_idx"
2177 * parameters must be set.
2178 */
2179 switch (params->bandwidth) {
2180 case WIFI_FREQ_BANDWIDTH_20MHZ:
2181 oper_chwidth = CHANWIDTH_USE_HT;
2182 center_freq_seg0_idx = params->channel;
2183 break;
2184 case WIFI_FREQ_BANDWIDTH_40MHZ:
2185 oper_chwidth = CHANWIDTH_USE_HT;
2186 center_freq = center_freq_40MHz;
2187 index_max = ARRAY_SIZE(center_freq_40MHz);
2188 ch_offset = 2;
2189 break;
2190 case WIFI_FREQ_BANDWIDTH_80MHZ:
2191 oper_chwidth = CHANWIDTH_80MHZ;
2192 center_freq = center_freq_80MHz;
2193 index_max = ARRAY_SIZE(center_freq_80MHz);
2194 ch_offset = 6;
2195 break;
2196 default:
2197 return -EINVAL;
2198 }
2199
2200 if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) {
2201 chan_idx = params->channel;
2202 for (index = 0; index < index_max; index++) {
2203 if ((chan_idx >= (center_freq[index] - ch_offset)) &&
2204 (chan_idx <= (center_freq[index] + ch_offset))) {
2205 center_freq_seg0_idx = center_freq[index];
2206 break;
2207 }
2208 }
2209 }
2210
2211 if (!hostapd_cli_cmd_v("set vht_oper_chwidth %d", oper_chwidth)) {
2212 goto out;
2213 }
2214 if (!hostapd_cli_cmd_v("set vht_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
2215 goto out;
2216 }
2217 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX
2218 if (!hostapd_cli_cmd_v("set he_oper_chwidth %d", oper_chwidth)) {
2219 goto out;
2220 }
2221 if (!hostapd_cli_cmd_v("set he_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
2222 goto out;
2223 }
2224 #endif
2225
2226 return ret;
2227 out:
2228 return -EINVAL;
2229 }
2230
2231 int hapd_config_network(struct hostapd_iface *iface,
2232 struct wifi_connect_req_params *params)
2233 {
2234 int ret = 0;
2235
2236 if (!hostapd_cli_cmd_v("set ssid %s", params->ssid)) {
2237 goto out;
2238 }
2239
2240 if (params->channel == 0) {
2241 if (params->band == 0) {
2242 if (!hostapd_cli_cmd_v("set hw_mode g")) {
2243 goto out;
2244 }
2245 } else if (params->band == 1) {
2246 if (!hostapd_cli_cmd_v("set hw_mode a")) {
2247 goto out;
2248 }
2249 } else {
2250 wpa_printf(MSG_ERROR, "Invalid band %d", params->band);
2251 goto out;
2252 }
2253 } else if (params->channel > 14) {
2254 if (!hostapd_cli_cmd_v("set hw_mode a")) {
2255 goto out;
2256 }
2257 } else {
2258 if (!hostapd_cli_cmd_v("set hw_mode g")) {
2259 goto out;
2260 }
2261 }
2262
2263 if (!hostapd_cli_cmd_v("set channel %d", params->channel)) {
2264 goto out;
2265 }
2266
2267 ret = hapd_config_chan_center_seg0(params);
2268 if (ret) {
2269 goto out;
2270 }
2271
2272 if (params->security != WIFI_SECURITY_TYPE_NONE) {
2273 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
2274 if (!hostapd_cli_cmd_v("set wpa 1")) {
2275 goto out;
2276 }
2277 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
2278 goto out;
2279 }
2280 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2281 goto out;
2282 }
2283 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
2284 goto out;
2285 }
2286 } else if (params->security == WIFI_SECURITY_TYPE_PSK) {
2287 if (!hostapd_cli_cmd_v("set wpa 2")) {
2288 goto out;
2289 }
2290 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
2291 goto out;
2292 }
2293 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2294 goto out;
2295 }
2296 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2297 goto out;
2298 }
2299 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
2300 if (!hostapd_cli_cmd_v("set wpa 2")) {
2301 goto out;
2302 }
2303 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK-SHA256")) {
2304 goto out;
2305 }
2306 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2307 goto out;
2308 }
2309 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2310 goto out;
2311 }
2312 } else if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
2313 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
2314 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
2315 if (!hostapd_cli_cmd_v("set wpa 2")) {
2316 goto out;
2317 }
2318 if (!hostapd_cli_cmd_v("set wpa_key_mgmt SAE")) {
2319 goto out;
2320 }
2321 if (!hostapd_cli_cmd_v("set sae_password %s",
2322 params->sae_password ? params->sae_password :
2323 params->psk)) {
2324 goto out;
2325 }
2326 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2327 goto out;
2328 }
2329 if (params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
2330 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
2331 if (!hostapd_cli_cmd_v("set sae_pwe %d",
2332 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
2333 ? 1
2334 : 2)) {
2335 goto out;
2336 }
2337 }
2338 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
2339 if (!hostapd_cli_cmd_v("set wpa 2")) {
2340 goto out;
2341 }
2342
2343 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK SAE")) {
2344 goto out;
2345 }
2346
2347 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2348 goto out;
2349 }
2350
2351 if (!hostapd_cli_cmd_v("set sae_password %s",
2352 params->sae_password ? params->sae_password
2353 : params->psk)) {
2354 goto out;
2355 }
2356
2357 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2358 goto out;
2359 }
2360
2361 if (!hostapd_cli_cmd_v("set sae_pwe 2")) {
2362 goto out;
2363 }
2364 } else if (params->security == WIFI_SECURITY_TYPE_DPP) {
2365 if (!hostapd_cli_cmd_v("set wpa 2")) {
2366 goto out;
2367 }
2368 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK DPP")) {
2369 goto out;
2370 }
2371 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
2372 goto out;
2373 }
2374 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
2375 goto out;
2376 }
2377 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
2378 goto out;
2379 }
2380 if (!hostapd_cli_cmd_v("set dpp_configurator_connectivity 1")) {
2381 goto out;
2382 }
2383 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
2384 } else if (is_eap_valid_security(params->security)) {
2385 if (hapd_process_enterprise_config(iface, params)) {
2386 goto out;
2387 }
2388 #endif
2389 }
2390 } else {
2391 if (!hostapd_cli_cmd_v("set wpa 0")) {
2392 goto out;
2393 }
2394 iface->bss[0]->conf->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
2395 }
2396
2397 if (!hostapd_cli_cmd_v("set ieee80211w %d", params->mfp)) {
2398 goto out;
2399 }
2400
2401 if (!hostapd_cli_cmd_v("set ignore_broadcast_ssid %d", params->ignore_broadcast_ssid)) {
2402 goto out;
2403 }
2404
2405 return ret;
2406 out:
2407 return -1;
2408 }
2409
2410 static int set_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
2411 {
2412 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2413
2414 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2415 return -ENOTSUP;
2416 }
2417
2418 return wifi_mgmt_api->ap_config_params(dev, params);
2419 }
2420
2421 int supplicant_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
2422 {
2423 struct hostapd_iface *iface;
2424 int ret = 0;
2425
2426 ret = set_ap_config_params(dev, params);
2427 if (ret && (ret != -ENOTSUP)) {
2428 wpa_printf(MSG_ERROR, "Failed to set ap config params");
2429 return -EINVAL;
2430 }
2431
2432 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2433
2434 iface = get_hostapd_handle(dev);
2435 if (iface == NULL) {
2436 ret = -ENOENT;
2437 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2438 goto out;
2439 }
2440
2441 if (iface->state > HAPD_IFACE_DISABLED) {
2442 ret = -EBUSY;
2443 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
2444 goto out;
2445 }
2446
2447 if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) {
2448 if (!hostapd_cli_cmd_v("set max_num_sta %d", params->max_num_sta)) {
2449 ret = -EINVAL;
2450 wpa_printf(MSG_ERROR, "Failed to set maximum number of stations");
2451 goto out;
2452 }
2453 wpa_printf(MSG_INFO, "Set maximum number of stations: %d", params->max_num_sta);
2454 }
2455
2456 if (params->type & WIFI_AP_CONFIG_PARAM_HT_CAPAB) {
2457 if (!hostapd_cli_cmd_v("set ht_capab %s", params->ht_capab)) {
2458 ret = -EINVAL;
2459 wpa_printf(MSG_ERROR, "Failed to set HT capabilities");
2460 goto out;
2461 }
2462 wpa_printf(MSG_INFO, "Set HT capabilities: %s", params->ht_capab);
2463 }
2464
2465 if (params->type & WIFI_AP_CONFIG_PARAM_VHT_CAPAB) {
2466 if (!hostapd_cli_cmd_v("set vht_capab %s", params->vht_capab)) {
2467 ret = -EINVAL;
2468 wpa_printf(MSG_ERROR, "Failed to set VHT capabilities");
2469 goto out;
2470 }
2471 wpa_printf(MSG_INFO, "Set VHT capabilities: %s", params->vht_capab);
2472 }
2473
2474 out:
2475 k_mutex_unlock(&wpa_supplicant_mutex);
2476
2477 return ret;
2478 }
2479
2480 int supplicant_ap_status(const struct device *dev, struct wifi_iface_status *status)
2481 {
2482 int ret = 0;
2483 struct hostapd_iface *iface;
2484 struct hostapd_config *conf;
2485 struct hostapd_data *hapd;
2486 struct hostapd_bss_config *bss;
2487 struct hostapd_ssid *ssid;
2488 struct hostapd_hw_modes *hw_mode;
2489 int proto; /* Wi-Fi secure protocol */
2490 int key_mgmt; /* Wi-Fi key management */
2491 int sae_pwe;
2492
2493 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2494
2495 iface = get_hostapd_handle(dev);
2496 if (!iface) {
2497 ret = -1;
2498 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2499 goto out;
2500 }
2501
2502 conf = iface->conf;
2503 if (!conf) {
2504 ret = -1;
2505 wpa_printf(MSG_ERROR, "Conf %s not found", dev->name);
2506 goto out;
2507 }
2508
2509 bss = conf->bss[0];
2510 if (!bss) {
2511 ret = -1;
2512 wpa_printf(MSG_ERROR, "Bss_conf %s not found", dev->name);
2513 goto out;
2514 }
2515
2516 hapd = iface->bss[0];
2517 if (!hapd) {
2518 ret = -1;
2519 wpa_printf(MSG_ERROR, "Bss %s not found", dev->name);
2520 goto out;
2521 }
2522
2523 status->state = iface->state;
2524 ssid = &bss->ssid;
2525
2526 os_memcpy(status->bssid, hapd->own_addr, WIFI_MAC_ADDR_LEN);
2527 status->iface_mode = WIFI_MODE_AP;
2528 status->band = wpas_band_to_zephyr(wpas_freq_to_band(iface->freq));
2529 key_mgmt = bss->wpa_key_mgmt;
2530 proto = bss->wpa;
2531 sae_pwe = bss->sae_pwe;
2532 status->security = wpas_key_mgmt_to_zephyr(key_mgmt, proto, sae_pwe);
2533 status->mfp = get_mfp(bss->ieee80211w);
2534 status->channel = conf->channel;
2535 os_memcpy(status->ssid, ssid->ssid, ssid->ssid_len);
2536
2537 status->dtim_period = bss->dtim_period;
2538 status->beacon_interval = conf->beacon_int;
2539
2540 hw_mode = iface->current_mode;
2541
2542 status->link_mode = conf->ieee80211ax ? WIFI_6
2543 : conf->ieee80211ac ? WIFI_5
2544 : conf->ieee80211n ? WIFI_4
2545 : hw_mode->mode == HOSTAPD_MODE_IEEE80211G ? WIFI_3
2546 : hw_mode->mode == HOSTAPD_MODE_IEEE80211A ? WIFI_2
2547 : hw_mode->mode == HOSTAPD_MODE_IEEE80211B ? WIFI_1
2548 : WIFI_0;
2549 status->twt_capable = (hw_mode->he_capab[IEEE80211_MODE_AP].mac_cap[0] & 0x04);
2550
2551 out:
2552 k_mutex_unlock(&wpa_supplicant_mutex);
2553 return ret;
2554 }
2555 #endif /* CONFIG_WIFI_NM_HOSTAPD_AP */
2556
2557 #ifdef CONFIG_WIFI_NM_HOSTAPD_WPS
2558 int supplicant_ap_wps_pbc(const struct device *dev)
2559 {
2560 struct hostapd_iface *iface;
2561 int ret = -1;
2562
2563 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2564
2565 iface = get_hostapd_handle(dev);
2566 if (!iface) {
2567 ret = -1;
2568 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2569 goto out;
2570 }
2571
2572 if (iface->state != HAPD_IFACE_ENABLED) {
2573 ret = -EBUSY;
2574 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2575 goto out;
2576 }
2577
2578 if (!hostapd_cli_cmd_v("wps_pbc")) {
2579 goto out;
2580 }
2581
2582 wpas_api_ctrl.dev = dev;
2583 wpas_api_ctrl.requested_op = WPS_PBC;
2584
2585 ret = 0;
2586
2587 out:
2588 k_mutex_unlock(&wpa_supplicant_mutex);
2589
2590 return ret;
2591 }
2592
2593 int supplicant_ap_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
2594 {
2595 #define WPS_PIN_EXPIRE_TIME 120
2596 struct hostapd_iface *iface;
2597 char *get_pin_cmd = "WPS_AP_PIN random";
2598 int ret = 0;
2599
2600 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2601
2602 iface = get_hostapd_handle(dev);
2603 if (!iface) {
2604 ret = -1;
2605 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2606 goto out;
2607 }
2608
2609 if (iface->state != HAPD_IFACE_ENABLED) {
2610 ret = -EBUSY;
2611 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2612 goto out;
2613 }
2614
2615 if (params->oper == WIFI_WPS_PIN_GET) {
2616 if (zephyr_hostapd_cli_cmd_resp(get_pin_cmd, params->pin)) {
2617 goto out;
2618 }
2619 } else if (params->oper == WIFI_WPS_PIN_SET) {
2620 if (!hostapd_cli_cmd_v("wps_check_pin %s", params->pin)) {
2621 goto out;
2622 }
2623
2624 if (!hostapd_cli_cmd_v("wps_pin any %s %d", params->pin, WPS_PIN_EXPIRE_TIME)) {
2625 goto out;
2626 }
2627
2628 wpas_api_ctrl.dev = dev;
2629 wpas_api_ctrl.requested_op = WPS_PIN;
2630 } else {
2631 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2632 goto out;
2633 }
2634
2635 ret = 0;
2636
2637 out:
2638 k_mutex_unlock(&wpa_supplicant_mutex);
2639
2640 return ret;
2641 }
2642
2643
2644 int supplicant_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2645 {
2646 int ret = 0;
2647
2648 if (params->oper == WIFI_WPS_PBC) {
2649 ret = supplicant_ap_wps_pbc(dev);
2650 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2651 ret = supplicant_ap_wps_pin(dev, params);
2652 }
2653
2654 return ret;
2655 }
2656 #endif
2657
2658 static int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth)
2659 {
2660 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2661 struct wifi_ap_config_params params = {0};
2662
2663 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2664 return -ENOTSUP;
2665 }
2666
2667 params.bandwidth = bandwidth;
2668 params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH;
2669 return wifi_mgmt_api->ap_config_params(dev, ¶ms);
2670 }
2671
2672 int supplicant_ap_enable(const struct device *dev,
2673 struct wifi_connect_req_params *params)
2674 {
2675 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2676 struct hostapd_iface *iface;
2677 struct hostapd_data *hapd;
2678 struct wpa_driver_capa capa;
2679 #else
2680 struct wpa_supplicant *wpa_s;
2681 #endif
2682 int ret;
2683
2684 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
2685 wpa_printf(MSG_ERROR,
2686 "Interface %s is down, dropping connect",
2687 dev->name);
2688 return -1;
2689 }
2690
2691 ret = set_ap_bandwidth(dev, params->bandwidth);
2692 if (ret && (ret != -ENOTSUP)) {
2693 wpa_printf(MSG_ERROR, "Failed to set ap bandwidth");
2694 return -EINVAL;
2695 }
2696
2697 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2698
2699 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2700 iface = get_hostapd_handle(dev);
2701 if (!iface) {
2702 ret = -1;
2703 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2704 goto out;
2705 }
2706
2707 iface->owner = iface;
2708
2709 if (iface->state == HAPD_IFACE_ENABLED) {
2710 ret = -EBUSY;
2711 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
2712 goto out;
2713 }
2714
2715 ret = hapd_config_network(iface, params);
2716 if (ret) {
2717 wpa_printf(MSG_ERROR, "Failed to configure network for AP: %d", ret);
2718 goto out;
2719 }
2720
2721 hapd = iface->bss[0];
2722 if (!iface->extended_capa || !iface->extended_capa_mask) {
2723 if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
2724 iface->extended_capa = capa.extended_capa;
2725 iface->extended_capa_mask = capa.extended_capa_mask;
2726 iface->extended_capa_len = capa.extended_capa_len;
2727 iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
2728
2729 /*
2730 * Override extended capa with per-interface type (AP), if
2731 * available from the driver.
2732 */
2733 hostapd_get_ext_capa(iface);
2734 } else {
2735 ret = -1;
2736 wpa_printf(MSG_ERROR, "Failed to get capability for AP: %d", ret);
2737 goto out;
2738 }
2739 }
2740
2741 if (!hostapd_cli_cmd_v("enable")) {
2742 goto out;
2743 }
2744
2745 #else
2746 wpa_s = get_wpa_s_handle(dev);
2747 if (!wpa_s) {
2748 ret = -1;
2749 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2750 goto out;
2751 }
2752
2753 if (wpa_s->wpa_state != WPA_DISCONNECTED) {
2754 ret = -EBUSY;
2755 wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name);
2756 goto out;
2757 }
2758
2759 /* No need to check for existing network to join for SoftAP */
2760 wpa_s->conf->ap_scan = 2;
2761 /* Set BSS parameter max_num_sta to default configured value */
2762 wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA;
2763
2764 ret = wpas_add_and_config_network(wpa_s, params, true);
2765 if (ret) {
2766 wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret);
2767 goto out;
2768 }
2769 #endif
2770
2771 out:
2772 k_mutex_unlock(&wpa_supplicant_mutex);
2773
2774 return ret;
2775 }
2776
2777 int supplicant_ap_disable(const struct device *dev)
2778 {
2779 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2780 struct hostapd_iface *iface;
2781 int ret = 0;
2782 #else
2783 struct wpa_supplicant *wpa_s;
2784 int ret = -1;
2785 #endif
2786
2787 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2788
2789 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2790 iface = get_hostapd_handle(dev);
2791 if (!iface) {
2792 ret = -ENOENT;
2793 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2794 goto out;
2795 }
2796
2797 if (iface->state != HAPD_IFACE_ENABLED) {
2798 ret = -EBUSY;
2799 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2800 goto out;
2801 }
2802
2803 if (!hostapd_cli_cmd_v("disable")) {
2804 goto out;
2805 }
2806
2807 iface->freq = 0;
2808 #else
2809 wpa_s = get_wpa_s_handle(dev);
2810 if (!wpa_s) {
2811 ret = -1;
2812 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2813 goto out;
2814 }
2815
2816 ret = wpas_disconnect_network(dev, WPAS_MODE_AP);
2817 if (ret) {
2818 wpa_printf(MSG_ERROR, "Failed to disconnect from network");
2819 goto out;
2820 }
2821
2822 /* Restore ap_scan to default value */
2823 wpa_s->conf->ap_scan = 1;
2824 #endif
2825
2826 out:
2827 k_mutex_unlock(&wpa_supplicant_mutex);
2828 return ret;
2829 }
2830
2831 int supplicant_ap_sta_disconnect(const struct device *dev,
2832 const uint8_t *mac_addr)
2833 {
2834 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2835 struct hostapd_iface *iface;
2836 int ret = 0;
2837 #else
2838 struct wpa_supplicant *wpa_s;
2839 int ret = -1;
2840 #endif
2841
2842 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2843
2844 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
2845 iface = get_hostapd_handle(dev);
2846 if (!iface) {
2847 ret = -1;
2848 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2849 goto out;
2850 }
2851
2852 if (iface->state != HAPD_IFACE_ENABLED) {
2853 ret = -EBUSY;
2854 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
2855 goto out;
2856 }
2857
2858 if (!mac_addr) {
2859 ret = -EINVAL;
2860 wpa_printf(MSG_ERROR, "Invalid MAC address");
2861 goto out;
2862 }
2863
2864 if (!hostapd_cli_cmd_v("deauthenticate %02x:%02x:%02x:%02x:%02x:%02x",
2865 mac_addr[0], mac_addr[1], mac_addr[2],
2866 mac_addr[3], mac_addr[4], mac_addr[5])) {
2867 goto out;
2868 }
2869
2870 #else
2871 wpa_s = get_wpa_s_handle(dev);
2872 if (!wpa_s) {
2873 ret = -1;
2874 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2875 goto out;
2876 }
2877
2878 if (!mac_addr) {
2879 ret = -EINVAL;
2880 wpa_printf(MSG_ERROR, "Invalid MAC address");
2881 goto out;
2882 }
2883
2884 if (!wpa_cli_cmd_v("disassociate %02x:%02x:%02x:%02x:%02x:%02x",
2885 mac_addr[0], mac_addr[1], mac_addr[2],
2886 mac_addr[3], mac_addr[4], mac_addr[5])) {
2887 goto out;
2888 }
2889
2890 ret = 0;
2891 #endif
2892
2893 out:
2894 k_mutex_unlock(&wpa_supplicant_mutex);
2895
2896 return ret;
2897 }
2898 #endif /* CONFIG_AP */
2899
2900 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
2901 static const char *dpp_params_to_args_curve(int curve)
2902 {
2903 switch (curve) {
2904 case WIFI_DPP_CURVES_P_256:
2905 return "P-256";
2906 case WIFI_DPP_CURVES_P_384:
2907 return "P-384";
2908 case WIFI_DPP_CURVES_P_512:
2909 return "P-521";
2910 case WIFI_DPP_CURVES_BP_256:
2911 return "BP-256";
2912 case WIFI_DPP_CURVES_BP_384:
2913 return "BP-384";
2914 case WIFI_DPP_CURVES_BP_512:
2915 return "BP-512";
2916 default:
2917 return "P-256";
2918 }
2919 }
2920
2921 static const char *dpp_params_to_args_conf(int conf)
2922 {
2923 switch (conf) {
2924 case WIFI_DPP_CONF_STA:
2925 return "sta-dpp";
2926 case WIFI_DPP_CONF_AP:
2927 return "ap-dpp";
2928 case WIFI_DPP_CONF_QUERY:
2929 return "query";
2930 default:
2931 return "sta-dpp";
2932 }
2933 }
2934
2935 static const char *dpp_params_to_args_role(int role)
2936 {
2937 switch (role) {
2938 case WIFI_DPP_ROLE_CONFIGURATOR:
2939 return "configurator";
2940 case WIFI_DPP_ROLE_ENROLLEE:
2941 return "enrollee";
2942 case WIFI_DPP_ROLE_EITHER:
2943 return "either";
2944 default:
2945 return "either";
2946 }
2947 }
2948
2949 static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len)
2950 {
2951 uint8_t *end = src + strlen(src);
2952
2953 /* do 4 bytes convert first */
2954 for (; (src + 4) < end; src += 4) {
2955 snprintf(dst, max_len, "%02x%02x%02x%02x",
2956 src[0], src[1], src[2], src[3]);
2957 dst += 8;
2958 }
2959
2960 /* then do 1 byte convert */
2961 for (; src < end; src++) {
2962 snprintf(dst, max_len, "%02x", src[0]);
2963 dst += 2;
2964 }
2965 }
2966
2967 #define SUPPLICANT_DPP_CMD_BUF_SIZE 384
2968 #define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur)))
2969
2970 static int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len)
2971 {
2972 char *pos = cmd;
2973 char *end = cmd + max_len;
2974
2975 switch (params->action) {
2976 case WIFI_DPP_CONFIGURATOR_ADD:
2977 strncpy(pos, "DPP_CONFIGURATOR_ADD", end - pos);
2978 STR_CUR_TO_END(pos);
2979
2980 if (params->configurator_add.curve) {
2981 snprintf(pos, end - pos, " curve=%s",
2982 dpp_params_to_args_curve(params->configurator_add.curve));
2983 STR_CUR_TO_END(pos);
2984 }
2985
2986 if (params->configurator_add.net_access_key_curve) {
2987 snprintf(pos, end - pos, " net_access_key_curve=%s",
2988 dpp_params_to_args_curve(
2989 params->configurator_add.net_access_key_curve));
2990 }
2991 break;
2992 case WIFI_DPP_AUTH_INIT:
2993 strncpy(pos, "DPP_AUTH_INIT", end - pos);
2994 STR_CUR_TO_END(pos);
2995
2996 if (params->auth_init.peer) {
2997 snprintf(pos, end - pos, " peer=%d", params->auth_init.peer);
2998 STR_CUR_TO_END(pos);
2999 }
3000
3001 if (params->auth_init.conf) {
3002 snprintf(pos, end - pos, " conf=%s",
3003 dpp_params_to_args_conf(
3004 params->auth_init.conf));
3005 STR_CUR_TO_END(pos);
3006 }
3007
3008 if (params->auth_init.ssid[0]) {
3009 strncpy(pos, " ssid=", end - pos);
3010 STR_CUR_TO_END(pos);
3011 dpp_ssid_bin2str(pos, params->auth_init.ssid,
3012 WIFI_SSID_MAX_LEN * 2);
3013 STR_CUR_TO_END(pos);
3014 }
3015
3016 if (params->auth_init.configurator) {
3017 snprintf(pos, end - pos, " configurator=%d",
3018 params->auth_init.configurator);
3019 STR_CUR_TO_END(pos);
3020 }
3021
3022 if (params->auth_init.role) {
3023 snprintf(pos, end - pos, " role=%s",
3024 dpp_params_to_args_role(
3025 params->auth_init.role));
3026 }
3027 break;
3028 case WIFI_DPP_QR_CODE:
3029 strncpy(pos, "DPP_QR_CODE", end - pos);
3030 STR_CUR_TO_END(pos);
3031
3032 if (params->dpp_qr_code[0]) {
3033 snprintf(pos, end - pos, " %s", params->dpp_qr_code);
3034 }
3035 break;
3036 case WIFI_DPP_CHIRP:
3037 strncpy(pos, "DPP_CHIRP", end - pos);
3038 STR_CUR_TO_END(pos);
3039
3040 if (params->chirp.id) {
3041 snprintf(pos, end - pos, " own=%d", params->chirp.id);
3042 STR_CUR_TO_END(pos);
3043 }
3044
3045 if (params->chirp.freq) {
3046 snprintf(pos, end - pos, " listen=%d", params->chirp.freq);
3047 }
3048 break;
3049 case WIFI_DPP_LISTEN:
3050 strncpy(pos, "DPP_LISTEN", end - pos);
3051 STR_CUR_TO_END(pos);
3052
3053 if (params->listen.freq) {
3054 snprintf(pos, end - pos, " %d", params->listen.freq);
3055 STR_CUR_TO_END(pos);
3056 }
3057
3058 if (params->listen.role) {
3059 snprintf(pos, end - pos, " role=%s",
3060 dpp_params_to_args_role(
3061 params->listen.role));
3062 }
3063 break;
3064 case WIFI_DPP_BOOTSTRAP_GEN:
3065 strncpy(pos, "DPP_BOOTSTRAP_GEN", end - pos);
3066 STR_CUR_TO_END(pos);
3067
3068 if (params->bootstrap_gen.type) {
3069 strncpy(pos, " type=qrcode", end - pos);
3070 STR_CUR_TO_END(pos);
3071 }
3072
3073 if (params->bootstrap_gen.op_class &&
3074 params->bootstrap_gen.chan) {
3075 snprintf(pos, end - pos, " chan=%d/%d",
3076 params->bootstrap_gen.op_class,
3077 params->bootstrap_gen.chan);
3078 STR_CUR_TO_END(pos);
3079 }
3080
3081 /* mac is mandatory, even if it is zero mac address */
3082 snprintf(pos, end - pos, " mac=%02x:%02x:%02x:%02x:%02x:%02x",
3083 params->bootstrap_gen.mac[0], params->bootstrap_gen.mac[1],
3084 params->bootstrap_gen.mac[2], params->bootstrap_gen.mac[3],
3085 params->bootstrap_gen.mac[4], params->bootstrap_gen.mac[5]);
3086 STR_CUR_TO_END(pos);
3087
3088 if (params->bootstrap_gen.curve) {
3089 snprintf(pos, end - pos, " curve=%s",
3090 dpp_params_to_args_curve(params->bootstrap_gen.curve));
3091 }
3092 break;
3093 case WIFI_DPP_BOOTSTRAP_GET_URI:
3094 snprintf(pos, end - pos, "DPP_BOOTSTRAP_GET_URI %d", params->id);
3095 break;
3096 case WIFI_DPP_SET_CONF_PARAM:
3097 strncpy(pos, "SET dpp_configurator_params", end - pos);
3098 STR_CUR_TO_END(pos);
3099
3100 if (params->configurator_set.peer) {
3101 snprintf(pos, end - pos, " peer=%d", params->configurator_set.peer);
3102 STR_CUR_TO_END(pos);
3103 }
3104
3105 if (params->configurator_set.conf) {
3106 snprintf(pos, end - pos, " conf=%s",
3107 dpp_params_to_args_conf(
3108 params->configurator_set.conf));
3109 STR_CUR_TO_END(pos);
3110 }
3111
3112 if (params->configurator_set.ssid[0]) {
3113 strncpy(pos, " ssid=", end - pos);
3114 STR_CUR_TO_END(pos);
3115 dpp_ssid_bin2str(pos, params->configurator_set.ssid,
3116 WIFI_SSID_MAX_LEN * 2);
3117 STR_CUR_TO_END(pos);
3118 }
3119
3120 if (params->configurator_set.configurator) {
3121 snprintf(pos, end - pos, " configurator=%d",
3122 params->configurator_set.configurator);
3123 STR_CUR_TO_END(pos);
3124 }
3125
3126 if (params->configurator_set.role) {
3127 snprintf(pos, end - pos, " role=%s",
3128 dpp_params_to_args_role(
3129 params->configurator_set.role));
3130 STR_CUR_TO_END(pos);
3131 }
3132
3133 if (params->configurator_set.curve) {
3134 snprintf(pos, end - pos, " curve=%s",
3135 dpp_params_to_args_curve(params->configurator_set.curve));
3136 STR_CUR_TO_END(pos);
3137 }
3138
3139 if (params->configurator_set.net_access_key_curve) {
3140 snprintf(pos, end - pos, " net_access_key_curve=%s",
3141 dpp_params_to_args_curve(
3142 params->configurator_set.net_access_key_curve));
3143 }
3144 break;
3145 case WIFI_DPP_SET_WAIT_RESP_TIME:
3146 snprintf(pos, end - pos, "SET dpp_resp_wait_time %d",
3147 params->dpp_resp_wait_time);
3148 break;
3149 case WIFI_DPP_RECONFIG:
3150 snprintf(pos, end - pos, "DPP_RECONFIG %d", params->network_id);
3151 break;
3152 default:
3153 wpa_printf(MSG_ERROR, "Unknown DPP action");
3154 return -EINVAL;
3155 }
3156
3157 return 0;
3158 }
3159
3160 int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
3161 {
3162 int ret;
3163 char *cmd = NULL;
3164
3165 if (params == NULL) {
3166 return -EINVAL;
3167 }
3168
3169 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
3170 if (cmd == NULL) {
3171 return -ENOMEM;
3172 }
3173
3174 /* leave one byte always be 0 */
3175 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
3176 if (ret) {
3177 os_free(cmd);
3178 return ret;
3179 }
3180
3181 wpa_printf(MSG_DEBUG, "wpa_cli %s", cmd);
3182 if (zephyr_wpa_cli_cmd_resp(cmd, params->resp)) {
3183 os_free(cmd);
3184 return -ENOEXEC;
3185 }
3186
3187 os_free(cmd);
3188 return 0;
3189 }
3190
3191 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
3192 int hapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
3193 {
3194 int ret;
3195 char *cmd = NULL;
3196
3197 if (params == NULL) {
3198 return -EINVAL;
3199 }
3200
3201 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
3202 if (cmd == NULL) {
3203 return -ENOMEM;
3204 }
3205
3206 /* leave one byte always be 0 */
3207 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
3208 if (ret) {
3209 os_free(cmd);
3210 return ret;
3211 }
3212
3213 wpa_printf(MSG_DEBUG, "hostapd_cli %s", cmd);
3214 if (zephyr_hostapd_cli_cmd_resp(cmd, params->resp)) {
3215 os_free(cmd);
3216 return -ENOEXEC;
3217 }
3218
3219 os_free(cmd);
3220 return 0;
3221 }
3222 #endif /* CONFIG_WIFI_NM_HOSTAPD_AP */
3223 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
3224