1 /**
2 * Copyright 2023-2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/net/wifi_mgmt.h>
8 #include "includes.h"
9 #include "common.h"
10 #include "common/defs.h"
11 #include "wpa_supplicant_i.h"
12 #include "hostapd.h"
13 #include "hostapd_cli_zephyr.h"
14 #include "ap_drv_ops.h"
15 #include "hapd_main.h"
16 #include "hapd_api.h"
17 #include "supp_events.h"
18 #include "supp_api.h"
19
20 K_MUTEX_DEFINE(hostapd_mutex);
21
22 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
23 static struct wifi_eap_config hapd_eap_config[] = {
24 {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL},
25 {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP",
26 "auth=MSCHAPV2"},
27 {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP",
28 "auth=GTC"},
29 {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS",
30 "auth=MSCHAPV2"},
31 {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP",
32 "auth=TLS"},
33 };
34
35 static struct wifi_enterprise_creds_params hapd_enterprise_creds;
36 #endif
37
38 #define hostapd_cli_cmd_v(cmd, ...) ({ \
39 bool status; \
40 \
41 if (zephyr_hostapd_cli_cmd_v(iface->ctrl_conn, cmd, ##__VA_ARGS__) < 0) { \
42 wpa_printf(MSG_ERROR, \
43 "Failed to execute wpa_cli command: %s", \
44 cmd); \
45 status = false; \
46 } else { \
47 status = true; \
48 } \
49 \
50 status; \
51 })
52
get_hostapd_handle(const struct device * dev)53 static inline struct hostapd_iface *get_hostapd_handle(const struct device *dev)
54 {
55 struct net_if *iface = net_if_lookup_by_dev(dev);
56 char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
57 struct hostapd_iface *hapd;
58 int ret;
59
60 if (!iface) {
61 wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name);
62 return NULL;
63 }
64
65 ret = net_if_get_name(iface, if_name, sizeof(if_name));
66 if (!ret) {
67 wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret);
68 return NULL;
69 }
70
71 hapd = zephyr_get_hapd_handle_by_ifname(if_name);
72 if (!hapd) {
73 wpa_printf(MSG_ERROR, "Interface %s not found", if_name);
74 return NULL;
75 }
76
77 return hapd;
78 }
79
80 #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)81 static int hapd_process_cert_data(struct hostapd_bss_config *conf,
82 char *type, uint8_t *data, uint32_t data_len)
83 {
84 if (os_strcmp(type, "ca_cert_blob") == 0) {
85 conf->ca_cert_blob = data;
86 conf->ca_cert_blob_len = data_len;
87 } else if (os_strcmp(type, "server_cert_blob") == 0) {
88 conf->server_cert_blob = data;
89 conf->server_cert_blob_len = data_len;
90 } else if (os_strcmp(type, "private_key_blob") == 0) {
91 conf->private_key_blob = data;
92 conf->private_key_blob_len = data_len;
93 } else if (os_strcmp(type, "dh_blob") == 0) {
94 conf->dh_blob = data;
95 conf->dh_blob_len = data_len;
96 } else {
97 wpa_printf(MSG_ERROR, "input type error");
98 return -ENOTSUP;
99 }
100
101 return 0;
102 }
103
hapd_get_eap_config(struct wifi_connect_req_params * params,struct wifi_eap_config * eap_cfg)104 static int hapd_get_eap_config(struct wifi_connect_req_params *params,
105 struct wifi_eap_config *eap_cfg)
106 {
107 unsigned int index = 0;
108
109 for (index = 0; index < ARRAY_SIZE(hapd_eap_config); index++) {
110 if (params->security == hapd_eap_config[index].type) {
111 memcpy(eap_cfg, &hapd_eap_config[index], sizeof(struct wifi_eap_config));
112 break;
113 }
114 }
115
116 if (index == ARRAY_SIZE(hapd_eap_config)) {
117 wpa_printf(MSG_ERROR, "Get eap method type with security type: %d",
118 params->security);
119 return -ENOTSUP;
120 }
121
122 return 0;
123 }
124
hapd_process_eap_user_phase1(struct wifi_connect_req_params * params,struct hostapd_eap_user ** pnew_user)125 static struct hostapd_eap_user *hapd_process_eap_user_phase1(
126 struct wifi_connect_req_params *params, struct hostapd_eap_user **pnew_user)
127 {
128 struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
129 struct wifi_eap_config eap_cfg;
130
131 user = os_zalloc(sizeof(*user));
132 if (user == NULL) {
133 wpa_printf(MSG_ERROR, "EAP user allocation failed");
134 goto failed;
135 }
136
137 user->force_version = -1;
138 if (params->eap_ver >= 0) {
139 user->force_version = params->eap_ver;
140 }
141
142 if (hapd_get_eap_config(params, &eap_cfg)) {
143 goto failed;
144 }
145
146 user->methods[0].method = eap_cfg.eap_type_phase1;
147 user->methods[0].vendor = 0;
148
149 if (tail == NULL) {
150 tail = new_user = user;
151 } else {
152 tail->next = user;
153 tail = user;
154 }
155
156 *pnew_user = new_user;
157
158 return tail;
159
160 failed:
161 if (user) {
162 hostapd_config_free_eap_user(user);
163 }
164
165 return NULL;
166 }
167
hapd_process_eap_user(struct wifi_connect_req_params * params,struct hostapd_bss_config * conf)168 static int hapd_process_eap_user(struct wifi_connect_req_params *params,
169 struct hostapd_bss_config *conf)
170 {
171 struct hostapd_eap_user *user = NULL, *tail = NULL, *user_list = NULL;
172 int i, nusers = params->nusers;
173 const char *identity, *password;
174 struct wifi_eap_config eap_cfg;
175 int ret = 0;
176
177 if (hapd_get_eap_config(params, &eap_cfg)) {
178 goto failed;
179 }
180
181 if (eap_cfg.phase2 != NULL) {
182 tail = hapd_process_eap_user_phase1(params, &user_list);
183 }
184
185 if (eap_cfg.phase2 != NULL && !nusers) {
186 wpa_printf(MSG_ERROR, "EAP users not found.");
187 goto failed;
188 }
189
190 for (i = 0; i < nusers; i++) {
191 user = os_zalloc(sizeof(*user));
192 if (user == NULL) {
193 wpa_printf(MSG_ERROR, "EAP user allocation failed");
194 goto failed;
195 }
196
197 user->force_version = -1;
198 if (params->eap_ver >= 0) {
199 user->force_version = params->eap_ver;
200 }
201
202 identity = params->identities[i];
203 password = params->passwords[i];
204
205 user->identity = os_memdup(identity, os_strlen(identity));
206 if (user->identity == NULL) {
207 wpa_printf(MSG_ERROR,
208 "Failed to allocate "
209 "memory for EAP identity");
210 goto failed;
211 }
212 user->identity_len = os_strlen(identity);
213
214 user->methods[0].method = eap_cfg.eap_type_phase1;
215 user->methods[0].vendor = 0;
216
217 if (eap_cfg.phase2 != NULL) {
218 user->methods[0].method = eap_cfg.eap_type_phase2;
219 user->password = os_memdup(password, os_strlen(password));
220 if (user->password == NULL) {
221 wpa_printf(MSG_ERROR,
222 "Failed to allocate "
223 "memory for EAP password");
224 goto failed;
225 }
226 user->password_len = os_strlen(password);
227
228 user->phase2 = 1;
229 }
230
231 if (params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) {
232 user->ttls_auth |= 0x1E;
233 }
234
235 if (tail == NULL) {
236 tail = user_list = user;
237 } else {
238 tail->next = user;
239 tail = user;
240 }
241
242 continue;
243
244 failed:
245 if (user) {
246 hostapd_config_free_eap_user(user);
247 }
248
249 ret = -1;
250 break;
251 }
252
253 if (ret == 0) {
254 hostapd_config_free_eap_users(conf->eap_user);
255 conf->eap_user = user_list;
256 } else {
257 hostapd_config_free_eap_users(user_list);
258 }
259
260 return ret;
261 }
262
hapd_process_enterprise_config(struct hostapd_iface * iface,struct wifi_connect_req_params * params)263 int hapd_process_enterprise_config(struct hostapd_iface *iface,
264 struct wifi_connect_req_params *params)
265 {
266 struct wifi_eap_cipher_config cipher_config = {
267 NULL, "DEFAULT:!EXP:!LOW", "CCMP", "CCMP", "AES-128-CMAC", NULL};
268 int ret = 0;
269
270 if (process_cipher_config(params, &cipher_config)) {
271 goto out;
272 }
273
274 if (!hostapd_cli_cmd_v("set wpa %d", WPA_PROTO_RSN)) {
275 goto out;
276 }
277
278 if (!hostapd_cli_cmd_v("set wpa_key_mgmt %s", cipher_config.key_mgmt)) {
279 goto out;
280 }
281
282 if (!hostapd_cli_cmd_v("set rsn_pairwise %s", cipher_config.pairwise_cipher)) {
283 goto out;
284 }
285
286 if (!hostapd_cli_cmd_v("set wpa_pairwise %s", cipher_config.pairwise_cipher)) {
287 goto out;
288 }
289
290 if (!hostapd_cli_cmd_v("set group_cipher %s", cipher_config.group_cipher)) {
291 goto out;
292 }
293
294 if (!hostapd_cli_cmd_v("set group_mgmt_cipher %s", cipher_config.group_mgmt_cipher)) {
295 goto out;
296 }
297
298 if (cipher_config.tls_flags != NULL) {
299 if (!hostapd_cli_cmd_v("set tls_flags %s", cipher_config.tls_flags)) {
300 goto out;
301 }
302 }
303
304 if (!hostapd_cli_cmd_v("set ieee8021x %d", 1)) {
305 goto out;
306 }
307
308 if (!hostapd_cli_cmd_v("set eapol_version %d", 2)) {
309 goto out;
310 }
311
312 if (!hostapd_cli_cmd_v("set eap_server %d", 1)) {
313 goto out;
314 }
315
316 if (hapd_process_cert_data(iface->bss[0]->conf, "ca_cert_blob",
317 hapd_enterprise_creds.ca_cert, hapd_enterprise_creds.ca_cert_len)) {
318 goto out;
319 }
320
321 if (hapd_process_cert_data(iface->bss[0]->conf, "server_cert_blob",
322 hapd_enterprise_creds.server_cert, hapd_enterprise_creds.server_cert_len)) {
323 goto out;
324 }
325
326 if (hapd_process_cert_data(iface->bss[0]->conf, "private_key_blob",
327 hapd_enterprise_creds.server_key, hapd_enterprise_creds.server_key_len)) {
328 goto out;
329 }
330
331 if (hapd_process_cert_data(iface->bss[0]->conf, "dh_blob",
332 hapd_enterprise_creds.dh_param, hapd_enterprise_creds.dh_param_len)) {
333 goto out;
334 }
335
336 if (!hostapd_cli_cmd_v("set private_key_passwd %s", params->key_passwd)) {
337 goto out;
338 }
339
340 if (hapd_process_eap_user(params, iface->bss[0]->conf)) {
341 goto out;
342 }
343
344 return ret;
345 out:
346 return -1;
347 }
348
hostapd_add_enterprise_creds(const struct device * dev,struct wifi_enterprise_creds_params * creds)349 int hostapd_add_enterprise_creds(const struct device *dev,
350 struct wifi_enterprise_creds_params *creds)
351 {
352 int ret = 0;
353
354 if (!creds) {
355 ret = -1;
356 wpa_printf(MSG_ERROR, "enterprise creds is NULL");
357 goto out;
358 }
359
360 memcpy((void *)&hapd_enterprise_creds, (void *)creds,
361 sizeof(struct wifi_enterprise_creds_params));
362
363 out:
364 return ret;
365 }
366 #endif
367
hostapd_ap_reg_domain(const struct device * dev,struct wifi_reg_domain * reg_domain)368 int hostapd_ap_reg_domain(const struct device *dev,
369 struct wifi_reg_domain *reg_domain)
370 {
371 struct hostapd_iface *iface;
372 int ret = 0;
373
374 iface = get_hostapd_handle(dev);
375 if (iface == NULL) {
376 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
377 ret = -ENODEV;
378 }
379
380 if (iface->state == HAPD_IFACE_ENABLED) {
381 wpa_printf(MSG_ERROR, "Interface %s is operational and in SAP mode", dev->name);
382 ret = -EACCES;
383 }
384
385 if (!hostapd_cli_cmd_v("set country_code %s", reg_domain->country_code)) {
386 ret = -ENOTSUP;
387 }
388
389 return ret;
390 }
391
hapd_config_chan_center_seg0(struct hostapd_iface * iface,struct wifi_connect_req_params * params)392 static int hapd_config_chan_center_seg0(struct hostapd_iface *iface,
393 struct wifi_connect_req_params *params)
394 {
395 int ret = 0;
396 uint8_t center_freq_seg0_idx = 0;
397 uint8_t oper_chwidth = CHANWIDTH_USE_HT;
398 const uint8_t *center_freq = NULL;
399 static const uint8_t center_freq_40MHz[] = {38, 46, 54, 62, 102, 110,
400 118, 126, 134, 142, 151, 159};
401 static const uint8_t center_freq_80MHz[] = {42, 58, 106, 122, 138, 155};
402 uint8_t index, index_max, chan_idx, ch_offset = 0;
403
404 /* Unless ACS is being used, both "channel" and "vht_oper_centr_freq_seg0_idx"
405 * parameters must be set.
406 */
407 switch (params->bandwidth) {
408 case WIFI_FREQ_BANDWIDTH_20MHZ:
409 oper_chwidth = CHANWIDTH_USE_HT;
410 center_freq_seg0_idx = params->channel;
411 break;
412 case WIFI_FREQ_BANDWIDTH_40MHZ:
413 oper_chwidth = CHANWIDTH_USE_HT;
414 center_freq = center_freq_40MHz;
415 index_max = ARRAY_SIZE(center_freq_40MHz);
416 ch_offset = 2;
417 break;
418 case WIFI_FREQ_BANDWIDTH_80MHZ:
419 oper_chwidth = CHANWIDTH_80MHZ;
420 center_freq = center_freq_80MHz;
421 index_max = ARRAY_SIZE(center_freq_80MHz);
422 ch_offset = 6;
423 break;
424 default:
425 return -EINVAL;
426 }
427
428 if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) {
429 chan_idx = params->channel;
430 for (index = 0; index < index_max; index++) {
431 if ((chan_idx >= (center_freq[index] - ch_offset)) &&
432 (chan_idx <= (center_freq[index] + ch_offset))) {
433 center_freq_seg0_idx = center_freq[index];
434 break;
435 }
436 }
437 }
438
439 if (!hostapd_cli_cmd_v("set vht_oper_chwidth %d", oper_chwidth)) {
440 goto out;
441 }
442 if (!hostapd_cli_cmd_v("set vht_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
443 goto out;
444 }
445 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX
446 if (!hostapd_cli_cmd_v("set he_oper_chwidth %d", oper_chwidth)) {
447 goto out;
448 }
449 if (!hostapd_cli_cmd_v("set he_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) {
450 goto out;
451 }
452 #endif
453
454 return ret;
455 out:
456 return -EINVAL;
457 }
458
hapd_config_network(struct hostapd_iface * iface,struct wifi_connect_req_params * params)459 int hapd_config_network(struct hostapd_iface *iface,
460 struct wifi_connect_req_params *params)
461 {
462 int ret = 0;
463
464 if (!hostapd_cli_cmd_v("set ssid %s", params->ssid)) {
465 goto out;
466 }
467
468 if (params->channel == 0) {
469 if (params->band == 0) {
470 if (!hostapd_cli_cmd_v("set hw_mode g")) {
471 goto out;
472 }
473 } else if (params->band == 1) {
474 if (!hostapd_cli_cmd_v("set hw_mode a")) {
475 goto out;
476 }
477 } else {
478 wpa_printf(MSG_ERROR, "Invalid band %d", params->band);
479 goto out;
480 }
481 } else if (params->channel > 14) {
482 if (!hostapd_cli_cmd_v("set hw_mode a")) {
483 goto out;
484 }
485 } else {
486 if (!hostapd_cli_cmd_v("set hw_mode g")) {
487 goto out;
488 }
489 }
490
491 if (!hostapd_cli_cmd_v("set channel %d", params->channel)) {
492 goto out;
493 }
494
495 ret = hapd_config_chan_center_seg0(iface, params);
496 if (ret) {
497 goto out;
498 }
499
500 if (params->security != WIFI_SECURITY_TYPE_NONE) {
501 if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
502 if (!hostapd_cli_cmd_v("set wpa 1")) {
503 goto out;
504 }
505 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
506 goto out;
507 }
508 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
509 goto out;
510 }
511 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
512 goto out;
513 }
514 } else if (params->security == WIFI_SECURITY_TYPE_PSK) {
515 if (!hostapd_cli_cmd_v("set wpa 2")) {
516 goto out;
517 }
518 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) {
519 goto out;
520 }
521 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
522 goto out;
523 }
524 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
525 goto out;
526 }
527 } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) {
528 if (!hostapd_cli_cmd_v("set wpa 2")) {
529 goto out;
530 }
531 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK-SHA256")) {
532 goto out;
533 }
534 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
535 goto out;
536 }
537 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
538 goto out;
539 }
540 } else if (params->security == WIFI_SECURITY_TYPE_SAE_HNP ||
541 params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
542 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
543 if (!hostapd_cli_cmd_v("set wpa 2")) {
544 goto out;
545 }
546 if (!hostapd_cli_cmd_v("set wpa_key_mgmt SAE")) {
547 goto out;
548 }
549 if (!hostapd_cli_cmd_v("set sae_password %s",
550 params->sae_password ? params->sae_password :
551 params->psk)) {
552 goto out;
553 }
554 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
555 goto out;
556 }
557 if (params->security == WIFI_SECURITY_TYPE_SAE_H2E ||
558 params->security == WIFI_SECURITY_TYPE_SAE_AUTO) {
559 if (!hostapd_cli_cmd_v("set sae_pwe %d",
560 (params->security == WIFI_SECURITY_TYPE_SAE_H2E)
561 ? 1
562 : 2)) {
563 goto out;
564 }
565 }
566 } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) {
567 if (!hostapd_cli_cmd_v("set wpa 2")) {
568 goto out;
569 }
570
571 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK SAE")) {
572 goto out;
573 }
574
575 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
576 goto out;
577 }
578
579 if (!hostapd_cli_cmd_v("set sae_password %s",
580 params->sae_password ? params->sae_password
581 : params->psk)) {
582 goto out;
583 }
584
585 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
586 goto out;
587 }
588
589 if (!hostapd_cli_cmd_v("set sae_pwe 2")) {
590 goto out;
591 }
592 } else if (params->security == WIFI_SECURITY_TYPE_DPP) {
593 if (!hostapd_cli_cmd_v("set wpa 2")) {
594 goto out;
595 }
596 if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK DPP")) {
597 goto out;
598 }
599 if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) {
600 goto out;
601 }
602 if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) {
603 goto out;
604 }
605 if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) {
606 goto out;
607 }
608 if (!hostapd_cli_cmd_v("set dpp_configurator_connectivity 1")) {
609 goto out;
610 }
611 #ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
612 } else if (is_eap_valid_security(params->security)) {
613 if (hapd_process_enterprise_config(iface, params)) {
614 goto out;
615 }
616 #endif
617 } else {
618 wpa_printf(MSG_ERROR, "Security type %d is not supported",
619 params->security);
620 goto out;
621 }
622 } else {
623 if (!hostapd_cli_cmd_v("set wpa 0")) {
624 goto out;
625 }
626 iface->bss[0]->conf->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
627 }
628
629 if (!hostapd_cli_cmd_v("set ieee80211w %d", params->mfp)) {
630 goto out;
631 }
632
633 if (!hostapd_cli_cmd_v("set ignore_broadcast_ssid %d", params->ignore_broadcast_ssid)) {
634 goto out;
635 }
636
637 return ret;
638 out:
639 return -1;
640 }
641
set_ap_config_params(const struct device * dev,struct wifi_ap_config_params * params)642 static int set_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
643 {
644 const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);
645
646 if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) {
647 return -ENOTSUP;
648 }
649
650 return wifi_mgmt_api->ap_config_params(dev, params);
651 }
652
hostapd_ap_config_params(const struct device * dev,struct wifi_ap_config_params * params)653 int hostapd_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params)
654 {
655 struct hostapd_iface *iface;
656 int ret = 0;
657
658 ret = set_ap_config_params(dev, params);
659 if (ret && (ret != -ENOTSUP)) {
660 wpa_printf(MSG_ERROR, "Failed to set ap config params");
661 return -EINVAL;
662 }
663
664 k_mutex_lock(&hostapd_mutex, K_FOREVER);
665
666 iface = get_hostapd_handle(dev);
667 if (iface == NULL) {
668 ret = -ENOENT;
669 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
670 goto out;
671 }
672
673 if (iface->state > HAPD_IFACE_DISABLED) {
674 ret = -EBUSY;
675 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
676 goto out;
677 }
678
679 if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) {
680 if (!hostapd_cli_cmd_v("set max_num_sta %d", params->max_num_sta)) {
681 ret = -EINVAL;
682 wpa_printf(MSG_ERROR, "Failed to set maximum number of stations");
683 goto out;
684 }
685 wpa_printf(MSG_INFO, "Set maximum number of stations: %d", params->max_num_sta);
686 }
687
688 if (params->type & WIFI_AP_CONFIG_PARAM_HT_CAPAB) {
689 if (!hostapd_cli_cmd_v("set ht_capab %s", params->ht_capab)) {
690 ret = -EINVAL;
691 wpa_printf(MSG_ERROR, "Failed to set HT capabilities");
692 goto out;
693 }
694 wpa_printf(MSG_INFO, "Set HT capabilities: %s", params->ht_capab);
695 }
696
697 if (params->type & WIFI_AP_CONFIG_PARAM_VHT_CAPAB) {
698 if (!hostapd_cli_cmd_v("set vht_capab %s", params->vht_capab)) {
699 ret = -EINVAL;
700 wpa_printf(MSG_ERROR, "Failed to set VHT capabilities");
701 goto out;
702 }
703 wpa_printf(MSG_INFO, "Set VHT capabilities: %s", params->vht_capab);
704 }
705
706 out:
707 k_mutex_unlock(&hostapd_mutex);
708 return ret;
709 }
710
hostapd_ap_status(const struct device * dev,struct wifi_iface_status * status)711 int hostapd_ap_status(const struct device *dev, struct wifi_iface_status *status)
712 {
713 int ret = 0;
714 struct hostapd_iface *iface;
715 struct hostapd_config *conf;
716 struct hostapd_data *hapd;
717 struct hostapd_bss_config *bss;
718 struct hostapd_ssid *ssid;
719 struct hostapd_hw_modes *hw_mode;
720 int proto; /* Wi-Fi secure protocol */
721 int key_mgmt; /* Wi-Fi key management */
722 int sae_pwe;
723
724 k_mutex_lock(&hostapd_mutex, K_FOREVER);
725
726 iface = get_hostapd_handle(dev);
727 if (!iface) {
728 ret = -1;
729 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
730 goto out;
731 }
732
733 conf = iface->conf;
734 if (!conf) {
735 ret = -1;
736 wpa_printf(MSG_ERROR, "Conf %s not found", dev->name);
737 goto out;
738 }
739
740 bss = conf->bss[0];
741 if (!bss) {
742 ret = -1;
743 wpa_printf(MSG_ERROR, "Bss_conf %s not found", dev->name);
744 goto out;
745 }
746
747 hapd = iface->bss[0];
748 if (!hapd) {
749 ret = -1;
750 wpa_printf(MSG_ERROR, "Bss %s not found", dev->name);
751 goto out;
752 }
753
754 status->state = iface->state;
755 ssid = &bss->ssid;
756
757 os_memcpy(status->bssid, hapd->own_addr, WIFI_MAC_ADDR_LEN);
758 status->iface_mode = WIFI_MODE_AP;
759 status->band = wpas_band_to_zephyr(wpas_freq_to_band(iface->freq));
760 key_mgmt = bss->wpa_key_mgmt;
761 proto = bss->wpa;
762 sae_pwe = bss->sae_pwe;
763 status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt);
764 status->security = wpas_key_mgmt_to_zephyr(1, hapd->conf, key_mgmt, proto, sae_pwe);
765 status->mfp = get_mfp(bss->ieee80211w);
766 status->channel = conf->channel;
767 os_memcpy(status->ssid, ssid->ssid, ssid->ssid_len);
768
769 status->dtim_period = bss->dtim_period;
770 status->beacon_interval = conf->beacon_int;
771
772 hw_mode = iface->current_mode;
773
774 status->link_mode = conf->ieee80211ax ? WIFI_6
775 : conf->ieee80211ac ? WIFI_5
776 : conf->ieee80211n ? WIFI_4
777 : hw_mode->mode == HOSTAPD_MODE_IEEE80211G ? WIFI_3
778 : hw_mode->mode == HOSTAPD_MODE_IEEE80211A ? WIFI_2
779 : hw_mode->mode == HOSTAPD_MODE_IEEE80211B ? WIFI_1
780 : WIFI_0;
781 status->twt_capable = (hw_mode->he_capab[IEEE80211_MODE_AP].mac_cap[0] & 0x04);
782
783 out:
784 k_mutex_unlock(&hostapd_mutex);
785 return ret;
786 }
787
788 #ifdef CONFIG_WIFI_NM_HOSTAPD_WPS
hapd_ap_wps_pbc(const struct device * dev)789 static int hapd_ap_wps_pbc(const struct device *dev)
790 {
791 struct hostapd_iface *iface;
792 int ret = -1;
793
794 k_mutex_lock(&hostapd_mutex, K_FOREVER);
795
796 iface = get_hostapd_handle(dev);
797 if (!iface) {
798 ret = -1;
799 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
800 goto out;
801 }
802
803 if (iface->state != HAPD_IFACE_ENABLED) {
804 ret = -EBUSY;
805 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
806 goto out;
807 }
808
809 if (!hostapd_cli_cmd_v("wps_pbc")) {
810 goto out;
811 }
812
813 ret = 0;
814
815 out:
816 k_mutex_unlock(&hostapd_mutex);
817 return ret;
818 }
819
hapd_ap_wps_pin(const struct device * dev,struct wifi_wps_config_params * params)820 static int hapd_ap_wps_pin(const struct device *dev, struct wifi_wps_config_params *params)
821 {
822 #define WPS_PIN_EXPIRE_TIME 120
823 struct hostapd_iface *iface;
824 char *get_pin_cmd = "WPS_AP_PIN random";
825 int ret = 0;
826
827 k_mutex_lock(&hostapd_mutex, K_FOREVER);
828
829 iface = get_hostapd_handle(dev);
830 if (!iface) {
831 ret = -1;
832 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
833 goto out;
834 }
835
836 if (iface->state != HAPD_IFACE_ENABLED) {
837 ret = -EBUSY;
838 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
839 goto out;
840 }
841
842 if (params->oper == WIFI_WPS_PIN_GET) {
843 if (zephyr_hostapd_cli_cmd_resp(iface->ctrl_conn, get_pin_cmd, params->pin)) {
844 goto out;
845 }
846 } else if (params->oper == WIFI_WPS_PIN_SET) {
847 if (!hostapd_cli_cmd_v("wps_check_pin %s", params->pin)) {
848 goto out;
849 }
850
851 if (!hostapd_cli_cmd_v("wps_pin any %s %d", params->pin, WPS_PIN_EXPIRE_TIME)) {
852 goto out;
853 }
854 } else {
855 wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper);
856 goto out;
857 }
858
859 ret = 0;
860
861 out:
862 k_mutex_unlock(&hostapd_mutex);
863 return ret;
864 }
865
hostapd_ap_wps_config(const struct device * dev,struct wifi_wps_config_params * params)866 int hostapd_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params)
867 {
868 int ret = 0;
869
870 if (params->oper == WIFI_WPS_PBC) {
871 ret = hapd_ap_wps_pbc(dev);
872 } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) {
873 ret = hapd_ap_wps_pin(dev, params);
874 }
875
876 return ret;
877 }
878 #endif
879
hostapd_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)880 int hostapd_ap_enable(const struct device *dev,
881 struct wifi_connect_req_params *params)
882 {
883 struct hostapd_iface *iface;
884 struct hostapd_data *hapd;
885 struct wpa_driver_capa capa;
886 int ret;
887
888 if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) {
889 wpa_printf(MSG_ERROR,
890 "Interface %s is down, dropping connect",
891 dev->name);
892 return -1;
893 }
894
895 ret = set_ap_bandwidth(dev, params->bandwidth);
896 if (ret && (ret != -ENOTSUP)) {
897 wpa_printf(MSG_ERROR, "Failed to set ap bandwidth");
898 return -EINVAL;
899 }
900
901 k_mutex_lock(&hostapd_mutex, K_FOREVER);
902
903 iface = get_hostapd_handle(dev);
904 if (!iface) {
905 ret = -1;
906 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
907 goto out;
908 }
909
910 iface->owner = iface;
911
912 if (iface->state == HAPD_IFACE_ENABLED) {
913 ret = -EBUSY;
914 wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name);
915 goto out;
916 }
917
918 ret = hapd_config_network(iface, params);
919 if (ret) {
920 wpa_printf(MSG_ERROR, "Failed to configure network for AP: %d", ret);
921 goto out;
922 }
923
924 hapd = iface->bss[0];
925 if (!iface->extended_capa || !iface->extended_capa_mask) {
926 if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
927 iface->extended_capa = capa.extended_capa;
928 iface->extended_capa_mask = capa.extended_capa_mask;
929 iface->extended_capa_len = capa.extended_capa_len;
930 iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
931
932 /*
933 * Override extended capa with per-interface type (AP), if
934 * available from the driver.
935 */
936 hostapd_get_ext_capa(iface);
937 } else {
938 ret = -1;
939 wpa_printf(MSG_ERROR, "Failed to get capability for AP: %d", ret);
940 goto out;
941 }
942 }
943
944 if (!hostapd_cli_cmd_v("enable")) {
945 goto out;
946 }
947 out:
948 k_mutex_unlock(&hostapd_mutex);
949 return ret;
950 }
951
hostapd_ap_disable(const struct device * dev)952 int hostapd_ap_disable(const struct device *dev)
953 {
954 struct hostapd_iface *iface;
955 int ret = 0;
956
957 k_mutex_lock(&hostapd_mutex, K_FOREVER);
958
959 iface = get_hostapd_handle(dev);
960 if (!iface) {
961 ret = -ENOENT;
962 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
963 goto out;
964 }
965
966 if (iface->state != HAPD_IFACE_ENABLED) {
967 ret = -EBUSY;
968 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
969 goto out;
970 }
971
972 if (!hostapd_cli_cmd_v("disable")) {
973 goto out;
974 }
975
976 iface->freq = 0;
977
978 out:
979 k_mutex_unlock(&hostapd_mutex);
980 return ret;
981 }
982
hostapd_ap_sta_disconnect(const struct device * dev,const uint8_t * mac_addr)983 int hostapd_ap_sta_disconnect(const struct device *dev,
984 const uint8_t *mac_addr)
985 {
986 struct hostapd_iface *iface;
987 int ret = 0;
988
989 k_mutex_lock(&hostapd_mutex, K_FOREVER);
990
991 iface = get_hostapd_handle(dev);
992 if (!iface) {
993 ret = -1;
994 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
995 goto out;
996 }
997
998 if (iface->state != HAPD_IFACE_ENABLED) {
999 ret = -EBUSY;
1000 wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name);
1001 goto out;
1002 }
1003
1004 if (!mac_addr) {
1005 ret = -EINVAL;
1006 wpa_printf(MSG_ERROR, "Invalid MAC address");
1007 goto out;
1008 }
1009
1010 if (!hostapd_cli_cmd_v("deauthenticate %02x:%02x:%02x:%02x:%02x:%02x",
1011 mac_addr[0], mac_addr[1], mac_addr[2],
1012 mac_addr[3], mac_addr[4], mac_addr[5])) {
1013 goto out;
1014 }
1015
1016 out:
1017 k_mutex_unlock(&hostapd_mutex);
1018 return ret;
1019 }
1020
1021 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
hostapd_dpp_dispatch(const struct device * dev,struct wifi_dpp_params * params)1022 int hostapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params)
1023 {
1024 int ret;
1025 char *cmd = NULL;
1026 struct hostapd_iface *iface;
1027
1028 if (params == NULL) {
1029 return -EINVAL;
1030 }
1031
1032 iface = get_hostapd_handle(dev);
1033 if (!iface) {
1034 wpa_printf(MSG_ERROR, "Interface %s not found", dev->name);
1035 return -ENOENT;
1036 }
1037
1038 cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE);
1039 if (cmd == NULL) {
1040 return -ENOMEM;
1041 }
1042
1043 /* leave one byte always be 0 */
1044 ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2);
1045 if (ret) {
1046 os_free(cmd);
1047 return ret;
1048 }
1049
1050 wpa_printf(MSG_DEBUG, "hostapd_cli %s", cmd);
1051 if (zephyr_hostapd_cli_cmd_resp(iface->ctrl_conn, cmd, params->resp)) {
1052 os_free(cmd);
1053 return -ENOEXEC;
1054 }
1055
1056 os_free(cmd);
1057 return 0;
1058 }
1059 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
1060