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 #include <zephyr/sys/util.h>
13
14 #include "includes.h"
15 #include "common.h"
16 #include "common/defs.h"
17 #include "common/ieee802_11_defs.h"
18 #include "common/ieee802_11_common.h"
19 #include "wpa_supplicant/config.h"
20 #include "wpa_supplicant_i.h"
21 #include "driver_i.h"
22
23 #include "supp_main.h"
24 #include "supp_api.h"
25 #include "wpa_cli_zephyr.h"
26 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
27 #include "eap_peer/eap.h"
28 #endif
29 #include "supp_events.h"
30 #include "hostapd.h"
31 #include "hapd_api.h"
32 #include "wpa_supplicant/bss.h"
33
34 extern struct k_sem wpa_supplicant_ready_sem;
35 extern struct wpa_global *global;
36
37 /* save the last wifi connection parameters */
38 static struct wifi_connect_req_params last_wifi_conn_params;
39
40 enum requested_ops {
41 CONNECT = 0,
42 DISCONNECT,
43 WPS_PBC,
44 WPS_PIN,
45 };
46
47 enum status_thread_state {
48 STATUS_THREAD_STOPPED = 0,
49 STATUS_THREAD_RUNNING,
50 };
51
52 #define OP_STATUS_POLLING_INTERVAL 1
53
54 #define CONNECTION_SUCCESS 0
55 #define CONNECTION_FAILURE 1
56 #define CONNECTION_TERMINATED 2
57
58 #define DISCONNECT_TIMEOUT_MS 5000
59
60 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
61 static struct wifi_enterprise_creds_params enterprise_creds;
62 #endif
63
64 K_MUTEX_DEFINE(wpa_supplicant_mutex);
65
66 extern struct k_work_q *get_workq(void);
67
68 struct wpa_supp_api_ctrl {
69 const struct device *dev;
70 enum requested_ops requested_op;
71 enum status_thread_state status_thread_state;
72 int connection_timeout; /* in seconds */
73 struct k_work_sync sync;
74 bool terminate;
75 };
76
77 static struct wpa_supp_api_ctrl wpas_api_ctrl;
78
79 static void supp_shell_connect_status(struct k_work *work);
80
81 static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work,
82 supp_shell_connect_status);
83
84 #define wpa_cli_cmd_v(cmd, ...) \
85 ({ \
86 bool status; \
87 \
88 if (zephyr_wpa_cli_cmd_v(wpa_s->ctrl_conn, cmd, ##__VA_ARGS__) < 0) { \
89 wpa_printf(MSG_ERROR, "Failed to execute wpa_cli command: %s", 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 #define WPA_SUPP_STATE_POLLING_MS 10
wait_for_disconnect_complete(const struct device * dev)126 static int wait_for_disconnect_complete(const struct device *dev)
127 {
128 int ret = 0;
129 int attempts = 0;
130 struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
131 unsigned int max_attempts = DISCONNECT_TIMEOUT_MS / WPA_SUPP_STATE_POLLING_MS;
132
133 if (!wpa_s) {
134 ret = -ENODEV;
135 wpa_printf(MSG_ERROR, "Failed to get wpa_s handle");
136 goto out;
137 }
138
139 while (wpa_s->wpa_state != WPA_DISCONNECTED) {
140 if (attempts++ > max_attempts) {
141 ret = -ETIMEDOUT;
142 wpa_printf(MSG_WARNING, "Failed to disconnect from network");
143 break;
144 }
145
146 k_sleep(K_MSEC(WPA_SUPP_STATE_POLLING_MS));
147 }
148 out:
149 return ret;
150 }
151
supp_shell_connect_status(struct k_work * work)152 static void supp_shell_connect_status(struct k_work *work)
153 {
154 static int seconds_counter;
155 int status = CONNECTION_SUCCESS;
156 int conn_result = CONNECTION_FAILURE;
157 struct wpa_supplicant *wpa_s;
158 struct wpa_supp_api_ctrl *ctrl = &wpas_api_ctrl;
159
160 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
161
162 if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) {
163 status = CONNECTION_TERMINATED;
164 goto out;
165 }
166
167 wpa_s = get_wpa_s_handle(ctrl->dev);
168 if (!wpa_s) {
169 status = CONNECTION_FAILURE;
170 goto out;
171 }
172
173 if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) {
174 if (ctrl->connection_timeout > 0 &&
175 seconds_counter++ > ctrl->connection_timeout) {
176 if (!wpa_cli_cmd_v("disconnect")) {
177 goto out;
178 }
179
180 conn_result = -ETIMEDOUT;
181 supplicant_send_wifi_mgmt_event(wpa_s->ifname,
182 NET_EVENT_WIFI_CMD_CONNECT_RESULT,
183 (void *)&conn_result, sizeof(int));
184 status = CONNECTION_FAILURE;
185 goto out;
186 }
187
188 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work,
189 K_SECONDS(OP_STATUS_POLLING_INTERVAL));
190 ctrl->status_thread_state = STATUS_THREAD_RUNNING;
191 k_mutex_unlock(&wpa_supplicant_mutex);
192 return;
193 }
194 out:
195 seconds_counter = 0;
196
197 ctrl->status_thread_state = STATUS_THREAD_STOPPED;
198 k_mutex_unlock(&wpa_supplicant_mutex);
199 }
200
get_mode_by_band(struct wpa_supplicant * wpa_s,uint8_t band)201 static struct hostapd_hw_modes *get_mode_by_band(struct wpa_supplicant *wpa_s, uint8_t band)
202 {
203 enum hostapd_hw_mode hw_mode;
204 bool is_6ghz = (band == WIFI_FREQ_BAND_6_GHZ) ? true : false;
205
206 if (band == WIFI_FREQ_BAND_2_4_GHZ) {
207 hw_mode = HOSTAPD_MODE_IEEE80211G;
208 } else if ((band == WIFI_FREQ_BAND_5_GHZ) ||
209 (band == WIFI_FREQ_BAND_6_GHZ)) {
210 hw_mode = HOSTAPD_MODE_IEEE80211A;
211 } else {
212 return NULL;
213 }
214
215 return get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, is_6ghz);
216 }
217
wpa_supp_supported_channels(struct wpa_supplicant * wpa_s,uint8_t band,char ** chan_list)218 static int wpa_supp_supported_channels(struct wpa_supplicant *wpa_s, uint8_t band, char **chan_list)
219 {
220 struct hostapd_hw_modes *mode = NULL;
221 int i;
222 int offset, retval;
223 int size;
224 char *_chan_list;
225
226 mode = get_mode_by_band(wpa_s, band);
227 if (!mode) {
228 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
229 return -EINVAL;
230 }
231
232 size = ((mode->num_channels) * CHAN_NUM_LEN) + 1;
233 _chan_list = os_malloc(size);
234 if (!_chan_list) {
235 wpa_printf(MSG_ERROR, "Mem alloc failed for channel list");
236 return -ENOMEM;
237 }
238
239 retval = 0;
240 offset = 0;
241 for (i = 0; i < mode->num_channels; i++) {
242 retval = snprintf(_chan_list + offset, CHAN_NUM_LEN, " %d",
243 mode->channels[i].freq);
244 offset += retval;
245 }
246 *chan_list = _chan_list;
247
248 return 0;
249 }
250
wpa_supp_band_chan_compat(struct wpa_supplicant * wpa_s,uint8_t band,uint8_t channel)251 static int wpa_supp_band_chan_compat(struct wpa_supplicant *wpa_s, uint8_t band, uint8_t channel)
252 {
253 struct hostapd_hw_modes *mode = NULL;
254 int i;
255
256 mode = get_mode_by_band(wpa_s, band);
257 if (!mode) {
258 wpa_printf(MSG_ERROR, "Unsupported or invalid band: %d", band);
259 return -EINVAL;
260 }
261
262 for (i = 0; i < mode->num_channels; i++) {
263 if (mode->channels[i].chan == channel) {
264 return mode->channels[i].freq;
265 }
266 }
267
268 wpa_printf(MSG_ERROR, "Channel %d not supported for band %d", channel, band);
269
270 return -EINVAL;
271 }
272
wpa_supp_restart_status_work(void)273 static inline void wpa_supp_restart_status_work(void)
274 {
275 /* Terminate synchronously */
276 wpas_api_ctrl.terminate = 1;
277 k_work_flush_delayable(&wpa_supp_status_work, &wpas_api_ctrl.sync);
278 wpas_api_ctrl.terminate = 0;
279
280 /* Start afresh */
281 k_work_reschedule_for_queue(get_workq(), &wpa_supp_status_work, K_MSEC(10));
282 }
283
chan_to_freq(int chan)284 static inline int chan_to_freq(int chan)
285 {
286 /* We use global channel list here and also use the widest
287 * op_class for 5GHz channels as there is no user input
288 * for these (yet).
289 */
290 int freq = -1;
291 int op_classes[] = {81, 82, 128};
292 int op_classes_size = ARRAY_SIZE(op_classes);
293
294 for (int i = 0; i < op_classes_size; i++) {
295 freq = ieee80211_chan_to_freq(NULL, op_classes[i], chan);
296 if (freq > 0) {
297 break;
298 }
299 }
300
301 if (freq <= 0) {
302 wpa_printf(MSG_ERROR, "Invalid channel %d", chan);
303 return -1;
304 }
305
306 return freq;
307 }
308
wpas_band_to_zephyr(enum wpa_radio_work_band band)309 enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band)
310 {
311 switch (band) {
312 case BAND_2_4_GHZ:
313 return WIFI_FREQ_BAND_2_4_GHZ;
314 case BAND_5_GHZ:
315 return WIFI_FREQ_BAND_5_GHZ;
316 default:
317 return WIFI_FREQ_BAND_UNKNOWN;
318 }
319 }
320
wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)321 enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt)
322 {
323 switch (key_mgmt) {
324 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
325 return WIFI_WPA3_ENTERPRISE_SUITEB;
326 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
327 return WIFI_WPA3_ENTERPRISE_SUITEB_192;
328 case WPA_KEY_MGMT_IEEE8021X_SHA256:
329 return WIFI_WPA3_ENTERPRISE_ONLY;
330 default:
331 return WIFI_WPA3_ENTERPRISE_NA;
332 }
333 }
334
wpas_key_mgmt_to_zephyr(bool is_hapd,void * config,int key_mgmt,int proto,int pwe)335 enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd, void *config, int key_mgmt,
336 int proto, int pwe)
337 {
338 switch (key_mgmt) {
339 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
340 case WPA_KEY_MGMT_IEEE8021X:
341 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
342 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
343 case WPA_KEY_MGMT_IEEE8021X_SHA256:
344 if (is_hapd) {
345 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
346 struct hostapd_bss_config *conf = (struct hostapd_bss_config *)config;
347
348 switch (conf->eap_user->methods[0].method) {
349 case WIFI_EAP_TYPE_PEAP:
350 if (conf->eap_user->next && conf->eap_user->next->phase2) {
351 switch (conf->eap_user->next->methods[0].method) {
352 case WIFI_EAP_TYPE_MSCHAPV2:
353 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
354 case WIFI_EAP_TYPE_GTC:
355 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
356 case WIFI_EAP_TYPE_TLS:
357 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
358 }
359 }
360 case WIFI_EAP_TYPE_TTLS:
361 if (conf->eap_user->next && conf->eap_user->next->phase2) {
362 if (conf->eap_user->next->ttls_auth & 0x1E) {
363 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
364 }
365 }
366 }
367 #endif
368 } else {
369 struct wpa_ssid *ssid = (struct wpa_ssid *)config;
370
371 switch (ssid->eap.eap_methods->method) {
372 case WIFI_EAP_TYPE_TTLS:
373 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
374 os_strlen(ssid->eap.phase2))) {
375 return WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2;
376 }
377 case WIFI_EAP_TYPE_PEAP:
378 if (!os_memcmp(ssid->eap.phase2, "auth=MSCHAPV2",
379 os_strlen(ssid->eap.phase2))) {
380 return WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2;
381 } else if (!os_memcmp(ssid->eap.phase2, "auth=GTC",
382 os_strlen(ssid->eap.phase2))) {
383 return WIFI_SECURITY_TYPE_EAP_PEAP_GTC;
384 } else if (!os_memcmp(ssid->eap.phase2, "auth=TLS",
385 os_strlen(ssid->eap.phase2))) {
386 return WIFI_SECURITY_TYPE_EAP_PEAP_TLS;
387 }
388 }
389 }
390 return WIFI_SECURITY_TYPE_EAP_TLS;
391 #endif
392 case WPA_KEY_MGMT_NONE:
393 return WIFI_SECURITY_TYPE_NONE;
394 case WPA_KEY_MGMT_PSK:
395 if (proto == WPA_PROTO_RSN) {
396 return WIFI_SECURITY_TYPE_PSK;
397 } else {
398 return WIFI_SECURITY_TYPE_WPA_PSK;
399 }
400 case WPA_KEY_MGMT_PSK_SHA256:
401 return WIFI_SECURITY_TYPE_PSK_SHA256;
402 case WPA_KEY_MGMT_SAE:
403 if (IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3)) {
404 if (pwe == 1) {
405 return WIFI_SECURITY_TYPE_SAE_H2E;
406 } else if (pwe == 2) {
407 return WIFI_SECURITY_TYPE_SAE_AUTO;
408 } else {
409 return WIFI_SECURITY_TYPE_SAE_HNP;
410 }
411 }
412 return WIFI_SECURITY_TYPE_UNKNOWN;
413 case WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_PSK:
414 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK:
415 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK_SHA256:
416 case WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_PSK:
417 return WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL;
418 case WPA_KEY_MGMT_FT_PSK:
419 return WIFI_SECURITY_TYPE_FT_PSK;
420 case WPA_KEY_MGMT_FT_SAE:
421 if (IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3)) {
422 return WIFI_SECURITY_TYPE_FT_SAE;
423 }
424 return WIFI_SECURITY_TYPE_UNKNOWN;
425 case WPA_KEY_MGMT_FT_IEEE8021X:
426 return WIFI_SECURITY_TYPE_FT_EAP;
427 case WPA_KEY_MGMT_DPP:
428 return WIFI_SECURITY_TYPE_DPP;
429 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
430 return WIFI_SECURITY_TYPE_FT_EAP_SHA384;
431 case WPA_KEY_MGMT_SAE_EXT_KEY:
432 if (IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3)) {
433 return WIFI_SECURITY_TYPE_SAE_EXT_KEY;
434 }
435 return WIFI_SECURITY_TYPE_UNKNOWN;
436 case WPA_KEY_MGMT_DPP | WPA_KEY_MGMT_PSK:
437 return WIFI_SECURITY_TYPE_DPP;
438 default:
439 return WIFI_SECURITY_TYPE_UNKNOWN;
440 }
441 }
442
443 #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)444 static int wpas_config_process_blob(struct wpa_config *config, char *name, uint8_t *data,
445 uint32_t data_len)
446 {
447 struct wpa_config_blob *blob;
448
449 if (!data || !data_len) {
450 return -1;
451 }
452
453 blob = os_zalloc(sizeof(*blob));
454 if (blob == NULL) {
455 return -1;
456 }
457
458 blob->data = os_zalloc(data_len);
459 if (blob->data == NULL) {
460 os_free(blob);
461 return -1;
462 }
463
464 blob->name = os_strdup(name);
465
466 if (blob->name == NULL) {
467 wpa_config_free_blob(blob);
468 return -1;
469 }
470
471 os_memcpy(blob->data, data, data_len);
472 blob->len = data_len;
473
474 wpa_config_set_blob(config, blob);
475
476 return 0;
477 }
478 #endif
479
480 #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
481 defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
supplicant_add_enterprise_creds(const struct device * dev,struct wifi_enterprise_creds_params * creds)482 int supplicant_add_enterprise_creds(const struct device *dev,
483 struct wifi_enterprise_creds_params *creds)
484 {
485 int ret = 0;
486
487 if (!creds) {
488 ret = -1;
489 wpa_printf(MSG_ERROR, "enterprise creds is NULL");
490 goto out;
491 }
492
493 memcpy((void *)&enterprise_creds, (void *)creds,
494 sizeof(struct wifi_enterprise_creds_params));
495
496 out:
497 return ret;
498 }
499
500 static const struct wifi_cipher_desc ciphers[] = {
501 {WPA_CAPA_ENC_GCMP_256, "GCMP-256"},
502 {WPA_CAPA_ENC_CCMP, "CCMP"},
503 {WPA_CAPA_ENC_GCMP, "GCMP"},
504 };
505
506 static const struct wifi_cipher_desc ciphers_group_mgmt[] = {
507 {WPA_CAPA_ENC_BIP, "AES-128-CMAC"},
508 {WPA_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128"},
509 {WPA_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256"},
510 };
511
512 static struct wifi_eap_config eap_config[] = {
513 {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
514 {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP",
515 "auth=MSCHAPV2"},
516 {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP",
517 "auth=GTC"},
518 {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS",
519 "auth=MSCHAPV2"},
520 {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP",
521 "auth=TLS tls_disable_tlsv1_3=1"},
522 };
523
process_cipher_config(struct wifi_connect_req_params * params,struct wifi_eap_cipher_config * cipher_config)524 int process_cipher_config(struct wifi_connect_req_params *params,
525 struct wifi_eap_cipher_config *cipher_config)
526 {
527 unsigned int cipher_capa;
528 unsigned int gropu_mgmt_cipher_capa;
529 unsigned int index;
530
531 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB) {
532 cipher_capa = WPA_CAPA_ENC_GCMP;
533 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_128;
534 cipher_config->key_mgmt = "WPA-EAP-SUITE-B";
535 cipher_config->openssl_ciphers = "SUITEB128";
536 cipher_config->tls_flags = "[SUITEB]";
537 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
538 cipher_capa = WPA_CAPA_ENC_GCMP_256;
539 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP_GMAC_256;
540 if (params->ft_used) {
541 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384";
542 } else {
543 cipher_config->key_mgmt = "WPA-EAP-SUITE-B-192";
544 }
545 cipher_config->openssl_ciphers = "SUITEB192";
546 cipher_config->tls_flags = "[SUITEB]";
547 } else if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_ONLY) {
548 cipher_capa = WPA_CAPA_ENC_CCMP;
549 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
550 cipher_config->key_mgmt = "WPA-EAP-SHA256";
551 } else {
552 cipher_capa = WPA_CAPA_ENC_CCMP;
553 gropu_mgmt_cipher_capa = WPA_CAPA_ENC_BIP;
554 if (params->ft_used) {
555 cipher_config->key_mgmt = "WPA-EAP FT-EAP";
556 } else {
557 cipher_config->key_mgmt = "WPA-EAP";
558 }
559 }
560
561 for (index = 0; index < ARRAY_SIZE(ciphers); index++) {
562 if (cipher_capa == ciphers[index].capa) {
563 cipher_config->group_cipher = ciphers[index].name;
564 cipher_config->pairwise_cipher = ciphers[index].name;
565 break;
566 }
567 }
568
569 if (index == ARRAY_SIZE(ciphers)) {
570 wpa_printf(MSG_ERROR, "Get ciphers error");
571 goto out;
572 }
573
574 for (index = 0; index < ARRAY_SIZE(ciphers_group_mgmt); index++) {
575 if (gropu_mgmt_cipher_capa == ciphers_group_mgmt[index].capa) {
576 cipher_config->group_mgmt_cipher = ciphers_group_mgmt[index].name;
577 break;
578 }
579 }
580
581 if (index == ARRAY_SIZE(ciphers_group_mgmt)) {
582 wpa_printf(MSG_ERROR, "Get group mgmt ciphers error");
583 goto out;
584 }
585
586 return 0;
587 out:
588 return -EINVAL;
589 }
590
is_eap_valid_security(int security)591 int is_eap_valid_security(int security)
592 {
593 return (security == WIFI_SECURITY_TYPE_EAP_TLS ||
594 security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
595 security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
596 security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
597 security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS);
598 }
599 #endif
600
601 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
wpas_remove_certs(struct wpa_supplicant * wpa_s)602 static void wpas_remove_certs(struct wpa_supplicant *wpa_s)
603 {
604 wpa_config_remove_blob(wpa_s->conf, "ca_cert");
605 wpa_config_remove_blob(wpa_s->conf, "client_cert");
606 wpa_config_remove_blob(wpa_s->conf, "private_key");
607 wpa_config_remove_blob(wpa_s->conf, "ca_cert2");
608 wpa_config_remove_blob(wpa_s->conf, "client_cert2");
609 wpa_config_remove_blob(wpa_s->conf, "private_key2");
610 }
611 #endif
612
wpas_add_and_config_network(struct wpa_supplicant * wpa_s,struct wifi_connect_req_params * params,bool mode_ap)613 static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s,
614 struct wifi_connect_req_params *params,
615 bool mode_ap)
616 {
617 struct add_network_resp resp = {0};
618 char *chan_list = NULL;
619 struct net_eth_addr mac = {0};
620 int ret = 0;
621 uint8_t ssid_null_terminated[WIFI_SSID_MAX_LEN + 1];
622 uint8_t psk_null_terminated[WIFI_PSK_MAX_LEN + 1];
623 uint8_t sae_null_terminated[WIFI_SAE_PSWD_MAX_LEN + 1];
624 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
625 struct wifi_eap_cipher_config cipher_config = {NULL, "DEFAULT:!EXP:!LOW", "CCMP",
626 "CCMP", "AES-128-CMAC", NULL};
627 char *method = NULL;
628 char phase1[128] = {0};
629 char *phase2 = NULL;
630 unsigned int index;
631
632 wpas_remove_certs(wpa_s);
633 #endif
634
635 if (!wpa_cli_cmd_v("remove_network all")) {
636 goto out;
637 }
638
639 ret = z_wpa_ctrl_add_network(wpa_s->ctrl_conn, &resp);
640 if (ret) {
641 wpa_printf(MSG_ERROR, "Failed to add network");
642 goto out;
643 }
644
645 wpa_printf(MSG_DEBUG, "NET added: %d", resp.network_id);
646
647 if (mode_ap) {
648 if (!wpa_cli_cmd_v("set_network %d mode 2", resp.network_id)) {
649 goto out;
650 }
651 }
652
653 if (params->ssid_length > WIFI_SSID_MAX_LEN) {
654 wpa_printf(MSG_ERROR, "SSID too long (max %d characters)", WIFI_SSID_MAX_LEN);
655 goto out;
656 }
657
658 strncpy(ssid_null_terminated, params->ssid, WIFI_SSID_MAX_LEN);
659 ssid_null_terminated[params->ssid_length] = '\0';
660
661 if (!wpa_cli_cmd_v("set_network %d ssid \"%s\"",
662 resp.network_id, ssid_null_terminated)) {
663 goto out;
664 }
665
666 if (!wpa_cli_cmd_v("set_network %d scan_ssid 1", resp.network_id)) {
667 goto out;
668 }
669
670 if (!wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id)) {
671 goto out;
672 }
673
674 if (!wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id)) {
675 goto out;
676 }
677
678 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
679 ret = wpa_supp_supported_channels(wpa_s, params->band, &chan_list);
680 if (ret < 0) {
681 goto rem_net;
682 }
683
684 if (chan_list) {
685 if (!wpa_cli_cmd_v("set_network %d scan_freq%s", resp.network_id,
686 chan_list)) {
687 os_free(chan_list);
688 goto out;
689 }
690
691 os_free(chan_list);
692 }
693 }
694
695 if (params->security != WIFI_SECURITY_TYPE_NONE) {
696 if (params->psk) {
697 if ((params->psk_length < WIFI_PSK_MIN_LEN) ||
698 (params->psk_length > WIFI_PSK_MAX_LEN)) {
699 wpa_printf(MSG_ERROR,
700 "Passphrase should be in range (%d-%d) characters",
701 WIFI_PSK_MIN_LEN, WIFI_PSK_MAX_LEN);
702 goto out;
703 }
704 strncpy(psk_null_terminated, params->psk, WIFI_PSK_MAX_LEN);
705 psk_null_terminated[params->psk_length] = '\0';
706 }
707
708 /* SAP - only open and WPA2-PSK are supported for now */
709 if (mode_ap && params->security != WIFI_SECURITY_TYPE_PSK) {
710 ret = -1;
711 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
712 params->security);
713 goto rem_net;
714 }
715
716 /* Except for WPA-PSK, rest all are under WPA2 */
717 if (params->security != WIFI_SECURITY_TYPE_WPA_PSK) {
718 if (!wpa_cli_cmd_v("set_network %d proto RSN",
719 resp.network_id)) {
720 goto out;
721 }
722 }
723
724 if (IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3) &&
725 (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
726 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
727 params->security == WIFI_SECURITY_TYPE_SAE_AUTO ||
728 params->security == WIFI_SECURITY_TYPE_SAE_EXT_KEY)) {
729 if (params->sae_password) {
730 if ((params->sae_password_length < WIFI_PSK_MIN_LEN) ||
731 (params->sae_password_length > WIFI_SAE_PSWD_MAX_LEN)) {
732 wpa_printf(MSG_ERROR,
733 "Passphrase should be in range (%d-%d) characters",
734 WIFI_PSK_MIN_LEN, WIFI_SAE_PSWD_MAX_LEN);
735 goto out;
736 }
737 strncpy(sae_null_terminated, params->sae_password,
738 WIFI_SAE_PSWD_MAX_LEN);
739 sae_null_terminated[params->sae_password_length] = '\0';
740 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
741 resp.network_id, sae_null_terminated)) {
742 goto out;
743 }
744 } else {
745 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
746 resp.network_id, psk_null_terminated)) {
747 goto out;
748 }
749 }
750
751 if (!wpa_cli_cmd_v("set sae_pwe %d",
752 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
753 ? 1
754 : ((params->security == WIFI_SECURITY_TYPE_SAE_HNP)
755 ? 0
756 : 2))) {
757 goto out;
758 }
759
760 if (params->security != WIFI_SECURITY_TYPE_SAE_EXT_KEY) {
761 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE%s", resp.network_id,
762 params->ft_used ? " FT-SAE" : "")) {
763 goto out;
764 }
765 } else {
766 if (!wpa_cli_cmd_v("set_network %d key_mgmt SAE-EXT-KEY%s",
767 resp.network_id,
768 params->ft_used ? " FT-SAE-EXT-KEY" : "")) {
769 goto out;
770 }
771 }
772
773 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
774 goto out;
775 }
776
777 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) {
778 goto out;
779 }
780 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
781 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
782 resp.network_id, psk_null_terminated)) {
783 goto out;
784 }
785
786 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256",
787 resp.network_id)) {
788 goto out;
789 }
790
791 if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) {
792 goto out;
793 }
794
795 if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) {
796 goto out;
797 }
798 } else if (params->security == WIFI_SECURITY_TYPE_PSK ||
799 params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
800 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"",
801 resp.network_id, psk_null_terminated)) {
802 goto out;
803 }
804
805 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK%s",
806 resp.network_id, params->ft_used ? " FT-PSK" : "")) {
807 goto out;
808 }
809
810 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
811 if (!wpa_cli_cmd_v("set_network %d proto WPA",
812 resp.network_id)) {
813 goto out;
814 }
815 }
816
817 if (!wpa_cli_cmd_v("set_network %d group TKIP CCMP", resp.network_id)) {
818 goto out;
819 }
820
821 if (!wpa_cli_cmd_v("set_network %d pairwise TKIP CCMP", resp.network_id)) {
822 goto out;
823 }
824 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
825 if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id,
826 psk_null_terminated)) {
827 goto out;
828 }
829
830 if (IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3)) {
831 if (params->sae_password) {
832 if ((params->sae_password_length < WIFI_PSK_MIN_LEN) ||
833 (params->sae_password_length > WIFI_SAE_PSWD_MAX_LEN)) {
834 wpa_printf(MSG_ERROR,
835 "Passphrase should be in range (%d-%d) characters",
836 WIFI_PSK_MIN_LEN, WIFI_SAE_PSWD_MAX_LEN);
837 goto out;
838 }
839 strncpy(sae_null_terminated, params->sae_password,
840 WIFI_SAE_PSWD_MAX_LEN);
841 sae_null_terminated[params->sae_password_length] = '\0';
842 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
843 resp.network_id, sae_null_terminated)) {
844 goto out;
845 }
846 } else {
847 if (!wpa_cli_cmd_v("set_network %d sae_password \"%s\"",
848 resp.network_id, psk_null_terminated)) {
849 goto out;
850 }
851 }
852
853 if (!wpa_cli_cmd_v("set sae_pwe 2")) {
854 goto out;
855 }
856
857 if (!wpa_cli_cmd_v(
858 "set_network %d key_mgmt WPA-PSK WPA-PSK-SHA256 SAE",
859 resp.network_id)) {
860 goto out;
861 }
862 } else {
863 if (!wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK WPA-PSK-SHA256",
864 resp.network_id)) {
865 goto out;
866 }
867 }
868
869 if (!wpa_cli_cmd_v("set_network %d proto WPA RSN", resp.network_id)) {
870 goto out;
871 }
872
873 if (!wpa_cli_cmd_v("set_network %d group TKIP CCMP", resp.network_id)) {
874 goto out;
875 }
876
877 if (!wpa_cli_cmd_v("set_network %d pairwise TKIP CCMP", resp.network_id)) {
878 goto out;
879 }
880 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
881 } else if (is_eap_valid_security(params->security)) {
882 if (process_cipher_config(params, &cipher_config)) {
883 goto out;
884 }
885
886 for (index = 0; index < ARRAY_SIZE(eap_config); index++) {
887 if (params->security == eap_config[index].type) {
888 method = eap_config[index].method;
889 phase2 = eap_config[index].phase2;
890 break;
891 }
892 }
893
894 if (index == ARRAY_SIZE(eap_config)) {
895 wpa_printf(MSG_ERROR, "Get eap method error with security type: %d",
896 params->security);
897 goto out;
898 }
899
900 if (params->wpa3_ent_mode == WIFI_WPA3_ENTERPRISE_SUITEB_192) {
901 if (params->TLS_cipher == WIFI_EAP_TLS_ECC_P384) {
902 if (!wpa_cli_cmd_v("set_network %d openssl_ciphers \"%s\"",
903 resp.network_id,
904 cipher_config.openssl_ciphers)) {
905 goto out;
906 }
907 } else if (params->TLS_cipher == WIFI_EAP_TLS_RSA_3K) {
908 snprintf(phase1, sizeof(phase1), "tls_suiteb=1 "
909 "tls_disable_tlsv1_3=1");
910 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"",
911 resp.network_id, &phase1[0])) {
912 goto out;
913 }
914 }
915 }
916
917 if (!wpa_cli_cmd_v("set_network %d key_mgmt %s", resp.network_id,
918 cipher_config.key_mgmt)) {
919 goto out;
920 }
921
922 if (!wpa_cli_cmd_v("set openssl_ciphers \"%s\"",
923 cipher_config.openssl_ciphers)) {
924 goto out;
925 }
926
927 if (!wpa_cli_cmd_v("set_network %d group %s", resp.network_id,
928 cipher_config.group_cipher)) {
929 goto out;
930 }
931
932 if (!wpa_cli_cmd_v("set_network %d pairwise %s", resp.network_id,
933 cipher_config.pairwise_cipher)) {
934 goto out;
935 }
936
937 if (!wpa_cli_cmd_v("set_network %d group_mgmt %s", resp.network_id,
938 cipher_config.group_mgmt_cipher)) {
939 goto out;
940 }
941
942 if (!wpa_cli_cmd_v("set_network %d proto RSN",
943 resp.network_id)) {
944 goto out;
945 }
946
947 if (method != NULL) {
948 if (!wpa_cli_cmd_v("set_network %d eap %s", resp.network_id,
949 method)) {
950 goto out;
951 }
952 }
953
954 if (params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
955 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
956 params->security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) {
957 snprintk(phase1, sizeof(phase1),
958 "peapver=%d peaplabel=0 crypto_binding=0",
959 params->eap_ver);
960
961 if (!wpa_cli_cmd_v("set_network %d phase1 \"%s\"", resp.network_id,
962 &phase1[0])) {
963 goto out;
964 }
965 }
966
967 if (phase2 != NULL) {
968 if (!wpa_cli_cmd_v("set_network %d phase2 \"%s\"", resp.network_id,
969 phase2)) {
970 goto out;
971 }
972 }
973
974 if (params->eap_id_length > 0) {
975 if (!wpa_cli_cmd_v("set_network %d identity \"%s\"",
976 resp.network_id, params->eap_identity)) {
977 goto out;
978 }
979 }
980
981 if (params->eap_passwd_length > 0) {
982 if (!wpa_cli_cmd_v("set_network %d password \"%s\"",
983 resp.network_id, params->eap_password)) {
984 goto out;
985 }
986 }
987
988 if (!wpa_cli_cmd_v("set_network %d anonymous_identity \"%s\"",
989 resp.network_id, params->anon_id)) {
990 goto out;
991 }
992
993 if (params->server_cert_domain_exact_len > 0) {
994 if (!wpa_cli_cmd_v("set_network %d domain_match \"%s\"",
995 resp.network_id,
996 params->server_cert_domain_exact)) {
997 goto out;
998 }
999 }
1000
1001 if (params->server_cert_domain_suffix_len > 0) {
1002 if (!wpa_cli_cmd_v("set_network %d domain_suffix_match \"%s\"",
1003 resp.network_id,
1004 params->server_cert_domain_suffix)) {
1005 goto out;
1006 }
1007 }
1008
1009 if (false == ((params->security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
1010 params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) &&
1011 (!params->verify_peer_cert))) {
1012 if (wpas_config_process_blob(wpa_s->conf, "ca_cert",
1013 enterprise_creds.ca_cert,
1014 enterprise_creds.ca_cert_len)) {
1015 goto out;
1016 }
1017
1018 if (!wpa_cli_cmd_v("set_network %d ca_cert \"blob://ca_cert\"",
1019 resp.network_id)) {
1020 goto out;
1021 }
1022 }
1023
1024 if (wpas_config_process_blob(wpa_s->conf, "client_cert",
1025 enterprise_creds.client_cert,
1026 enterprise_creds.client_cert_len)) {
1027 goto out;
1028 }
1029
1030 if (!wpa_cli_cmd_v("set_network %d client_cert \"blob://client_cert\"",
1031 resp.network_id)) {
1032 goto out;
1033 }
1034
1035 if (wpas_config_process_blob(wpa_s->conf, "private_key",
1036 enterprise_creds.client_key,
1037 enterprise_creds.client_key_len)) {
1038 goto out;
1039 }
1040
1041 if (!wpa_cli_cmd_v("set_network %d private_key \"blob://private_key\"",
1042 resp.network_id)) {
1043 goto out;
1044 }
1045
1046 if (!wpa_cli_cmd_v("set_network %d private_key_passwd \"%s\"",
1047 resp.network_id, params->key_passwd)) {
1048 goto out;
1049 }
1050
1051 if (wpas_config_process_blob(wpa_s->conf, "ca_cert2",
1052 enterprise_creds.ca_cert2,
1053 enterprise_creds.ca_cert2_len)) {
1054 goto out;
1055 }
1056
1057 if (!wpa_cli_cmd_v("set_network %d ca_cert2 \"blob://ca_cert2\"",
1058 resp.network_id)) {
1059 goto out;
1060 }
1061
1062 if (wpas_config_process_blob(wpa_s->conf, "client_cert2",
1063 enterprise_creds.client_cert2,
1064 enterprise_creds.client_cert2_len)) {
1065 goto out;
1066 }
1067
1068 if (!wpa_cli_cmd_v("set_network %d client_cert2 \"blob://client_cert2\"",
1069 resp.network_id)) {
1070 goto out;
1071 }
1072
1073 if (wpas_config_process_blob(wpa_s->conf, "private_key2",
1074 enterprise_creds.client_key2,
1075 enterprise_creds.client_key2_len)) {
1076 goto out;
1077 }
1078
1079 if (!wpa_cli_cmd_v("set_network %d private_key2 \"blob://private_key2\"",
1080 resp.network_id)) {
1081 goto out;
1082 }
1083
1084 if (!wpa_cli_cmd_v("set_network %d private_key2_passwd \"%s\"",
1085 resp.network_id, params->key2_passwd)) {
1086 goto out;
1087 }
1088 #endif
1089 } else {
1090 ret = -1;
1091 wpa_printf(MSG_ERROR, "Unsupported security type: %d",
1092 params->security);
1093 goto rem_net;
1094 }
1095
1096 if (params->mfp) {
1097 if (!wpa_cli_cmd_v("set_network %d ieee80211w %d",
1098 resp.network_id, params->mfp)) {
1099 goto out;
1100 }
1101 }
1102 }
1103
1104 if (params->channel != WIFI_CHANNEL_ANY) {
1105 int freq;
1106
1107 if (params->band != WIFI_FREQ_BAND_UNKNOWN) {
1108 freq = wpa_supp_band_chan_compat(wpa_s, params->band, params->channel);
1109 if (freq < 0) {
1110 goto rem_net;
1111 }
1112 } else {
1113 freq = chan_to_freq(params->channel);
1114 if (freq < 0) {
1115 ret = -1;
1116 wpa_printf(MSG_ERROR, "Invalid channel %d",
1117 params->channel);
1118 goto rem_net;
1119 }
1120 }
1121
1122 if (mode_ap) {
1123 if (!wpa_cli_cmd_v("set_network %d frequency %d",
1124 resp.network_id, freq)) {
1125 goto out;
1126 }
1127 } else {
1128 if (!wpa_cli_cmd_v("set_network %d scan_freq %d",
1129 resp.network_id, freq)) {
1130 goto out;
1131 }
1132 }
1133 }
1134
1135 memcpy((void *)&mac, params->bssid, WIFI_MAC_ADDR_LEN);
1136 if (net_eth_is_addr_broadcast(&mac) ||
1137 net_eth_is_addr_multicast(&mac)) {
1138 wpa_printf(MSG_ERROR, "Invalid BSSID. Configuration "
1139 "of multicast or broadcast MAC is not allowed.");
1140 ret = -EINVAL;
1141 goto rem_net;
1142 }
1143
1144 if (!net_eth_is_addr_unspecified(&mac)) {
1145 char bssid_str[MAC_STR_LEN] = {0};
1146
1147 snprintf(bssid_str, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
1148 params->bssid[0], params->bssid[1], params->bssid[2],
1149 params->bssid[3], params->bssid[4], params->bssid[5]);
1150
1151 if (!wpa_cli_cmd_v("set_network %d bssid %s",
1152 resp.network_id, bssid_str)) {
1153 goto out;
1154 }
1155 }
1156
1157 /* enable and select network */
1158 if (!wpa_cli_cmd_v("enable_network %d", resp.network_id)) {
1159 goto out;
1160 }
1161
1162 if (!wpa_cli_cmd_v("select_network %d", resp.network_id)) {
1163 goto out;
1164 }
1165
1166 memset(&last_wifi_conn_params, 0, sizeof(struct wifi_connect_req_params));
1167 memcpy((void *)&last_wifi_conn_params, params, sizeof(struct wifi_connect_req_params));
1168 return 0;
1169
1170 rem_net:
1171 if (!wpa_cli_cmd_v("remove_network %d", resp.network_id)) {
1172 goto out;
1173 }
1174
1175 out:
1176 return ret;
1177 }
1178
wpas_disconnect_network(const struct device * dev,int cur_mode)1179 static int wpas_disconnect_network(const struct device *dev, int cur_mode)
1180 {
1181 struct net_if *iface = net_if_lookup_by_dev(dev);
1182 struct wpa_supplicant *wpa_s;
1183 bool is_ap = false;
1184 int ret = 0;
1185
1186 if (!iface) {
1187 ret = -ENOENT;
1188 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1189 return ret;
1190 }
1191
1192 wpa_s = get_wpa_s_handle(dev);
1193 if (!wpa_s) {
1194 ret = -1;
1195 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1196 goto out;
1197 }
1198
1199 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1200
1201 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != cur_mode) {
1202 ret = -EBUSY;
1203 wpa_printf(MSG_ERROR, "Interface %s is not in %s mode", dev->name,
1204 cur_mode == WPAS_MODE_INFRA ? "STA" : "AP");
1205 goto out;
1206 }
1207
1208 is_ap = (cur_mode == WPAS_MODE_AP);
1209
1210 wpas_api_ctrl.dev = dev;
1211 wpas_api_ctrl.requested_op = DISCONNECT;
1212
1213 if (!wpa_cli_cmd_v("disconnect")) {
1214 goto out;
1215 }
1216
1217 out:
1218 k_mutex_unlock(&wpa_supplicant_mutex);
1219
1220 if (ret) {
1221 wpa_printf(MSG_ERROR, "Disconnect failed: %s", strerror(-ret));
1222 return ret;
1223 }
1224
1225 wpa_supp_restart_status_work();
1226
1227 ret = wait_for_disconnect_complete(dev);
1228 #ifdef CONFIG_AP
1229 if (is_ap) {
1230 supplicant_send_wifi_mgmt_ap_status(wpa_s,
1231 NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT,
1232 ret == 0 ? WIFI_STATUS_AP_SUCCESS : WIFI_STATUS_AP_FAIL);
1233 } else {
1234 #else
1235 {
1236 #endif /* CONFIG_AP */
1237 wifi_mgmt_raise_disconnect_complete_event(iface, ret);
1238 }
1239
1240 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1241 wpas_remove_certs(wpa_s);
1242 #endif
1243
1244 if (!wpa_cli_cmd_v("remove_network all")) {
1245 wpa_printf(MSG_ERROR, "Failed to remove all networks");
1246 }
1247
1248 return ret;
1249 }
1250
1251 /* Public API */
1252 int supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params)
1253 {
1254 struct wpa_supplicant *wpa_s;
1255 int ret = 0;
1256
1257 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
1258 wpa_printf(MSG_ERROR,
1259 "Interface %s is down, dropping connect",
1260 dev->name);
1261 return -1;
1262 }
1263
1264 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1265
1266 wpa_s = get_wpa_s_handle(dev);
1267 if (!wpa_s) {
1268 ret = -1;
1269 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1270 goto out;
1271 }
1272
1273 /* Allow connect in STA mode only even if we are connected already */
1274 if (wpa_s->current_ssid && wpa_s->current_ssid->mode != WPAS_MODE_INFRA) {
1275 ret = -EBUSY;
1276 wpa_printf(MSG_ERROR, "Interface %s is not in STA mode", dev->name);
1277 goto out;
1278 }
1279
1280 ret = wpas_add_and_config_network(wpa_s, params, false);
1281 if (ret) {
1282 wpa_printf(MSG_ERROR, "Failed to add and configure network for STA mode: %d", ret);
1283 goto out;
1284 }
1285
1286 wpas_api_ctrl.dev = dev;
1287 wpas_api_ctrl.requested_op = CONNECT;
1288 wpas_api_ctrl.connection_timeout = params->timeout;
1289
1290 out:
1291 k_mutex_unlock(&wpa_supplicant_mutex);
1292
1293 if (!ret) {
1294 wpa_supp_restart_status_work();
1295 }
1296
1297 return ret;
1298 }
1299
1300 int supplicant_disconnect(const struct device *dev)
1301 {
1302 return wpas_disconnect_network(dev, WPAS_MODE_INFRA);
1303 }
1304
1305 enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option)
1306 {
1307 switch (supp_mfp_option) {
1308 case NO_MGMT_FRAME_PROTECTION:
1309 return WIFI_MFP_DISABLE;
1310 case MGMT_FRAME_PROTECTION_OPTIONAL:
1311 return WIFI_MFP_OPTIONAL;
1312 case MGMT_FRAME_PROTECTION_REQUIRED:
1313 return WIFI_MFP_REQUIRED;
1314 default:
1315 wpa_printf(MSG_ERROR, "Invalid mfp mapping %d", supp_mfp_option);
1316 break;
1317 }
1318
1319 return WIFI_MFP_DISABLE;
1320 }
1321
1322 static enum wifi_iface_mode get_iface_mode(enum wpas_mode supp_mode)
1323 {
1324 switch (supp_mode) {
1325 case WPAS_MODE_INFRA:
1326 return WIFI_MODE_INFRA;
1327 case WPAS_MODE_IBSS:
1328 return WIFI_MODE_IBSS;
1329 case WPAS_MODE_AP:
1330 return WIFI_MODE_AP;
1331 case WPAS_MODE_P2P_GO:
1332 return WIFI_MODE_P2P_GO;
1333 case WPAS_MODE_P2P_GROUP_FORMATION:
1334 return WIFI_MODE_P2P_GROUP_FORMATION;
1335 case WPAS_MODE_MESH:
1336 return WIFI_MODE_MESH;
1337 default:
1338 break;
1339 }
1340
1341 return WIFI_MODE_UNKNOWN;
1342 }
1343
1344 int supplicant_status(const struct device *dev, struct wifi_iface_status *status)
1345 {
1346 struct net_if *iface = net_if_lookup_by_dev(dev);
1347 struct wpa_supplicant *wpa_s;
1348 int ret = -1;
1349 struct wpa_signal_info *si = NULL;
1350 struct wpa_conn_info *conn_info = NULL;
1351
1352 if (!iface) {
1353 ret = -ENOENT;
1354 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
1355 return ret;
1356 }
1357
1358 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1359
1360 wpa_s = get_wpa_s_handle(dev);
1361 if (!wpa_s) {
1362 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1363 goto out;
1364 }
1365
1366 si = os_zalloc(sizeof(struct wpa_signal_info));
1367 if (!si) {
1368 wpa_printf(MSG_ERROR, "Failed to allocate memory for signal info");
1369 goto out;
1370 }
1371
1372 status->state = wpa_s->wpa_state; /* 1-1 Mapping */
1373
1374 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1375 struct wpa_ssid *ssid = wpa_s->current_ssid;
1376 u8 channel;
1377 struct signal_poll_resp signal_poll;
1378 u8 *_ssid;
1379 size_t ssid_len;
1380 struct status_resp cli_status;
1381 int proto;
1382 int key_mgmt;
1383 int sae_pwe;
1384
1385 if (!ssid) {
1386 wpa_printf(MSG_ERROR, "Failed to get current ssid");
1387 goto out;
1388 }
1389
1390 _ssid = ssid->ssid;
1391 ssid_len = ssid->ssid_len;
1392 proto = ssid->proto;
1393 key_mgmt = ssid->key_mgmt;
1394 sae_pwe = wpa_s->conf->sae_pwe;
1395 os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN);
1396 status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq));
1397 status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt);
1398 status->security = wpas_key_mgmt_to_zephyr(0, ssid, key_mgmt, proto, sae_pwe);
1399 status->mfp = get_mfp(ssid->ieee80211w);
1400 ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel);
1401 status->channel = channel;
1402
1403 if (ssid_len == 0) {
1404 int _res = z_wpa_ctrl_status(wpa_s->ctrl_conn, &cli_status);
1405
1406 if (_res < 0) {
1407 ssid_len = 0;
1408 } else {
1409 ssid_len = cli_status.ssid_len;
1410 }
1411
1412 _ssid = cli_status.ssid;
1413 }
1414
1415 os_memcpy(status->ssid, _ssid, ssid_len);
1416 status->ssid_len = ssid_len;
1417 status->iface_mode = get_iface_mode(ssid->mode);
1418
1419 if (wpa_s->connection_set == 1) {
1420 status->link_mode = wpa_s->connection_he ? WIFI_6 :
1421 wpa_s->connection_vht ? WIFI_5 :
1422 wpa_s->connection_ht ? WIFI_4 :
1423 wpa_s->connection_g ? WIFI_3 :
1424 wpa_s->connection_a ? WIFI_2 :
1425 wpa_s->connection_b ? WIFI_1 :
1426 WIFI_0;
1427 } else {
1428 status->link_mode = WIFI_LINK_MODE_UNKNOWN;
1429 }
1430
1431 status->rssi = -WPA_INVALID_NOISE;
1432 if (status->iface_mode == WIFI_MODE_INFRA) {
1433 ret = z_wpa_ctrl_signal_poll(wpa_s->ctrl_conn, &signal_poll);
1434 if (!ret) {
1435 status->rssi = signal_poll.rssi;
1436 status->current_phy_tx_rate = signal_poll.current_txrate;
1437 } else {
1438 wpa_printf(MSG_WARNING, "%s: Failed to read signal poll info",
1439 __func__);
1440 }
1441 }
1442
1443 conn_info = os_zalloc(sizeof(struct wpa_conn_info));
1444 if (!conn_info) {
1445 wpa_printf(MSG_ERROR, "%s:Failed to allocate memory\n",
1446 __func__);
1447 ret = -ENOMEM;
1448 goto out;
1449 }
1450
1451 ret = wpa_drv_get_conn_info(wpa_s, conn_info);
1452 if (!ret) {
1453 status->beacon_interval = conn_info->beacon_interval;
1454 status->dtim_period = conn_info->dtim_period;
1455 status->twt_capable = conn_info->twt_capable;
1456 } else {
1457 wpa_printf(MSG_WARNING, "%s: Failed to get connection info\n",
1458 __func__);
1459
1460 status->beacon_interval = 0;
1461 status->dtim_period = 0;
1462 status->twt_capable = false;
1463 ret = 0;
1464 }
1465
1466 os_free(conn_info);
1467 } else {
1468 ret = 0;
1469 }
1470
1471 out:
1472 os_free(si);
1473 k_mutex_unlock(&wpa_supplicant_mutex);
1474 return ret;
1475 }
1476
1477 /* Below APIs are not natively supported by WPA supplicant, so,
1478 * these are just wrappers around driver offload APIs. But it is
1479 * transparent to the user.
1480 *
1481 * In the future these might be implemented natively by the WPA
1482 * supplicant.
1483 */
1484
1485 const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev)
1486 {
1487 struct net_wifi_mgmt_offload *api = (struct net_wifi_mgmt_offload *)dev->api;
1488
1489 return api ? api->wifi_mgmt_api : NULL;
1490 }
1491
1492 int supplicant_get_version(const struct device *dev, struct wifi_version *params)
1493 {
1494 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1495
1496 if (!wifi_mgmt_api || !wifi_mgmt_api->get_version) {
1497 wpa_printf(MSG_ERROR, "get_version not supported");
1498 return -ENOTSUP;
1499 }
1500
1501 return wifi_mgmt_api->get_version(dev, params);
1502 }
1503
1504 int supplicant_scan(const struct device *dev, struct wifi_scan_params *params,
1505 scan_result_cb_t cb)
1506 {
1507 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1508
1509 if (!wifi_mgmt_api || !wifi_mgmt_api->scan) {
1510 wpa_printf(MSG_ERROR, "Scan not supported");
1511 return -ENOTSUP;
1512 }
1513
1514 return wifi_mgmt_api->scan(dev, params, cb);
1515 }
1516
1517 #ifdef CONFIG_NET_STATISTICS_WIFI
1518 int supplicant_get_stats(const struct device *dev, struct net_stats_wifi *stats)
1519 {
1520 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1521
1522 if (!wifi_mgmt_api || !wifi_mgmt_api->get_stats) {
1523 wpa_printf(MSG_ERROR, "Get stats not supported");
1524 return -ENOTSUP;
1525 }
1526
1527 return wifi_mgmt_api->get_stats(dev, stats);
1528 }
1529
1530 int supplicant_reset_stats(const struct device *dev)
1531 {
1532 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1533
1534 if (!wifi_mgmt_api || !wifi_mgmt_api->reset_stats) {
1535 wpa_printf(MSG_WARNING, "Reset stats not supported");
1536 return -ENOTSUP;
1537 }
1538
1539 return wifi_mgmt_api->reset_stats(dev);
1540 }
1541 #endif /* CONFIG_NET_STATISTICS_WIFI */
1542
1543 int supplicant_pmksa_flush(const struct device *dev)
1544 {
1545 struct wpa_supplicant *wpa_s;
1546 int ret = 0;
1547
1548 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1549
1550 wpa_s = get_wpa_s_handle(dev);
1551 if (!wpa_s) {
1552 ret = -1;
1553 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1554 goto out;
1555 }
1556
1557 if (!wpa_cli_cmd_v("pmksa_flush")) {
1558 ret = -1;
1559 wpa_printf(MSG_ERROR, "pmksa_flush failed");
1560 goto out;
1561 }
1562
1563 out:
1564 k_mutex_unlock(&wpa_supplicant_mutex);
1565 return ret;
1566 }
1567
1568 int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params)
1569 {
1570 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1571
1572 if (!wifi_mgmt_api || !wifi_mgmt_api->cfg_11k) {
1573 wpa_printf(MSG_ERROR, "cfg 11k not supported");
1574 return -ENOTSUP;
1575 }
1576
1577 return wifi_mgmt_api->cfg_11k(dev, params);
1578 }
1579
1580 int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params)
1581 {
1582 struct wpa_supplicant *wpa_s;
1583 int ssid_len;
1584
1585 wpa_s = get_wpa_s_handle(dev);
1586 if (!wpa_s) {
1587 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1588 return -1;
1589 }
1590
1591 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1592 wpa_s->wpa_state < WPA_COMPLETED)) {
1593 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1594 return 0;
1595 }
1596
1597 if (params) {
1598 ssid_len = strlen(params->ssid);
1599 } else {
1600 ssid_len = 0;
1601 }
1602
1603 if (ssid_len > 0) {
1604 if (ssid_len > WIFI_SSID_MAX_LEN) {
1605 wpa_printf(MSG_ERROR, "%s: ssid too long %u",
1606 __func__, ssid_len);
1607 return -1;
1608 }
1609
1610 if (!wpa_cli_cmd_v("neighbor_rep_request ssid %s",
1611 params->ssid)) {
1612 wpa_printf(MSG_ERROR,
1613 "%s: cli cmd <neighbor_rep_request ssid %s> fail",
1614 __func__, params->ssid);
1615 return -1;
1616 }
1617 } else {
1618 if (!wpa_cli_cmd_v("neighbor_rep_request")) {
1619 wpa_printf(MSG_ERROR,
1620 "%s: cli cmd <neighbor_rep_request> fail",
1621 __func__);
1622 return -1;
1623 }
1624 }
1625
1626 return 0;
1627 }
1628
1629 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
1630 #define SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE 100
1631 int supplicant_candidate_scan(const struct device *dev, struct wifi_scan_params *params)
1632 {
1633 int i = 0;
1634 char cmd[SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE] = {0};
1635 char *pos = cmd;
1636 char *end = pos + SUPPLICANT_CANDIDATE_SCAN_CMD_BUF_SIZE;
1637 int freq = 0;
1638 struct wpa_supplicant *wpa_s;
1639
1640 wpa_s = get_wpa_s_handle(dev);
1641 if (!wpa_s) {
1642 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1643 return -1;
1644 }
1645
1646 strcpy(pos, "freq=");
1647 pos += 5;
1648 while (params->band_chan[i].channel) {
1649 if (i > 0) {
1650 pos += snprintf(pos, end - pos, ",");
1651 }
1652 freq = chan_to_freq(params->band_chan[i].channel);
1653 pos += snprintf(pos, end - pos, "%d", freq);
1654 i++;
1655 }
1656
1657 if (!wpa_cli_cmd_v("scan %s", cmd)) {
1658 wpa_printf(MSG_ERROR,
1659 "%s: cli cmd <scan %s> fail",
1660 __func__, cmd);
1661 return -1;
1662 }
1663
1664 return 0;
1665 }
1666
1667 int supplicant_11r_roaming(const struct device *dev)
1668 {
1669 struct wpa_supplicant *wpa_s;
1670 int ret = 0;
1671
1672 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1673
1674 wpa_s = get_wpa_s_handle(dev);
1675 if (!wpa_s) {
1676 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
1677 ret = -1;
1678 goto out;
1679 }
1680
1681 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1682 wpa_s->wpa_state < WPA_COMPLETED)) {
1683 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1684 ret = 0;
1685 goto out;
1686 }
1687
1688 if (!wpa_cli_cmd_v("reassociate")) {
1689 wpa_printf(MSG_ERROR, "%s: cli cmd <reassociate> fail",
1690 __func__);
1691 ret = -1;
1692 goto out;
1693 }
1694
1695 out:
1696 k_mutex_unlock(&wpa_supplicant_mutex);
1697 return ret;
1698 }
1699 #endif
1700
1701 int supplicant_set_power_save(const struct device *dev, struct wifi_ps_params *params)
1702 {
1703 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1704
1705 if (!wifi_mgmt_api || !wifi_mgmt_api->set_power_save) {
1706 wpa_printf(MSG_ERROR, "Set power save not supported");
1707 return -ENOTSUP;
1708 }
1709
1710 return wifi_mgmt_api->set_power_save(dev, params);
1711 }
1712
1713 int supplicant_set_twt(const struct device *dev, struct wifi_twt_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->set_twt) {
1718 wpa_printf(MSG_ERROR, "Set TWT not supported");
1719 return -ENOTSUP;
1720 }
1721
1722 return wifi_mgmt_api->set_twt(dev, params);
1723 }
1724
1725 int supplicant_set_btwt(const struct device *dev, struct wifi_twt_params *params)
1726 {
1727 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1728
1729 if (!wifi_mgmt_api || !wifi_mgmt_api->set_btwt) {
1730 wpa_printf(MSG_ERROR, "Set Broadcast TWT not supported");
1731 return -ENOTSUP;
1732 }
1733
1734 return wifi_mgmt_api->set_btwt(dev, params);
1735 }
1736
1737 int supplicant_get_power_save_config(const struct device *dev,
1738 struct wifi_ps_config *config)
1739 {
1740 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1741
1742 if (!wifi_mgmt_api || !wifi_mgmt_api->get_power_save_config) {
1743 wpa_printf(MSG_ERROR, "Get power save config not supported");
1744 return -ENOTSUP;
1745 }
1746
1747 return wifi_mgmt_api->get_power_save_config(dev, config);
1748 }
1749
1750 int supplicant_reg_domain(const struct device *dev,
1751 struct wifi_reg_domain *reg_domain)
1752 {
1753 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1754 struct wpa_supplicant *wpa_s;
1755 int ret = -1;
1756
1757 if (!wifi_mgmt_api || !wifi_mgmt_api->reg_domain) {
1758 wpa_printf(MSG_ERROR, "Regulatory domain not supported");
1759 return -ENOTSUP;
1760 }
1761
1762 if (reg_domain->oper == WIFI_MGMT_GET) {
1763 return wifi_mgmt_api->reg_domain(dev, reg_domain);
1764 }
1765
1766 if (reg_domain->oper == WIFI_MGMT_SET) {
1767 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1768
1769 if (IS_ENABLED(CONFIG_WIFI_NM_HOSTAPD_AP)) {
1770 const struct device *dev2 = net_if_get_device(net_if_get_wifi_sap());
1771
1772 ret = hostapd_ap_reg_domain(dev2, reg_domain);
1773 if (ret) {
1774 goto out;
1775 }
1776 }
1777
1778 wpa_s = get_wpa_s_handle(dev);
1779 if (!wpa_s) {
1780 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1781 goto out;
1782 }
1783
1784 if (!wpa_cli_cmd_v("set country %s", reg_domain->country_code)) {
1785 goto out;
1786 }
1787
1788 ret = 0;
1789
1790 out:
1791 k_mutex_unlock(&wpa_supplicant_mutex);
1792 }
1793
1794 return ret;
1795 }
1796
1797 int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode)
1798 {
1799 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1800
1801 if (!wifi_mgmt_api || !wifi_mgmt_api->mode) {
1802 wpa_printf(MSG_ERROR, "Setting mode not supported");
1803 return -ENOTSUP;
1804 }
1805
1806 return wifi_mgmt_api->mode(dev, mode);
1807 }
1808
1809 int supplicant_filter(const struct device *dev, struct wifi_filter_info *filter)
1810 {
1811 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1812
1813 if (!wifi_mgmt_api || !wifi_mgmt_api->filter) {
1814 wpa_printf(MSG_ERROR, "Setting filter not supported");
1815 return -ENOTSUP;
1816 }
1817
1818 return wifi_mgmt_api->filter(dev, filter);
1819 }
1820
1821 int supplicant_channel(const struct device *dev, struct wifi_channel_info *channel)
1822 {
1823 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1824
1825 if (!wifi_mgmt_api || !wifi_mgmt_api->channel) {
1826 wpa_printf(MSG_ERROR, "Setting channel not supported");
1827 return -ENOTSUP;
1828 }
1829
1830 return wifi_mgmt_api->channel(dev, channel);
1831 }
1832
1833 int supplicant_set_rts_threshold(const struct device *dev, unsigned int rts_threshold)
1834 {
1835 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1836
1837 if (!wifi_mgmt_api || !wifi_mgmt_api->set_rts_threshold) {
1838 wpa_printf(MSG_ERROR, "Set RTS not supported");
1839 return -ENOTSUP;
1840 }
1841
1842 return wifi_mgmt_api->set_rts_threshold(dev, rts_threshold);
1843 }
1844
1845 int supplicant_get_rts_threshold(const struct device *dev, unsigned int *rts_threshold)
1846 {
1847 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1848
1849 if (!wifi_mgmt_api || !wifi_mgmt_api->get_rts_threshold) {
1850 wpa_printf(MSG_ERROR, "Get RTS not supported");
1851 return -ENOTSUP;
1852 }
1853
1854 return wifi_mgmt_api->get_rts_threshold(dev, rts_threshold);
1855 }
1856
1857 bool supplicant_bss_support_neighbor_rep(const struct device *dev)
1858 {
1859 struct wpa_supplicant *wpa_s;
1860 bool is_support = false;
1861 const u8 *rrm_ie = NULL;
1862
1863 wpa_s = get_wpa_s_handle(dev);
1864 if (!wpa_s) {
1865 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1866 return false;
1867 }
1868
1869 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1870 if (!wpa_s->rrm.rrm_used) {
1871 goto out;
1872 }
1873
1874 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
1875 WLAN_EID_RRM_ENABLED_CAPABILITIES);
1876 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
1877 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
1878 goto out;
1879 }
1880 is_support = true;
1881 out:
1882 k_mutex_unlock(&wpa_supplicant_mutex);
1883 return is_support;
1884 }
1885
1886 int supplicant_bss_ext_capab(const struct device *dev, int capab)
1887 {
1888 struct wpa_supplicant *wpa_s;
1889 int is_support = 0;
1890
1891 wpa_s = get_wpa_s_handle(dev);
1892 if (!wpa_s) {
1893 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1894 return 0;
1895 }
1896
1897 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1898 is_support = wpa_bss_ext_capab(wpa_s->current_bss, capab);
1899 k_mutex_unlock(&wpa_supplicant_mutex);
1900
1901 return is_support;
1902 }
1903
1904 int supplicant_legacy_roam(const struct device *dev)
1905 {
1906 struct wpa_supplicant *wpa_s;
1907 int ret = -1;
1908
1909 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1910
1911 wpa_s = get_wpa_s_handle(dev);
1912 if (!wpa_s) {
1913 ret = -1;
1914 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1915 goto out;
1916 }
1917
1918 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
1919 wpa_s->wpa_state < WPA_COMPLETED)) {
1920 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
1921 ret = 0;
1922 goto out;
1923 }
1924
1925 if (!wpa_cli_cmd_v("scan")) {
1926 goto out;
1927 }
1928
1929 ret = 0;
1930
1931 out:
1932 k_mutex_unlock(&wpa_supplicant_mutex);
1933
1934 return ret;
1935 }
1936
1937 int supplicant_set_bss_max_idle_period(const struct device *dev,
1938 unsigned short bss_max_idle_period)
1939 {
1940 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
1941
1942 if (!wifi_mgmt_api || !wifi_mgmt_api->set_bss_max_idle_period) {
1943 wpa_printf(MSG_ERROR, "set_bss_max_idle_period is not supported");
1944 return -ENOTSUP;
1945 }
1946
1947 return wifi_mgmt_api->set_bss_max_idle_period(dev, bss_max_idle_period);
1948 }
1949
1950 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_BGSCAN
1951 int supplicant_set_bgscan(const struct device *dev, struct wifi_bgscan_params *params)
1952 {
1953 struct wpa_supplicant *wpa_s;
1954 struct wpa_ssid *ssid;
1955 int ret = -1;
1956
1957 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
1958
1959 wpa_s = get_wpa_s_handle(dev);
1960 if (wpa_s == NULL) {
1961 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1962 goto out;
1963 }
1964
1965 ssid = wpa_s->current_ssid;
1966 if (ssid == NULL) {
1967 wpa_printf(MSG_ERROR, "SSID for %s not found", dev->name);
1968 goto out;
1969 }
1970
1971 switch (params->type) {
1972 case WIFI_BGSCAN_SIMPLE:
1973 if (!IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_BGSCAN_SIMPLE)) {
1974 wpa_printf(MSG_ERROR, "Invalid bgscan type, enable "
1975 "CONFIG_WIFI_NM_WPA_SUPPLICANT_BGSCAN_SIMPLE");
1976 ret = -ENOTSUP;
1977 goto out;
1978 }
1979 if (!wpa_cli_cmd_v("set_network %d bgscan \"simple:%d:%d:%d:%d\"", ssid->id,
1980 params->short_interval, params->rssi_threshold,
1981 params->long_interval, params->btm_queries)) {
1982 goto out;
1983 }
1984 break;
1985 case WIFI_BGSCAN_LEARN:
1986 if (!IS_ENABLED(CONFIG_WIFI_NM_WPA_SUPPLICANT_BGSCAN_LEARN)) {
1987 wpa_printf(MSG_ERROR, "Invalid bgscan type, enable "
1988 "CONFIG_WIFI_NM_WPA_SUPPLICANT_BGSCAN_LEARN");
1989 ret = -ENOTSUP;
1990 goto out;
1991 }
1992 if (!wpa_cli_cmd_v("set_network %d bgscan \"learn:%d:%d:%d\"", ssid->id,
1993 params->short_interval, params->rssi_threshold,
1994 params->long_interval)) {
1995 goto out;
1996 }
1997 break;
1998 case WIFI_BGSCAN_NONE:
1999 default:
2000 if (!wpa_cli_cmd_v("set_network %d bgscan \"\"", ssid->id)) {
2001 goto out;
2002 }
2003 break;
2004 }
2005
2006 ret = 0;
2007
2008 out:
2009 k_mutex_unlock(&wpa_supplicant_mutex);
2010
2011 return ret;
2012 }
2013 #endif
2014
2015 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
2016 int supplicant_btm_query(const struct device *dev, uint8_t reason)
2017 {
2018 struct wpa_supplicant *wpa_s;
2019 int ret = -1;
2020
2021 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2022
2023 wpa_s = get_wpa_s_handle(dev);
2024 if (!wpa_s) {
2025 ret = -1;
2026 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2027 goto out;
2028 }
2029
2030 if (wpa_s->reassociate || (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
2031 wpa_s->wpa_state < WPA_COMPLETED)) {
2032 wpa_printf(MSG_INFO, "Reassociation is in progress, skip");
2033 ret = 0;
2034 goto out;
2035 }
2036
2037 /* Flush all unused BSS entries */
2038 if (!wpa_cli_cmd_v("bss_flush")) {
2039 goto out;
2040 }
2041
2042 if (!wpa_cli_cmd_v("wnm_bss_query %d", reason)) {
2043 goto out;
2044 }
2045
2046 ret = 0;
2047
2048 out:
2049 k_mutex_unlock(&wpa_supplicant_mutex);
2050
2051 return ret;
2052 }
2053 #endif
2054
2055 int supplicant_get_wifi_conn_params(const struct device *dev,
2056 struct wifi_connect_req_params *params)
2057 {
2058 struct wpa_supplicant *wpa_s;
2059 int ret = 0;
2060
2061 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2062
2063 wpa_s = get_wpa_s_handle(dev);
2064 if (!wpa_s) {
2065 ret = -1;
2066 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2067 goto out;
2068 }
2069
2070 memcpy(params, &last_wifi_conn_params, sizeof(struct wifi_connect_req_params));
2071 out:
2072 k_mutex_unlock(&wpa_supplicant_mutex);
2073 return ret;
2074 }
2075
2076 static int supplicant_wps_pbc(const struct device *dev)
2077 {
2078 struct wpa_supplicant *wpa_s;
2079 int ret = -1;
2080
2081 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2082
2083 wpa_s = get_wpa_s_handle(dev);
2084 if (!wpa_s) {
2085 ret = -1;
2086 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2087 goto out;
2088 }
2089
2090 if (!wpa_cli_cmd_v("wps_pbc")) {
2091 goto out;
2092 }
2093
2094 wpas_api_ctrl.dev = dev;
2095 wpas_api_ctrl.requested_op = WPS_PBC;
2096
2097 ret = 0;
2098
2099 out:
2100 k_mutex_unlock(&wpa_supplicant_mutex);
2101
2102 return ret;
2103 }
2104
2105 static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
2106 {
2107 struct wpa_supplicant *wpa_s;
2108 char *get_pin_cmd = "WPS_PIN get";
2109 int ret = -1;
2110
2111 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2112
2113 wpa_s = get_wpa_s_handle(dev);
2114 if (!wpa_s) {
2115 ret = -1;
2116 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2117 goto out;
2118 }
2119
2120 if (params->oper == WIFI_WPS_PIN_GET) {
2121 if (zephyr_wpa_cli_cmd_resp(wpa_s->ctrl_conn, get_pin_cmd, params->pin)) {
2122 goto out;
2123 }
2124 } else if (params->oper == WIFI_WPS_PIN_SET) {
2125 if (!wpa_cli_cmd_v("wps_check_pin %s", params->pin)) {
2126 goto out;
2127 }
2128
2129 if (!wpa_cli_cmd_v("wps_pin any %s", params->pin)) {
2130 goto out;
2131 }
2132
2133 wpas_api_ctrl.dev = dev;
2134 wpas_api_ctrl.requested_op = WPS_PIN;
2135 } else {
2136 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
2137 goto out;
2138 }
2139
2140 ret = 0;
2141
2142 out:
2143 k_mutex_unlock(&wpa_supplicant_mutex);
2144
2145 return ret;
2146 }
2147
2148 int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
2149 {
2150 int ret = 0;
2151
2152 if (params->oper == WIFI_WPS_PBC) {
2153 ret = supplicant_wps_pbc(dev);
2154 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
2155 ret = supplicant_wps_pin(dev, params);
2156 }
2157
2158 return ret;
2159 }
2160
2161 #ifdef CONFIG_AP
2162 int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth)
2163 {
2164 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
2165 struct wifi_ap_config_params params = {0};
2166
2167 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
2168 return -ENOTSUP;
2169 }
2170
2171 params.bandwidth = bandwidth;
2172 params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH;
2173 return wifi_mgmt_api->ap_config_params(dev, ¶ms);
2174 }
2175
2176 int supplicant_ap_enable(const struct device *dev,
2177 struct wifi_connect_req_params *params)
2178 {
2179 struct wpa_supplicant *wpa_s;
2180 int ret;
2181
2182 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
2183 wpa_printf(MSG_ERROR,
2184 "Interface %s is down, dropping connect",
2185 dev->name);
2186 return -1;
2187 }
2188
2189 ret = set_ap_bandwidth(dev, params->bandwidth);
2190 if (ret && (ret != -ENOTSUP)) {
2191 wpa_printf(MSG_ERROR, "Failed to set ap bandwidth");
2192 return -EINVAL;
2193 }
2194
2195 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2196
2197 wpa_s = get_wpa_s_handle(dev);
2198 if (!wpa_s) {
2199 ret = -1;
2200 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2201 goto out;
2202 }
2203
2204 if (wpa_s->wpa_state != WPA_DISCONNECTED) {
2205 ret = -EBUSY;
2206 wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name);
2207 goto out;
2208 }
2209
2210 /* No need to check for existing network to join for SoftAP */
2211 wpa_s->conf->ap_scan = 2;
2212 /* Set BSS parameter max_num_sta to default configured value */
2213 wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA;
2214
2215 ret = wpas_add_and_config_network(wpa_s, params, true);
2216 if (ret) {
2217 wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret);
2218 goto out;
2219 }
2220
2221 out:
2222 k_mutex_unlock(&wpa_supplicant_mutex);
2223
2224 return ret;
2225 }
2226
2227 int supplicant_ap_disable(const struct device *dev)
2228 {
2229 struct wpa_supplicant *wpa_s;
2230 int ret = -1;
2231
2232 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2233
2234 wpa_s = get_wpa_s_handle(dev);
2235 if (!wpa_s) {
2236 ret = -1;
2237 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2238 goto out;
2239 }
2240
2241 ret = wpas_disconnect_network(dev, WPAS_MODE_AP);
2242 if (ret) {
2243 wpa_printf(MSG_ERROR, "Failed to disconnect from network");
2244 goto out;
2245 }
2246
2247 /* Restore ap_scan to default value */
2248 wpa_s->conf->ap_scan = 1;
2249
2250 out:
2251 k_mutex_unlock(&wpa_supplicant_mutex);
2252 return ret;
2253 }
2254
2255 int supplicant_ap_sta_disconnect(const struct device *dev,
2256 const uint8_t *mac_addr)
2257 {
2258 struct wpa_supplicant *wpa_s;
2259 int ret = -1;
2260
2261 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2262
2263 wpa_s = get_wpa_s_handle(dev);
2264 if (!wpa_s) {
2265 ret = -1;
2266 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
2267 goto out;
2268 }
2269
2270 if (!mac_addr) {
2271 ret = -EINVAL;
2272 wpa_printf(MSG_ERROR, "Invalid MAC address");
2273 goto out;
2274 }
2275
2276 if (!wpa_cli_cmd_v("disassociate %02x:%02x:%02x:%02x:%02x:%02x",
2277 mac_addr[0], mac_addr[1], mac_addr[2],
2278 mac_addr[3], mac_addr[4], mac_addr[5])) {
2279 goto out;
2280 }
2281
2282 ret = 0;
2283
2284 out:
2285 k_mutex_unlock(&wpa_supplicant_mutex);
2286
2287 return ret;
2288 }
2289 #endif /* CONFIG_AP */
2290
2291 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
2292 static const char *dpp_params_to_args_curve(int curve)
2293 {
2294 switch (curve) {
2295 case WIFI_DPP_CURVES_P_256:
2296 return "P-256";
2297 case WIFI_DPP_CURVES_P_384:
2298 return "P-384";
2299 case WIFI_DPP_CURVES_P_512:
2300 return "P-521";
2301 case WIFI_DPP_CURVES_BP_256:
2302 return "BP-256";
2303 case WIFI_DPP_CURVES_BP_384:
2304 return "BP-384";
2305 case WIFI_DPP_CURVES_BP_512:
2306 return "BP-512";
2307 default:
2308 return "P-256";
2309 }
2310 }
2311
2312 static const char *dpp_params_to_args_conf(int conf)
2313 {
2314 switch (conf) {
2315 case WIFI_DPP_CONF_STA:
2316 return "sta-dpp";
2317 case WIFI_DPP_CONF_AP:
2318 return "ap-dpp";
2319 case WIFI_DPP_CONF_QUERY:
2320 return "query";
2321 default:
2322 return "sta-dpp";
2323 }
2324 }
2325
2326 static const char *dpp_params_to_args_role(int role)
2327 {
2328 switch (role) {
2329 case WIFI_DPP_ROLE_CONFIGURATOR:
2330 return "configurator";
2331 case WIFI_DPP_ROLE_ENROLLEE:
2332 return "enrollee";
2333 case WIFI_DPP_ROLE_EITHER:
2334 return "either";
2335 default:
2336 return "either";
2337 }
2338 }
2339
2340 static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len)
2341 {
2342 uint8_t *end = src + strlen(src);
2343
2344 /* do 4 bytes convert first */
2345 for (; (src + 4) < end; src += 4) {
2346 snprintf(dst, max_len, "%02x%02x%02x%02x",
2347 src[0], src[1], src[2], src[3]);
2348 dst += 8;
2349 }
2350
2351 /* then do 1 byte convert */
2352 for (; src < end; src++) {
2353 snprintf(dst, max_len, "%02x", src[0]);
2354 dst += 2;
2355 }
2356 }
2357
2358 #define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur)))
2359
2360 int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len)
2361 {
2362 char *pos = cmd;
2363 char *end = cmd + max_len;
2364
2365 switch (params->action) {
2366 case WIFI_DPP_CONFIGURATOR_ADD:
2367 strncpy(pos, "DPP_CONFIGURATOR_ADD", end - pos);
2368 STR_CUR_TO_END(pos);
2369
2370 if (params->configurator_add.curve) {
2371 snprintf(pos, end - pos, " curve=%s",
2372 dpp_params_to_args_curve(params->configurator_add.curve));
2373 STR_CUR_TO_END(pos);
2374 }
2375
2376 if (params->configurator_add.net_access_key_curve) {
2377 snprintf(pos, end - pos, " net_access_key_curve=%s",
2378 dpp_params_to_args_curve(
2379 params->configurator_add.net_access_key_curve));
2380 }
2381 break;
2382 case WIFI_DPP_AUTH_INIT:
2383 strncpy(pos, "DPP_AUTH_INIT", end - pos);
2384 STR_CUR_TO_END(pos);
2385
2386 if (params->auth_init.peer) {
2387 snprintf(pos, end - pos, " peer=%d", params->auth_init.peer);
2388 STR_CUR_TO_END(pos);
2389 }
2390
2391 if (params->auth_init.conf) {
2392 snprintf(pos, end - pos, " conf=%s",
2393 dpp_params_to_args_conf(
2394 params->auth_init.conf));
2395 STR_CUR_TO_END(pos);
2396 }
2397
2398 if (params->auth_init.ssid[0]) {
2399 strncpy(pos, " ssid=", end - pos);
2400 STR_CUR_TO_END(pos);
2401 dpp_ssid_bin2str(pos, params->auth_init.ssid,
2402 WIFI_SSID_MAX_LEN * 2);
2403 STR_CUR_TO_END(pos);
2404 }
2405
2406 if (params->auth_init.configurator) {
2407 snprintf(pos, end - pos, " configurator=%d",
2408 params->auth_init.configurator);
2409 STR_CUR_TO_END(pos);
2410 }
2411
2412 if (params->auth_init.role) {
2413 snprintf(pos, end - pos, " role=%s",
2414 dpp_params_to_args_role(
2415 params->auth_init.role));
2416 }
2417 break;
2418 case WIFI_DPP_QR_CODE:
2419 strncpy(pos, "DPP_QR_CODE", end - pos);
2420 STR_CUR_TO_END(pos);
2421
2422 if (params->dpp_qr_code[0]) {
2423 snprintf(pos, end - pos, " %s", params->dpp_qr_code);
2424 }
2425 break;
2426 case WIFI_DPP_CHIRP:
2427 strncpy(pos, "DPP_CHIRP", end - pos);
2428 STR_CUR_TO_END(pos);
2429
2430 if (params->chirp.id) {
2431 snprintf(pos, end - pos, " own=%d", params->chirp.id);
2432 STR_CUR_TO_END(pos);
2433 }
2434
2435 if (params->chirp.freq) {
2436 snprintf(pos, end - pos, " listen=%d", params->chirp.freq);
2437 }
2438 break;
2439 case WIFI_DPP_LISTEN:
2440 strncpy(pos, "DPP_LISTEN", end - pos);
2441 STR_CUR_TO_END(pos);
2442
2443 if (params->listen.freq) {
2444 snprintf(pos, end - pos, " %d", params->listen.freq);
2445 STR_CUR_TO_END(pos);
2446 }
2447
2448 if (params->listen.role) {
2449 snprintf(pos, end - pos, " role=%s",
2450 dpp_params_to_args_role(
2451 params->listen.role));
2452 }
2453 break;
2454 case WIFI_DPP_BOOTSTRAP_GEN:
2455 strncpy(pos, "DPP_BOOTSTRAP_GEN", end - pos);
2456 STR_CUR_TO_END(pos);
2457
2458 if (params->bootstrap_gen.type) {
2459 strncpy(pos, " type=qrcode", end - pos);
2460 STR_CUR_TO_END(pos);
2461 }
2462
2463 if (params->bootstrap_gen.op_class &&
2464 params->bootstrap_gen.chan) {
2465 snprintf(pos, end - pos, " chan=%d/%d",
2466 params->bootstrap_gen.op_class,
2467 params->bootstrap_gen.chan);
2468 STR_CUR_TO_END(pos);
2469 }
2470
2471 /* mac is mandatory, even if it is zero mac address */
2472 snprintf(pos, end - pos, " mac=%02x:%02x:%02x:%02x:%02x:%02x",
2473 params->bootstrap_gen.mac[0], params->bootstrap_gen.mac[1],
2474 params->bootstrap_gen.mac[2], params->bootstrap_gen.mac[3],
2475 params->bootstrap_gen.mac[4], params->bootstrap_gen.mac[5]);
2476 STR_CUR_TO_END(pos);
2477
2478 if (params->bootstrap_gen.curve) {
2479 snprintf(pos, end - pos, " curve=%s",
2480 dpp_params_to_args_curve(params->bootstrap_gen.curve));
2481 }
2482 break;
2483 case WIFI_DPP_BOOTSTRAP_GET_URI:
2484 snprintf(pos, end - pos, "DPP_BOOTSTRAP_GET_URI %d", params->id);
2485 break;
2486 case WIFI_DPP_SET_CONF_PARAM:
2487 strncpy(pos, "SET dpp_configurator_params", end - pos);
2488 STR_CUR_TO_END(pos);
2489
2490 if (params->configurator_set.peer) {
2491 snprintf(pos, end - pos, " peer=%d", params->configurator_set.peer);
2492 STR_CUR_TO_END(pos);
2493 }
2494
2495 if (params->configurator_set.conf) {
2496 snprintf(pos, end - pos, " conf=%s",
2497 dpp_params_to_args_conf(
2498 params->configurator_set.conf));
2499 STR_CUR_TO_END(pos);
2500 }
2501
2502 if (params->configurator_set.ssid[0]) {
2503 strncpy(pos, " ssid=", end - pos);
2504 STR_CUR_TO_END(pos);
2505 dpp_ssid_bin2str(pos, params->configurator_set.ssid,
2506 WIFI_SSID_MAX_LEN * 2);
2507 STR_CUR_TO_END(pos);
2508 }
2509
2510 if (params->configurator_set.configurator) {
2511 snprintf(pos, end - pos, " configurator=%d",
2512 params->configurator_set.configurator);
2513 STR_CUR_TO_END(pos);
2514 }
2515
2516 if (params->configurator_set.role) {
2517 snprintf(pos, end - pos, " role=%s",
2518 dpp_params_to_args_role(
2519 params->configurator_set.role));
2520 STR_CUR_TO_END(pos);
2521 }
2522
2523 if (params->configurator_set.curve) {
2524 snprintf(pos, end - pos, " curve=%s",
2525 dpp_params_to_args_curve(params->configurator_set.curve));
2526 STR_CUR_TO_END(pos);
2527 }
2528
2529 if (params->configurator_set.net_access_key_curve) {
2530 snprintf(pos, end - pos, " net_access_key_curve=%s",
2531 dpp_params_to_args_curve(
2532 params->configurator_set.net_access_key_curve));
2533 }
2534 break;
2535 case WIFI_DPP_SET_WAIT_RESP_TIME:
2536 snprintf(pos, end - pos, "SET dpp_resp_wait_time %d",
2537 params->dpp_resp_wait_time);
2538 break;
2539 case WIFI_DPP_RECONFIG:
2540 snprintf(pos, end - pos, "DPP_RECONFIG %d", params->network_id);
2541 break;
2542 default:
2543 wpa_printf(MSG_ERROR, "Unknown DPP action");
2544 return -EINVAL;
2545 }
2546
2547 return 0;
2548 }
2549
2550 int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
2551 {
2552 int ret;
2553 char *cmd = NULL;
2554 struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev);
2555
2556 if (params == NULL) {
2557 return -EINVAL;
2558 }
2559
2560 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
2561 if (cmd == NULL) {
2562 return -ENOMEM;
2563 }
2564
2565 /* leave one byte always be 0 */
2566 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
2567 if (ret) {
2568 os_free(cmd);
2569 return ret;
2570 }
2571
2572 wpa_printf(MSG_DEBUG, "wpa_cli %s", cmd);
2573 if (zephyr_wpa_cli_cmd_resp(wpa_s->ctrl_conn, cmd, params->resp)) {
2574 os_free(cmd);
2575 return -ENOEXEC;
2576 }
2577
2578 os_free(cmd);
2579 return 0;
2580 }
2581 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
2582
2583 int supplicant_config_params(const struct device *dev, struct wifi_config_params *params)
2584 {
2585 struct wpa_supplicant *wpa_s;
2586 int ret = 0;
2587
2588 k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER);
2589
2590 wpa_s = get_wpa_s_handle(dev);
2591 if (!wpa_s) {
2592 ret = -ENOENT;
2593 wpa_printf(MSG_ERROR, "Device %s not found", dev->name);
2594 goto out;
2595 }
2596
2597 if (params->type & WIFI_CONFIG_PARAM_OKC) {
2598 if (!wpa_cli_cmd_v("set okc %d", params->okc)) {
2599 ret = -EINVAL;
2600 wpa_printf(MSG_ERROR, "Failed to set OKC");
2601 goto out;
2602 }
2603 wpa_printf(MSG_DEBUG, "Set OKC: %d", params->okc);
2604 }
2605
2606 out:
2607 k_mutex_unlock(&wpa_supplicant_mutex);
2608 return ret;
2609 }
2610