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