diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index 3e0bc2ddc4c..c30faaf9e5d 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -249,6 +249,11 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_HOSTAPD_AP ${WIFI_NM_HOSTAPD_BASE}/eap_register.c ${WIFI_NM_HOSTAPD_BASE}/hostapd_cli_cmds.c ${WIFI_NM_HOSTAPD_BASE}/hostapd_cli_zephyr.c + + # Zephyr specific files (glue code) + src/hapd_main.c + src/hapd_api.c + src/hapd_events.c ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_HOSTAPD_AP diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 8dbb3363de5..6fb9aa4a684 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -294,6 +294,7 @@ config WIFI_NM_HOSTAPD_AP config WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE bool "Hostapd crypto enterprise support" + depends on WIFI_NM_HOSTAPD_AP config EAP_SERVER_TLS bool "EAP-TLS server support" diff --git a/modules/hostap/src/hapd_api.c b/modules/hostap/src/hapd_api.c new file mode 100644 index 00000000000..97367d35c53 --- /dev/null +++ b/modules/hostap/src/hapd_api.c @@ -0,0 +1,1032 @@ +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "includes.h" +#include "common.h" +#include "common/defs.h" +#include "wpa_supplicant_i.h" +#include "hostapd.h" +#include "hostapd_cli_zephyr.h" +#include "ap_drv_ops.h" +#include "hapd_main.h" +#include "hapd_api.h" +#include "supp_events.h" +#include "supp_api.h" + +K_MUTEX_DEFINE(hostapd_mutex); + +#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE +static struct wifi_eap_config hapd_eap_config[] = { + {WIFI_SECURITY_TYPE_EAP_TLS, WIFI_EAP_TYPE_TLS, WIFI_EAP_TYPE_NONE, "TLS", NULL}, + {WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_MSCHAPV2, "PEAP", + "auth=MSCHAPV2"}, + {WIFI_SECURITY_TYPE_EAP_PEAP_GTC, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_GTC, "PEAP", + "auth=GTC"}, + {WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2, WIFI_EAP_TYPE_TTLS, WIFI_EAP_TYPE_NONE, "TTLS", + "auth=MSCHAPV2"}, + {WIFI_SECURITY_TYPE_EAP_PEAP_TLS, WIFI_EAP_TYPE_PEAP, WIFI_EAP_TYPE_TLS, "PEAP", + "auth=TLS"}, +}; + +static struct wifi_enterprise_creds_params hapd_enterprise_creds; +#endif + +#define hostapd_cli_cmd_v(cmd, ...) ({ \ + bool status; \ + \ + if (zephyr_hostapd_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \ + wpa_printf(MSG_ERROR, \ + "Failed to execute wpa_cli command: %s", \ + cmd); \ + status = false; \ + } else { \ + status = true; \ + } \ + \ + status; \ +}) + +static inline struct hostapd_iface *get_hostapd_handle(const struct device *dev) +{ + struct net_if *iface = net_if_lookup_by_dev(dev); + char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; + struct hostapd_iface *hapd; + int ret; + + if (!iface) { + wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name); + return NULL; + } + + ret = net_if_get_name(iface, if_name, sizeof(if_name)); + if (!ret) { + wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret); + return NULL; + } + + hapd = zephyr_get_hapd_handle_by_ifname(if_name); + if (!hapd) { + wpa_printf(MSG_ERROR, "Interface %s not found", if_name); + return NULL; + } + + return hapd; +} + +#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE +static int hapd_process_cert_data(struct hostapd_bss_config *conf, + char *type, uint8_t *data, uint32_t data_len) +{ + if (os_strcmp(type, "ca_cert_blob") == 0) { + conf->ca_cert_blob = data; + conf->ca_cert_blob_len = data_len; + } else if (os_strcmp(type, "server_cert_blob") == 0) { + conf->server_cert_blob = data; + conf->server_cert_blob_len = data_len; + } else if (os_strcmp(type, "private_key_blob") == 0) { + conf->private_key_blob = data; + conf->private_key_blob_len = data_len; + } else if (os_strcmp(type, "dh_blob") == 0) { + conf->dh_blob = data; + conf->dh_blob_len = data_len; + } else { + wpa_printf(MSG_ERROR, "input type error"); + return -ENOTSUP; + } + + return 0; +} + +static int hapd_get_eap_config(struct wifi_connect_req_params *params, + struct wifi_eap_config *eap_cfg) +{ + unsigned int index = 0; + + for (index = 0; index < ARRAY_SIZE(hapd_eap_config); index++) { + if (params->security == hapd_eap_config[index].type) { + memcpy(eap_cfg, &hapd_eap_config[index], sizeof(struct wifi_eap_config)); + break; + } + } + + if (index == ARRAY_SIZE(hapd_eap_config)) { + wpa_printf(MSG_ERROR, "Get eap method type with security type: %d", + params->security); + return -ENOTSUP; + } + + return 0; +} + +static struct hostapd_eap_user *hapd_process_eap_user_phase1( + struct wifi_connect_req_params *params, struct hostapd_eap_user **pnew_user) +{ + struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; + struct wifi_eap_config eap_cfg; + + user = os_zalloc(sizeof(*user)); + if (user == NULL) { + wpa_printf(MSG_ERROR, "EAP user allocation failed"); + goto failed; + } + + user->force_version = -1; + if (params->eap_ver >= 0) { + user->force_version = params->eap_ver; + } + + if (hapd_get_eap_config(params, &eap_cfg)) { + goto failed; + } + + user->methods[0].method = eap_cfg.eap_type_phase1; + user->methods[0].vendor = 0; + + if (tail == NULL) { + tail = new_user = user; + } else { + tail->next = user; + tail = user; + } + + *pnew_user = new_user; + + return tail; + +failed: + if (user) { + hostapd_config_free_eap_user(user); + } + + return NULL; +} + +static int hapd_process_eap_user(struct wifi_connect_req_params *params, + struct hostapd_bss_config *conf) +{ + struct hostapd_eap_user *user = NULL, *tail = NULL, *user_list = NULL; + int i, nusers = params->nusers; + const char *identity, *password; + struct wifi_eap_config eap_cfg; + int ret = 0; + + if (hapd_get_eap_config(params, &eap_cfg)) { + goto failed; + } + + if (eap_cfg.phase2 != NULL) { + tail = hapd_process_eap_user_phase1(params, &user_list); + } + + if (eap_cfg.phase2 != NULL && !nusers) { + wpa_printf(MSG_ERROR, "EAP users not found."); + goto failed; + } + + for (i = 0; i < nusers; i++) { + user = os_zalloc(sizeof(*user)); + if (user == NULL) { + wpa_printf(MSG_ERROR, "EAP user allocation failed"); + goto failed; + } + + user->force_version = -1; + if (params->eap_ver >= 0) { + user->force_version = params->eap_ver; + } + + identity = params->identities[i]; + password = params->passwords[i]; + + user->identity = os_memdup(identity, os_strlen(identity)); + if (user->identity == NULL) { + wpa_printf(MSG_ERROR, + "Failed to allocate " + "memory for EAP identity"); + goto failed; + } + user->identity_len = os_strlen(identity); + + user->methods[0].method = eap_cfg.eap_type_phase1; + user->methods[0].vendor = 0; + + if (eap_cfg.phase2 != NULL) { + user->methods[0].method = eap_cfg.eap_type_phase2; + user->password = os_memdup(password, os_strlen(password)); + if (user->password == NULL) { + wpa_printf(MSG_ERROR, + "Failed to allocate " + "memory for EAP password"); + goto failed; + } + user->password_len = os_strlen(password); + + user->phase2 = 1; + } + + if (params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) { + user->ttls_auth |= 0x1E; + } + + if (tail == NULL) { + tail = user_list = user; + } else { + tail->next = user; + tail = user; + } + + continue; + +failed: + if (user) { + hostapd_config_free_eap_user(user); + } + + ret = -1; + break; + } + + if (ret == 0) { + hostapd_config_free_eap_users(conf->eap_user); + conf->eap_user = user_list; + } else { + hostapd_config_free_eap_users(user_list); + } + + return ret; +} + +int hapd_process_enterprise_config(struct hostapd_iface *iface, + struct wifi_connect_req_params *params) +{ + struct wifi_eap_cipher_config cipher_config = { + NULL, "DEFAULT:!EXP:!LOW", "CCMP", "CCMP", "AES-128-CMAC", NULL}; + int ret = 0; + + if (process_cipher_config(params, &cipher_config)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set wpa %d", WPA_PROTO_RSN)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set wpa_key_mgmt %s", cipher_config.key_mgmt)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set rsn_pairwise %s", cipher_config.pairwise_cipher)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set wpa_pairwise %s", cipher_config.pairwise_cipher)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set group_cipher %s", cipher_config.group_cipher)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set group_mgmt_cipher %s", cipher_config.group_mgmt_cipher)) { + goto out; + } + + if (cipher_config.tls_flags != NULL) { + if (!hostapd_cli_cmd_v("set tls_flags %s", cipher_config.tls_flags)) { + goto out; + } + } + + if (!hostapd_cli_cmd_v("set ieee8021x %d", 1)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set eapol_version %d", 2)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set eap_server %d", 1)) { + goto out; + } + + if (hapd_process_cert_data(iface->bss[0]->conf, "ca_cert_blob", + hapd_enterprise_creds.ca_cert, hapd_enterprise_creds.ca_cert_len)) { + goto out; + } + + if (hapd_process_cert_data(iface->bss[0]->conf, "server_cert_blob", + hapd_enterprise_creds.server_cert, hapd_enterprise_creds.server_cert_len)) { + goto out; + } + + if (hapd_process_cert_data(iface->bss[0]->conf, "private_key_blob", + hapd_enterprise_creds.server_key, hapd_enterprise_creds.server_key_len)) { + goto out; + } + + if (hapd_process_cert_data(iface->bss[0]->conf, "dh_blob", + hapd_enterprise_creds.dh_param, hapd_enterprise_creds.dh_param_len)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set private_key_passwd %s", params->key_passwd)) { + goto out; + } + + if (hapd_process_eap_user(params, iface->bss[0]->conf)) { + goto out; + } + + return ret; +out: + return -1; +} + +int hostapd_add_enterprise_creds(const struct device *dev, + struct wifi_enterprise_creds_params *creds) +{ + int ret = 0; + + if (!creds) { + ret = -1; + wpa_printf(MSG_ERROR, "enterprise creds is NULL"); + goto out; + } + + memcpy((void *)&hapd_enterprise_creds, (void *)creds, + sizeof(struct wifi_enterprise_creds_params)); + +out: + return ret; +} +#endif + +bool hostapd_ap_reg_domain(struct wifi_reg_domain *reg_domain) +{ + return hostapd_cli_cmd_v("set country_code %s", reg_domain->country_code); +} + +static int hapd_config_chan_center_seg0(struct wifi_connect_req_params *params) +{ + int ret = 0; + uint8_t center_freq_seg0_idx = 0; + uint8_t oper_chwidth = CHANWIDTH_USE_HT; + const uint8_t *center_freq = NULL; + static const uint8_t center_freq_40MHz[] = {38, 46, 54, 62, 102, 110, + 118, 126, 134, 142, 151, 159}; + static const uint8_t center_freq_80MHz[] = {42, 58, 106, 122, 138, 155}; + uint8_t index, index_max, chan_idx, ch_offset = 0; + + /* Unless ACS is being used, both "channel" and "vht_oper_centr_freq_seg0_idx" + * parameters must be set. + */ + switch (params->bandwidth) { + case WIFI_FREQ_BANDWIDTH_20MHZ: + oper_chwidth = CHANWIDTH_USE_HT; + center_freq_seg0_idx = params->channel; + break; + case WIFI_FREQ_BANDWIDTH_40MHZ: + oper_chwidth = CHANWIDTH_USE_HT; + center_freq = center_freq_40MHz; + index_max = ARRAY_SIZE(center_freq_40MHz); + ch_offset = 2; + break; + case WIFI_FREQ_BANDWIDTH_80MHZ: + oper_chwidth = CHANWIDTH_80MHZ; + center_freq = center_freq_80MHz; + index_max = ARRAY_SIZE(center_freq_80MHz); + ch_offset = 6; + break; + default: + return -EINVAL; + } + + if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) { + chan_idx = params->channel; + for (index = 0; index < index_max; index++) { + if ((chan_idx >= (center_freq[index] - ch_offset)) && + (chan_idx <= (center_freq[index] + ch_offset))) { + center_freq_seg0_idx = center_freq[index]; + break; + } + } + } + + if (!hostapd_cli_cmd_v("set vht_oper_chwidth %d", oper_chwidth)) { + goto out; + } + if (!hostapd_cli_cmd_v("set vht_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) { + goto out; + } +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX + if (!hostapd_cli_cmd_v("set he_oper_chwidth %d", oper_chwidth)) { + goto out; + } + if (!hostapd_cli_cmd_v("set he_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) { + goto out; + } +#endif + + return ret; +out: + return -EINVAL; +} + +int hapd_config_network(struct hostapd_iface *iface, + struct wifi_connect_req_params *params) +{ + int ret = 0; + + if (!hostapd_cli_cmd_v("set ssid %s", params->ssid)) { + goto out; + } + + if (params->channel == 0) { + if (params->band == 0) { + if (!hostapd_cli_cmd_v("set hw_mode g")) { + goto out; + } + } else if (params->band == 1) { + if (!hostapd_cli_cmd_v("set hw_mode a")) { + goto out; + } + } else { + wpa_printf(MSG_ERROR, "Invalid band %d", params->band); + goto out; + } + } else if (params->channel > 14) { + if (!hostapd_cli_cmd_v("set hw_mode a")) { + goto out; + } + } else { + if (!hostapd_cli_cmd_v("set hw_mode g")) { + goto out; + } + } + + if (!hostapd_cli_cmd_v("set channel %d", params->channel)) { + goto out; + } + + ret = hapd_config_chan_center_seg0(params); + if (ret) { + goto out; + } + + if (params->security != WIFI_SECURITY_TYPE_NONE) { + if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) { + if (!hostapd_cli_cmd_v("set wpa 1")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) { + goto out; + } + } else if (params->security == WIFI_SECURITY_TYPE_PSK) { + if (!hostapd_cli_cmd_v("set wpa 2")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { + goto out; + } + if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { + goto out; + } + } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) { + if (!hostapd_cli_cmd_v("set wpa 2")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK-SHA256")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { + goto out; + } + if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { + goto out; + } + } else if (params->security == WIFI_SECURITY_TYPE_SAE_HNP || + params->security == WIFI_SECURITY_TYPE_SAE_H2E || + params->security == WIFI_SECURITY_TYPE_SAE_AUTO) { + if (!hostapd_cli_cmd_v("set wpa 2")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_key_mgmt SAE")) { + goto out; + } + if (!hostapd_cli_cmd_v("set sae_password %s", + params->sae_password ? params->sae_password : + params->psk)) { + goto out; + } + if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { + goto out; + } + if (params->security == WIFI_SECURITY_TYPE_SAE_H2E || + params->security == WIFI_SECURITY_TYPE_SAE_AUTO) { + if (!hostapd_cli_cmd_v("set sae_pwe %d", + (params->security == WIFI_SECURITY_TYPE_SAE_H2E) + ? 1 + : 2)) { + goto out; + } + } + } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) { + if (!hostapd_cli_cmd_v("set wpa 2")) { + goto out; + } + + if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK SAE")) { + goto out; + } + + if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set sae_password %s", + params->sae_password ? params->sae_password + : params->psk)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { + goto out; + } + + if (!hostapd_cli_cmd_v("set sae_pwe 2")) { + goto out; + } + } else if (params->security == WIFI_SECURITY_TYPE_DPP) { + if (!hostapd_cli_cmd_v("set wpa 2")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK DPP")) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { + goto out; + } + if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) { + goto out; + } + if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { + goto out; + } + if (!hostapd_cli_cmd_v("set dpp_configurator_connectivity 1")) { + goto out; + } +#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE + } else if (is_eap_valid_security(params->security)) { + if (hapd_process_enterprise_config(iface, params)) { + goto out; + } +#endif + } else { + wpa_printf(MSG_ERROR, "Security type %d is not supported", + params->security); + goto out; + } + } else { + if (!hostapd_cli_cmd_v("set wpa 0")) { + goto out; + } + iface->bss[0]->conf->wpa_key_mgmt = WPA_KEY_MGMT_NONE; + } + + if (!hostapd_cli_cmd_v("set ieee80211w %d", params->mfp)) { + goto out; + } + + if (!hostapd_cli_cmd_v("set ignore_broadcast_ssid %d", params->ignore_broadcast_ssid)) { + goto out; + } + + return ret; +out: + return -1; +} + +static int set_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params) +{ + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->ap_config_params(dev, params); +} + +int hostapd_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params) +{ + struct hostapd_iface *iface; + int ret = 0; + + ret = set_ap_config_params(dev, params); + if (ret && (ret != -ENOTSUP)) { + wpa_printf(MSG_ERROR, "Failed to set ap config params"); + return -EINVAL; + } + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (iface == NULL) { + ret = -ENOENT; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + if (iface->state > HAPD_IFACE_DISABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name); + goto out; + } + + if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) { + if (!hostapd_cli_cmd_v("set max_num_sta %d", params->max_num_sta)) { + ret = -EINVAL; + wpa_printf(MSG_ERROR, "Failed to set maximum number of stations"); + goto out; + } + wpa_printf(MSG_INFO, "Set maximum number of stations: %d", params->max_num_sta); + } + + if (params->type & WIFI_AP_CONFIG_PARAM_HT_CAPAB) { + if (!hostapd_cli_cmd_v("set ht_capab %s", params->ht_capab)) { + ret = -EINVAL; + wpa_printf(MSG_ERROR, "Failed to set HT capabilities"); + goto out; + } + wpa_printf(MSG_INFO, "Set HT capabilities: %s", params->ht_capab); + } + + if (params->type & WIFI_AP_CONFIG_PARAM_VHT_CAPAB) { + if (!hostapd_cli_cmd_v("set vht_capab %s", params->vht_capab)) { + ret = -EINVAL; + wpa_printf(MSG_ERROR, "Failed to set VHT capabilities"); + goto out; + } + wpa_printf(MSG_INFO, "Set VHT capabilities: %s", params->vht_capab); + } + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +int hostapd_ap_status(const struct device *dev, struct wifi_iface_status *status) +{ + int ret = 0; + struct hostapd_iface *iface; + struct hostapd_config *conf; + struct hostapd_data *hapd; + struct hostapd_bss_config *bss; + struct hostapd_ssid *ssid; + struct hostapd_hw_modes *hw_mode; + int proto; /* Wi-Fi secure protocol */ + int key_mgmt; /* Wi-Fi key management */ + int sae_pwe; + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + conf = iface->conf; + if (!conf) { + ret = -1; + wpa_printf(MSG_ERROR, "Conf %s not found", dev->name); + goto out; + } + + bss = conf->bss[0]; + if (!bss) { + ret = -1; + wpa_printf(MSG_ERROR, "Bss_conf %s not found", dev->name); + goto out; + } + + hapd = iface->bss[0]; + if (!hapd) { + ret = -1; + wpa_printf(MSG_ERROR, "Bss %s not found", dev->name); + goto out; + } + + status->state = iface->state; + ssid = &bss->ssid; + + os_memcpy(status->bssid, hapd->own_addr, WIFI_MAC_ADDR_LEN); + status->iface_mode = WIFI_MODE_AP; + status->band = wpas_band_to_zephyr(wpas_freq_to_band(iface->freq)); + key_mgmt = bss->wpa_key_mgmt; + proto = bss->wpa; + sae_pwe = bss->sae_pwe; + status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt); + status->security = wpas_key_mgmt_to_zephyr(1, hapd->conf, key_mgmt, proto, sae_pwe); + status->mfp = get_mfp(bss->ieee80211w); + status->channel = conf->channel; + os_memcpy(status->ssid, ssid->ssid, ssid->ssid_len); + + status->dtim_period = bss->dtim_period; + status->beacon_interval = conf->beacon_int; + + hw_mode = iface->current_mode; + + status->link_mode = conf->ieee80211ax ? WIFI_6 + : conf->ieee80211ac ? WIFI_5 + : conf->ieee80211n ? WIFI_4 + : hw_mode->mode == HOSTAPD_MODE_IEEE80211G ? WIFI_3 + : hw_mode->mode == HOSTAPD_MODE_IEEE80211A ? WIFI_2 + : hw_mode->mode == HOSTAPD_MODE_IEEE80211B ? WIFI_1 + : WIFI_0; + status->twt_capable = (hw_mode->he_capab[IEEE80211_MODE_AP].mac_cap[0] & 0x04); + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS +static int hapd_ap_wps_pbc(const struct device *dev) +{ + struct hostapd_iface *iface; + int ret = -1; + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + if (iface->state != HAPD_IFACE_ENABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); + goto out; + } + + if (!hostapd_cli_cmd_v("wps_pbc")) { + goto out; + } + + ret = 0; + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +static int hapd_ap_wps_pin(const struct device *dev, struct wifi_wps_config_params *params) +{ +#define WPS_PIN_EXPIRE_TIME 120 + struct hostapd_iface *iface; + char *get_pin_cmd = "WPS_AP_PIN random"; + int ret = 0; + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + if (iface->state != HAPD_IFACE_ENABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); + goto out; + } + + if (params->oper == WIFI_WPS_PIN_GET) { + if (zephyr_hostapd_cli_cmd_resp(get_pin_cmd, params->pin)) { + goto out; + } + } else if (params->oper == WIFI_WPS_PIN_SET) { + if (!hostapd_cli_cmd_v("wps_check_pin %s", params->pin)) { + goto out; + } + + if (!hostapd_cli_cmd_v("wps_pin any %s %d", params->pin, WPS_PIN_EXPIRE_TIME)) { + goto out; + } + } else { + wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper); + goto out; + } + + ret = 0; + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +int hostapd_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params) +{ + int ret = 0; + + if (params->oper == WIFI_WPS_PBC) { + ret = hapd_ap_wps_pbc(dev); + } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) { + ret = hapd_ap_wps_pin(dev, params); + } + + return ret; +} +#endif + +int hostapd_ap_enable(const struct device *dev, + struct wifi_connect_req_params *params) +{ + struct hostapd_iface *iface; + struct hostapd_data *hapd; + struct wpa_driver_capa capa; + int ret; + + if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) { + wpa_printf(MSG_ERROR, + "Interface %s is down, dropping connect", + dev->name); + return -1; + } + + ret = set_ap_bandwidth(dev, params->bandwidth); + if (ret && (ret != -ENOTSUP)) { + wpa_printf(MSG_ERROR, "Failed to set ap bandwidth"); + return -EINVAL; + } + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + iface->owner = iface; + + if (iface->state == HAPD_IFACE_ENABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name); + goto out; + } + + ret = hapd_config_network(iface, params); + if (ret) { + wpa_printf(MSG_ERROR, "Failed to configure network for AP: %d", ret); + goto out; + } + + hapd = iface->bss[0]; + if (!iface->extended_capa || !iface->extended_capa_mask) { + if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { + iface->extended_capa = capa.extended_capa; + iface->extended_capa_mask = capa.extended_capa_mask; + iface->extended_capa_len = capa.extended_capa_len; + iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; + + /* + * Override extended capa with per-interface type (AP), if + * available from the driver. + */ + hostapd_get_ext_capa(iface); + } else { + ret = -1; + wpa_printf(MSG_ERROR, "Failed to get capability for AP: %d", ret); + goto out; + } + } + + if (!hostapd_cli_cmd_v("enable")) { + goto out; + } +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +int hostapd_ap_disable(const struct device *dev) +{ + struct hostapd_iface *iface; + int ret = 0; + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -ENOENT; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + if (iface->state != HAPD_IFACE_ENABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); + goto out; + } + + if (!hostapd_cli_cmd_v("disable")) { + goto out; + } + + iface->freq = 0; + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +int hostapd_ap_sta_disconnect(const struct device *dev, + const uint8_t *mac_addr) +{ + struct hostapd_iface *iface; + int ret = 0; + + k_mutex_lock(&hostapd_mutex, K_FOREVER); + + iface = get_hostapd_handle(dev); + if (!iface) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); + goto out; + } + + if (iface->state != HAPD_IFACE_ENABLED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); + goto out; + } + + if (!mac_addr) { + ret = -EINVAL; + wpa_printf(MSG_ERROR, "Invalid MAC address"); + goto out; + } + + if (!hostapd_cli_cmd_v("deauthenticate %02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5])) { + goto out; + } + +out: + k_mutex_unlock(&hostapd_mutex); + return ret; +} + +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP +int hostapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params) +{ + int ret; + char *cmd = NULL; + + if (params == NULL) { + return -EINVAL; + } + + cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE); + if (cmd == NULL) { + return -ENOMEM; + } + + /* leave one byte always be 0 */ + ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2); + if (ret) { + os_free(cmd); + return ret; + } + + wpa_printf(MSG_DEBUG, "hostapd_cli %s", cmd); + if (zephyr_hostapd_cli_cmd_resp(cmd, params->resp)) { + os_free(cmd); + return -ENOEXEC; + } + + os_free(cmd); + return 0; +} +#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ diff --git a/modules/hostap/src/hapd_api.h b/modules/hostap/src/hapd_api.h new file mode 100644 index 00000000000..cc6f1fe7401 --- /dev/null +++ b/modules/hostap/src/hapd_api.h @@ -0,0 +1,91 @@ +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __HAPD_API_H_ +#define __HAPD_API_H_ + +#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE +int hostapd_add_enterprise_creds(const struct device *dev, + struct wifi_enterprise_creds_params *creds); +#endif + +/** + * @brief Wi-Fi AP configuration parameter. + * + * @param dev Wi-Fi device + * @param params AP parameters + * @return 0 for OK; -1 for ERROR + */ +int hostapd_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params); + +/** + * @brief Set Wi-Fi AP region domain + * + * @param reg_domain region domain parameters + * @return true for OK; false for ERROR + */ +bool hostapd_ap_reg_domain(struct wifi_reg_domain *reg_domain); + +#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS +/** Start AP WPS PBC/PIN + * + * @param dev Pointer to the device structure for the driver instance + * @param params wps operarion parameters + * + * @return 0 if ok, < 0 if error + */ +int hostapd_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params); +#endif + +/** + * @brief Get Wi-Fi SAP status + * + * @param dev Wi-Fi device + * @param status SAP status + * @return 0 for OK; -1 for ERROR + */ +int hostapd_ap_status(const struct device *dev, struct wifi_iface_status *status); + +/** + * @brief Set Wi-Fi AP configuration + * + * @param dev Wi-Fi interface name to use + * @param params AP configuration parameters to set + * @return 0 for OK; -1 for ERROR + */ +int hostapd_ap_enable(const struct device *dev, + struct wifi_connect_req_params *params); + +/** + * @brief Disable Wi-Fi AP + * @param dev Wi-Fi interface name to use + * @return 0 for OK; -1 for ERROR + */ +int hostapd_ap_disable(const struct device *dev); + +/** + * @brief Set Wi-Fi AP STA disconnect + * @param dev Wi-Fi interface name to use + * @param mac_addr MAC address of the station to disconnect + * @return 0 for OK; -1 for ERROR + */ +int hostapd_ap_sta_disconnect(const struct device *dev, + const uint8_t *mac_addr); + +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP +#ifdef CONFIG_WIFI_NM_HOSTAPD_AP +/** + * @brief Dispatch DPP operations for AP + * + * @param dev Wi-Fi interface name to use + * @param dpp_params DPP action enum and params in string + * @return 0 for OK; -1 for ERROR + */ +int hostapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params); +#endif /* CONFIG_WIFI_NM_HOSTAPD_AP */ +#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ + +#endif /* __HAPD_API_H_ */ diff --git a/modules/hostap/src/hapd_events.c b/modules/hostap/src/hapd_events.c new file mode 100644 index 00000000000..c71015f7f92 --- /dev/null +++ b/modules/hostap/src/hapd_events.c @@ -0,0 +1,122 @@ +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "includes.h" +#include "common.h" +#include "ap/sta_info.h" +#include "ap/ieee802_11.h" +#include "ap/hostapd.h" +#include "wpa_supplicant_i.h" +#include +#include "hapd_events.h" +#include "supp_events.h" + +static enum wifi_link_mode hapd_get_sta_link_mode(struct hostapd_iface *iface, + struct sta_info *sta) +{ + if (sta->flags & WLAN_STA_HE) { + return WIFI_6; + } else if (sta->flags & WLAN_STA_VHT) { + return WIFI_5; + } else if (sta->flags & WLAN_STA_HT) { + return WIFI_4; + } else if ((sta->flags & WLAN_STA_NONERP) || + (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B)) { + return WIFI_1; + } else if (iface->freq > 4000) { + return WIFI_2; + } else if (iface->freq > 2000) { + return WIFI_3; + } else { + return WIFI_LINK_MODE_UNKNOWN; + } +} + +static bool hapd_is_twt_capable(struct hostapd_iface *iface, struct sta_info *sta) +{ +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX + return hostapd_get_he_twt_responder(iface->bss[0], IEEE80211_MODE_AP); +#else + return false; +#endif +} + +int hostapd_send_wifi_mgmt_ap_status(struct hostapd_iface *iface, + enum net_event_wifi_cmd event, + enum wifi_ap_status ap_status) +{ + char *ifname = iface->conf->bss[0]->iface; + int status = ap_status; + + return supplicant_send_wifi_mgmt_event(ifname, + event, + (void *)&status, + sizeof(int)); +} + +int hostapd_send_wifi_mgmt_ap_sta_event(struct hostapd_iface *ap_ctx, + enum net_event_wifi_cmd event, + void *data) +{ + struct sta_info *sta = data; + char *ifname = ap_ctx->bss[0]->conf->iface; + struct wifi_ap_sta_info sta_info = { 0 }; + + if (!ap_ctx || !sta) { + return -EINVAL; + } + + memcpy(sta_info.mac, sta->addr, sizeof(sta_info.mac)); + + if (event == NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) { + sta_info.link_mode = hapd_get_sta_link_mode(ap_ctx, sta); + sta_info.twt_capable = hapd_is_twt_capable(ap_ctx, sta); + } + + return supplicant_send_wifi_mgmt_event(ifname, + event, + (void *)&sta_info, + sizeof(sta_info)); +} + +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP +void hostapd_handle_dpp_event(void *ctx, char *buf, size_t len) +{ + struct hostapd_data *hapd = (struct hostapd_data *)ctx; + + if (hapd == NULL) { + return; + } + + struct hostapd_bss_config *conf = hapd->conf; + + if (conf == NULL || !(conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP)) { + return; + } + + /* check hostapd */ + if (!strncmp(buf, DPP_EVENT_CONNECTOR, sizeof(DPP_EVENT_CONNECTOR) - 1)) { + if (conf->dpp_connector) { + os_free(conf->dpp_connector); + } + + conf->dpp_connector = os_strdup(buf + sizeof(DPP_EVENT_CONNECTOR) - 1); + } else if (!strncmp(buf, DPP_EVENT_C_SIGN_KEY, sizeof(DPP_EVENT_C_SIGN_KEY) - 1)) { + if (conf->dpp_csign) { + wpabuf_free(conf->dpp_csign); + } + + conf->dpp_csign = wpabuf_parse_bin(buf + sizeof(DPP_EVENT_C_SIGN_KEY) - 1); + } else if (!strncmp(buf, DPP_EVENT_NET_ACCESS_KEY, sizeof(DPP_EVENT_NET_ACCESS_KEY) - 1)) { + if (conf->dpp_netaccesskey) { + wpabuf_free(conf->dpp_netaccesskey); + } + + conf->dpp_netaccesskey = + wpabuf_parse_bin(buf + sizeof(DPP_EVENT_NET_ACCESS_KEY) - 1); + } +} +#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ diff --git a/modules/hostap/src/hapd_events.h b/modules/hostap/src/hapd_events.h new file mode 100644 index 00000000000..66ea7f6e1cc --- /dev/null +++ b/modules/hostap/src/hapd_events.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __HAPD_EVENTS_H__ +#define __HAPD_EVENTS_H__ + +#include + +int hostapd_send_wifi_mgmt_ap_status(struct hostapd_iface *iface, + enum net_event_wifi_cmd event, + enum wifi_ap_status ap_status); + +int hostapd_send_wifi_mgmt_ap_sta_event(struct hostapd_iface *ap_ctx, + enum net_event_wifi_cmd event, + void *data); + +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP +void hostapd_handle_dpp_event(void *ctx, char *buf, size_t len); +#endif + +#endif /* __HAPD_EVENTS_H_ */ diff --git a/modules/hostap/src/hapd_main.c b/modules/hostap/src/hapd_main.c new file mode 100644 index 00000000000..c11f0d806d7 --- /dev/null +++ b/modules/hostap/src/hapd_main.c @@ -0,0 +1,572 @@ +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "includes.h" +#include "common.h" +#include "eloop.h" +#include "wpa_supplicant_i.h" +#include "hostapd.h" +#include "hostapd_cli_zephyr.h" +#include "eap_register.h" +#include "ap_drv_ops.h" +#include "l2_packet/l2_packet.h" +#include "supp_main.h" +#include "hapd_main.h" +#include "supp_api.h" +#include "hapd_api.h" +#include "hapd_events.h" + +static const struct wifi_mgmt_ops mgmt_ap_ops = { + .ap_enable = hostapd_ap_enable, + .ap_disable = hostapd_ap_disable, + .ap_sta_disconnect = hostapd_ap_sta_disconnect, + .iface_status = hostapd_ap_status, +#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS + .wps_config = hostapd_ap_wps_config, +#endif +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP + .dpp_dispatch = hostapd_dpp_dispatch, +#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ + .ap_config_params = hostapd_ap_config_params, + .set_rts_threshold = supplicant_set_rts_threshold, +#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE + .enterprise_creds = hostapd_add_enterprise_creds, +#endif + .set_btwt = supplicant_set_btwt, +}; + +DEFINE_WIFI_NM_INSTANCE(hostapd, &mgmt_ap_ops); + +struct hapd_global { + void **drv_priv; + size_t drv_count; +}; + +static struct hapd_global hglobal; + +#ifndef HOSTAPD_CLEANUP_INTERVAL +#define HOSTAPD_CLEANUP_INTERVAL 10 +#endif /* HOSTAPD_CLEANUP_INTERVAL */ + +static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx) +{ + hostapd_periodic_iface(iface); + return 0; +} + +/* Periodic cleanup tasks */ +static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) +{ + struct hapd_interfaces *interfaces = eloop_ctx; + + eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, + hostapd_periodic, interfaces, NULL); + hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL); +} + +struct hostapd_iface *zephyr_get_hapd_handle_by_ifname(const char *ifname) +{ + struct hapd_interfaces *interfaces = zephyr_get_default_hapd_context(); + struct hostapd_data *hapd = NULL; + + hapd = hostapd_get_iface(interfaces, ifname); + if (!hapd) { + wpa_printf(MSG_ERROR, "%s: Unable to get hapd handle for %s\n", __func__, ifname); + return NULL; + } + + return hapd->iface; +} + +static void hostapd_event_eapol_rx_cb(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len) +{ + hostapd_event_eapol_rx(ctx, src_addr, buf, len, FRAME_ENCRYPTION_UNKNOWN, -1); +} + +struct hostapd_iface *hostapd_get_interface(const char *ifname) +{ + struct hapd_interfaces *interfaces = zephyr_get_default_hapd_context(); + + return interfaces->iface[0]; +} + +static int hostapd_enable_iface_cb(struct hostapd_iface *hapd_iface) +{ + struct hostapd_data *bss; + + wpa_printf(MSG_DEBUG, "Enable interface %s", hapd_iface->conf->bss[0]->iface); + + bss = hapd_iface->bss[0]; + + bss->conf->start_disabled = 0; + + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_INFO, "Invalid configuration - cannot enable"); + return -1; + } + + l2_packet_deinit(bss->l2); + bss->l2 = l2_packet_init(bss->conf->iface, bss->conf->bssid, ETH_P_EAPOL, + &hostapd_event_eapol_rx_cb, bss, 0); + if (bss->l2 == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize l2 for hostapd interface"); + return -1; + } + + if (hostapd_setup_interface(hapd_iface)) { + wpa_printf(MSG_ERROR, "Failed to initialize hostapd interface"); + return -1; + } + + return 0; +} + +static int hostapd_disable_iface_cb(struct hostapd_iface *hapd_iface) +{ + size_t j; + struct hostapd_data *hapd = NULL; + + wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + + hapd_iface->driver_ap_teardown = !!(hapd_iface->drv_flags + & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + +#ifdef NEED_AP_MLME + for (j = 0; j < hapd_iface->num_bss; j++) { + hostapd_cleanup_cs_params(hapd_iface->bss[j]); + } +#endif /* NEED_AP_MLME */ + + /* Same as hostapd_interface_deinit() without deinitializing control + * interface + */ + for (j = 0; j < hapd_iface->num_bss; j++) { + hapd = hapd_iface->bss[j]; + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } + + hostapd_drv_stop_ap(hapd); + + hostapd_cleanup_iface_partial(hapd_iface); + + wpa_printf(MSG_DEBUG, "Interface %s disabled", hapd_iface->bss[0]->conf->iface); + hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); + hostapd_send_wifi_mgmt_ap_status(hapd_iface, + NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT, + WIFI_STATUS_AP_SUCCESS); + hostapd_config_free(hapd_iface->conf); + hapd_iface->conf = hapd_iface->interfaces->config_read_cb(hapd_iface->config_fname); + for (j = 0; j < hapd_iface->num_bss; j++) { + hapd = hapd_iface->bss[j]; + hapd->iconf = hapd_iface->conf; + hapd->conf = hapd_iface->conf->bss[j]; + hapd->driver = hapd_iface->conf->driver; + } + + return 0; +} + +static int hostapd_global_init(struct hapd_interfaces *interfaces, const char *entropy_file) +{ + int i; + + os_memset(&hglobal, 0, sizeof(struct hapd_global)); + + if (eap_server_register_methods()) { + wpa_printf(MSG_ERROR, "Failed to register EAP methods"); + return -1; + } + + interfaces->eloop_initialized = 1; + + for (i = 0; wpa_drivers[i]; i++) { + hglobal.drv_count++; + } + + if (hglobal.drv_count == 0) { + wpa_printf(MSG_ERROR, "No drivers enabled"); + return -1; + } + hglobal.drv_priv = os_calloc(hglobal.drv_count, sizeof(void *)); + if (hglobal.drv_priv == NULL) { + return -1; + } + + return 0; +} + +const char *zephyr_hostap_msg_ifname_cb(void *ctx) +{ + if (ctx == NULL) { + return NULL; + } + + if ((*((int *)ctx)) == 0) { + struct wpa_supplicant *wpa_s = ctx; + + return wpa_s->ifname; + } + + struct hostapd_data *hapd = ctx; + + if (hapd && hapd->conf) { + return hapd->conf->iface; + } + + return NULL; +} + +void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type, + const char *txt, size_t len) +{ + if (ctx == NULL) { + return; + } + + if ((*((int *)ctx)) == 0) { + wpa_supplicant_msg_send(ctx, level, type, txt, len); + } else { + hostapd_msg_send(ctx, level, type, txt, len); + } +} + +static int hostapd_driver_init(struct hostapd_iface *iface) +{ + struct wpa_init_params params; + size_t i; + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_bss_config *conf = hapd->conf; + u8 *b = conf->bssid; + struct wpa_driver_capa capa; + + if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { + wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); + return -1; + } + + /* Initialize the driver interface */ + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) { + b = NULL; + } + + os_memset(¶ms, 0, sizeof(params)); + for (i = 0; wpa_drivers[i]; i++) { + if (wpa_drivers[i] != hapd->driver) { + continue; + } + + if (hglobal.drv_priv[i] == NULL && wpa_drivers[i]->global_init) { + hglobal.drv_priv[i] = wpa_drivers[i]->global_init(iface->interfaces); + if (hglobal.drv_priv[i] == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize driver '%s'", + wpa_drivers[i]->name); + return -1; + } + hglobal.drv_count++; + } + + params.global_priv = hglobal.drv_priv[i]; + break; + } + params.bssid = b; + params.ifname = hapd->conf->iface; + params.driver_params = hapd->iconf->driver_params; + params.use_pae_group_addr = hapd->conf->use_pae_group_addr; + params.num_bridge = hapd->iface->num_bss; + params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); + if (params.bridge == NULL) { + return -1; + } + for (i = 0; i < hapd->iface->num_bss; i++) { + struct hostapd_data *bss = hapd->iface->bss[i]; + + if (bss->conf->bridge[0]) { + params.bridge[i] = bss->conf->bridge; + } + } + + params.own_addr = hapd->own_addr; + + hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); + os_free(params.bridge); + if (hapd->drv_priv == NULL) { + wpa_printf(MSG_ERROR, "%s driver initialization failed.", + hapd->driver->name); + hapd->driver = NULL; + return -1; + } + + if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { + struct wowlan_triggers *triggs; + + iface->drv_flags = capa.flags; + iface->drv_flags2 = capa.flags2; + iface->probe_resp_offloads = capa.probe_resp_offloads; + /* + * Use default extended capa values from per-radio information + */ + iface->extended_capa = capa.extended_capa; + iface->extended_capa_mask = capa.extended_capa_mask; + iface->extended_capa_len = capa.extended_capa_len; + iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; + + /* + * Override extended capa with per-interface type (AP), if + * available from the driver. + */ + hostapd_get_ext_capa(iface); + + triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); + if (triggs && hapd->driver->set_wowlan) { + if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) { + wpa_printf(MSG_ERROR, "set_wowlan failed"); + } + } + os_free(triggs); + } + + return 0; +} + +struct hostapd_config *hostapd_config_read2(const char *fname) +{ + struct hostapd_config *conf; + const struct device *dev; + char ifname[IFNAMSIZ + 1] = {0}; + int errors = 0; + size_t i; + int aCWmin = 4, aCWmax = 10; + /* background traffic */ + struct hostapd_wmm_ac_params ac_bk = {aCWmin, aCWmax, 9, 0, 0}; + /* best effort traffic */ + struct hostapd_wmm_ac_params ac_be = {aCWmin, aCWmax - 4, 5, 0, 0}; + /* video traffic */ + struct hostapd_wmm_ac_params ac_vi = {aCWmin - 1, aCWmin, 3, + 3008 / 32, 0}; + /* voice traffic */ + struct hostapd_wmm_ac_params ac_vo = {aCWmin - 2, aCWmin - 1, 3, + 1504 / 32, 0}; + + dev = net_if_get_device(net_if_get_wifi_sap()); + strncpy(ifname, dev->name, IFNAMSIZ); + ifname[IFNAMSIZ] = '\0'; + + conf = hostapd_config_defaults(); + if (conf == NULL) { + return NULL; + } + + conf->wmm_ac_params[0] = ac_be; + conf->wmm_ac_params[1] = ac_bk; + conf->wmm_ac_params[2] = ac_vi; + conf->wmm_ac_params[3] = ac_vo; + + /* set default driver based on configuration */ + conf->driver = wpa_drivers[0]; + if (conf->driver == NULL) { + wpa_printf(MSG_ERROR, "No driver wrappers registered!"); + hostapd_config_free(conf); + return NULL; + } + conf->last_bss = conf->bss[0]; + struct hostapd_bss_config *bss; + + bss = conf->last_bss; + bss->start_disabled = 1; + bss->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA; + bss->dtim_period = 1; + os_strlcpy(conf->bss[0]->iface, ifname, sizeof(conf->bss[0]->iface)); + bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; + bss->logger_stdout = 0xffff; + bss->nas_identifier = os_strdup("ap.example.com"); + os_memcpy(conf->country, "US ", 3); + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; + bss->wps_state = WPS_STATE_CONFIGURED; + bss->eap_server = 1; +#ifdef CONFIG_WPS + bss->ap_setup_locked = 1; +#endif + conf->channel = 1; + conf->acs = conf->channel == 0; +#ifdef CONFIG_ACS + conf->acs_num_scans = 1; +#endif + conf->ieee80211n = 1; + conf->ieee80211h = 0; + conf->ieee80211d = 1; + conf->acs_exclude_dfs = 1; + conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; + bss->auth_algs = 1; + bss->okc = 1; + conf->no_pri_sec_switch = 1; + conf->ht_op_mode_fixed = 1; + conf->ieee80211ac = 1; + conf->vht_oper_chwidth = CHANWIDTH_USE_HT; + conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX; +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX + conf->ieee80211ax = 1; + conf->he_oper_chwidth = CHANWIDTH_USE_HT; + conf->he_phy_capab.he_su_beamformer = 0; + conf->he_phy_capab.he_su_beamformee = 1; + conf->he_phy_capab.he_mu_beamformer = 0; + conf->he_op.he_bss_color = 1; + conf->he_op.he_default_pe_duration = 0; + /* Set default basic MCS/NSS set to single stream MCS 0-7 */ + conf->he_op.he_basic_mcs_nss_set = 0xfffc; +#endif + + for (i = 0; i < conf->num_bss; i++) { + hostapd_set_security_params(conf->bss[i], 1); + } + + if (hostapd_config_check(conf, 1)) { + errors++; + } + +#ifndef WPA_IGNORE_CONFIG_ERRORS + if (errors) { + wpa_printf(MSG_ERROR, "%d errors found in configuration file '%s'", + errors, fname); + hostapd_config_free(conf); + conf = NULL; + } +#endif /* WPA_IGNORE_CONFIG_ERRORS */ + return conf; +} + +static struct hostapd_iface *hostapd_interface_init(struct hapd_interfaces *interfaces, + const char *if_name, + const char *config_fname, + int debug) +{ + struct hostapd_iface *iface; + int k; + + wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname); + iface = hostapd_init(interfaces, config_fname); + if (!iface) { + return NULL; + } + + if (if_name) { + os_strlcpy(iface->conf->bss[0]->iface, if_name, + sizeof(iface->conf->bss[0]->iface)); + } + + iface->interfaces = interfaces; + + for (k = 0; k < debug; k++) { + if (iface->bss[0]->conf->logger_stdout_level > 0) { + iface->bss[0]->conf->logger_stdout_level--; + } + } + + if (iface->conf->bss[0]->iface[0] == '\0' && + !hostapd_drv_none(iface->bss[0])) { + wpa_printf(MSG_ERROR, + "Interface name not specified in %s, nor by '-i' parameter", + config_fname); + hostapd_interface_deinit_free(iface); + return NULL; + } + + iface->bss[0]->is_hostapd = 1; + + return iface; +} + +void zephyr_hostapd_init(struct hapd_interfaces *interfaces) +{ + size_t i; + int ret, debug = 0; + struct net_if *iface; + char ifname[IFNAMSIZ + 1] = { 0 }; + const char *entropy_file = NULL; + size_t num_bss_configs = 0; + int start_ifaces_in_sync = 0; +#ifdef CONFIG_DPP + struct dpp_global_config dpp_conf; +#endif /* CONFIG_DPP */ + + os_memset(interfaces, 0, sizeof(struct hapd_interfaces)); + interfaces->reload_config = hostapd_reload_config; + interfaces->config_read_cb = hostapd_config_read2; + interfaces->for_each_interface = hostapd_for_each_interface; + interfaces->driver_init = hostapd_driver_init; + interfaces->global_ctrl_sock = -1; + dl_list_init(&interfaces->global_ctrl_dst); +#ifdef CONFIG_DPP + os_memset(&dpp_conf, 0, sizeof(dpp_conf)); + dpp_conf.cb_ctx = interfaces; + interfaces->dpp = dpp_global_init(&dpp_conf); + if (!interfaces->dpp) { + return; + } +#endif /* CONFIG_DPP */ + + interfaces->count = 1; + if (interfaces->count || num_bss_configs) { + interfaces->iface = os_calloc(interfaces->count + num_bss_configs, + sizeof(struct hostapd_iface *)); + if (interfaces->iface == NULL) { + wpa_printf(MSG_ERROR, "malloc failed"); + return; + } + } + + if (hostapd_global_init(interfaces, entropy_file)) { + wpa_printf(MSG_ERROR, "Failed to initialize global context"); + return; + } + + eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, + hostapd_periodic, interfaces, NULL); + + iface = net_if_get_wifi_sap(); + ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Cannot get interface %d (%p) name", + net_if_get_by_iface(iface), iface); + goto out; + } + + for (i = 0; i < interfaces->count; i++) { + interfaces->iface[i] = hostapd_interface_init(interfaces, ifname, + "hostapd.conf", debug); + if (!interfaces->iface[i]) { + wpa_printf(MSG_ERROR, "Failed to initialize interface"); + goto out; + } + if (start_ifaces_in_sync) { + interfaces->iface[i]->need_to_start_in_sync = 0; + } + } + + /* + * Enable configured interfaces. Depending on channel configuration, + * this may complete full initialization before returning or use a + * callback mechanism to complete setup in case of operations like HT + * co-ex scans, ACS, or DFS are needed to determine channel parameters. + * In such case, the interface will be enabled from eloop context within + * hostapd_global_run(). + */ + interfaces->terminate_on_error = 0; + for (i = 0; i < interfaces->count; i++) { + if (hostapd_driver_init(interfaces->iface[i])) { + goto out; + } + interfaces->iface[i]->enable_iface_cb = hostapd_enable_iface_cb; + interfaces->iface[i]->disable_iface_cb = hostapd_disable_iface_cb; + zephyr_hostapd_ctrl_init((void *)interfaces->iface[i]->bss[0]); + } + +out: + return; +} diff --git a/modules/hostap/src/hapd_main.h b/modules/hostap/src/hapd_main.h new file mode 100644 index 00000000000..6e1d3185abf --- /dev/null +++ b/modules/hostap/src/hapd_main.h @@ -0,0 +1,21 @@ +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __HAPD_MAIN_H_ +#define __HAPD_MAIN_H_ + +#include "common.h" +#include "wpa_debug_zephyr.h" + +struct hostapd_iface *zephyr_get_hapd_handle_by_ifname(const char *ifname); +void wpa_supplicant_msg_send(void *ctx, int level, enum wpa_msg_type type, const char *txt, + size_t len); +void hostapd_msg_send(void *ctx, int level, enum wpa_msg_type type, const char *buf, size_t len); +const char *zephyr_hostap_msg_ifname_cb(void *ctx); +void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type, + const char *txt, size_t len); +void zephyr_hostapd_init(struct hapd_interfaces *interfaces); +#endif /* __HAPD_MAIN_H_ */ diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index ba314b35da1..4b0c156ca46 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -22,15 +22,12 @@ #include "supp_main.h" #include "supp_api.h" #include "wpa_cli_zephyr.h" -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -#include "hostapd.h" -#include "hostapd_cli_zephyr.h" -#include "ap_drv_ops.h" -#endif #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE #include "eap_peer/eap.h" #endif #include "supp_events.h" +#include "hostapd.h" +#include "hapd_api.h" #include "wpa_supplicant/bss.h" extern struct k_sem wpa_supplicant_ready_sem; @@ -125,50 +122,6 @@ static struct wpa_supplicant *get_wpa_s_handle(const struct device *dev) return wpa_s; } -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -#define hostapd_cli_cmd_v(cmd, ...) ({ \ - bool status; \ - \ - if (zephyr_hostapd_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \ - wpa_printf(MSG_ERROR, \ - "Failed to execute wpa_cli command: %s", \ - cmd); \ - status = false; \ - } else { \ - status = true; \ - } \ - \ - status; \ -}) - -static inline struct hostapd_iface *get_hostapd_handle(const struct device *dev) -{ - struct net_if *iface = net_if_lookup_by_dev(dev); - char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; - struct hostapd_iface *hapd; - int ret; - - if (!iface) { - wpa_printf(MSG_ERROR, "Interface for device %s not found", dev->name); - return NULL; - } - - ret = net_if_get_name(iface, if_name, sizeof(if_name)); - if (!ret) { - wpa_printf(MSG_ERROR, "Cannot get interface name (%d)", ret); - return NULL; - } - - hapd = zephyr_get_hapd_handle_by_ifname(if_name); - if (!hapd) { - wpa_printf(MSG_ERROR, "Interface %s not found", if_name); - return NULL; - } - - return hapd; -} -#endif - #define WPA_SUPP_STATE_POLLING_MS 10 static int wait_for_disconnect_complete(const struct device *dev) { @@ -353,7 +306,7 @@ static inline int chan_to_freq(int chan) return freq; } -static inline enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band) +enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band) { switch (band) { case BAND_2_4_GHZ: @@ -365,7 +318,7 @@ static inline enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_ } } -static inline enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt) +enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt) { switch (key_mgmt) { case WPA_KEY_MGMT_IEEE8021X_SUITE_B: @@ -379,8 +332,8 @@ static inline enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(in } } -static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd, - void *config, int key_mgmt, int proto, int pwe) +enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd, void *config, int key_mgmt, + int proto, int pwe) { switch (key_mgmt) { #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE @@ -619,7 +572,7 @@ out: return -EINVAL; } -static int is_eap_valid_security(int security) +int is_eap_valid_security(int security) { return (security == WIFI_SECURITY_TYPE_EAP_TLS || security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 || @@ -629,276 +582,6 @@ static int is_eap_valid_security(int security) } #endif -#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE -static int hapd_process_cert_data(struct hostapd_bss_config *conf, - char *type, uint8_t *data, uint32_t data_len) -{ - if (os_strcmp(type, "ca_cert_blob") == 0) { - conf->ca_cert_blob = data; - conf->ca_cert_blob_len = data_len; - } else if (os_strcmp(type, "server_cert_blob") == 0) { - conf->server_cert_blob = data; - conf->server_cert_blob_len = data_len; - } else if (os_strcmp(type, "private_key_blob") == 0) { - conf->private_key_blob = data; - conf->private_key_blob_len = data_len; - } else if (os_strcmp(type, "dh_blob") == 0) { - conf->dh_blob = data; - conf->dh_blob_len = data_len; - } else { - wpa_printf(MSG_ERROR, "input type error"); - return -ENOTSUP; - } - - return 0; -} - -static int hapd_get_eap_config(struct wifi_connect_req_params *params, - struct wifi_eap_config *eap_cfg) -{ - unsigned int index = 0; - - for (index = 0; index < ARRAY_SIZE(eap_config); index++) { - if (params->security == eap_config[index].type) { - memcpy(eap_cfg, &eap_config[index], sizeof(struct wifi_eap_config)); - break; - } - } - - if (index == ARRAY_SIZE(eap_config)) { - wpa_printf(MSG_ERROR, "Get eap method type with security type: %d", - params->security); - return -ENOTSUP; - } - - return 0; -} - -static struct hostapd_eap_user *hostapd_process_eap_user_phase1( - struct wifi_connect_req_params *params, struct hostapd_eap_user **pnew_user) -{ - struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; - struct wifi_eap_config eap_cfg; - - user = os_zalloc(sizeof(*user)); - if (user == NULL) { - wpa_printf(MSG_ERROR, "EAP user allocation failed"); - goto failed; - } - - user->force_version = -1; - if (params->eap_ver >= 0) { - user->force_version = params->eap_ver; - } - - if (hapd_get_eap_config(params, &eap_cfg)) { - goto failed; - } - - user->methods[0].method = eap_cfg.eap_type_phase1; - user->methods[0].vendor = 0; - - if (tail == NULL) { - tail = new_user = user; - } else { - tail->next = user; - tail = user; - } - - *pnew_user = new_user; - - return tail; - -failed: - if (user) { - hostapd_config_free_eap_user(user); - } - - return NULL; -} - -static int hostapd_process_eap_user(struct wifi_connect_req_params *params, - struct hostapd_bss_config *conf) -{ - struct hostapd_eap_user *user = NULL, *tail = NULL, *user_list = NULL; - int i, nusers = params->nusers; - const char *identity, *password; - struct wifi_eap_config eap_cfg; - int ret = 0; - - if (hapd_get_eap_config(params, &eap_cfg)) { - goto failed; - } - - if (eap_cfg.phase2 != NULL) { - tail = hostapd_process_eap_user_phase1(params, &user_list); - } - - if (eap_cfg.phase2 != NULL && !nusers) { - wpa_printf(MSG_ERROR, "EAP users not found."); - goto failed; - } - - for (i = 0; i < nusers; i++) { - user = os_zalloc(sizeof(*user)); - if (user == NULL) { - wpa_printf(MSG_ERROR, "EAP user allocation failed"); - goto failed; - } - - user->force_version = -1; - if (params->eap_ver >= 0) { - user->force_version = params->eap_ver; - } - - identity = params->identities[i]; - password = params->passwords[i]; - - user->identity = os_memdup(identity, os_strlen(identity)); - if (user->identity == NULL) { - wpa_printf(MSG_ERROR, - "Failed to allocate " - "memory for EAP identity"); - goto failed; - } - user->identity_len = os_strlen(identity); - - user->methods[0].method = eap_cfg.eap_type_phase1; - user->methods[0].vendor = 0; - - if (eap_cfg.phase2 != NULL) { - user->methods[0].method = eap_cfg.eap_type_phase2; - user->password = os_memdup(password, os_strlen(password)); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, - "Failed to allocate " - "memory for EAP password"); - goto failed; - } - user->password_len = os_strlen(password); - - user->phase2 = 1; - } - - if (params->security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2) { - user->ttls_auth |= 0x1E; - } - - if (tail == NULL) { - tail = user_list = user; - } else { - tail->next = user; - tail = user; - } - - continue; - -failed: - if (user) { - hostapd_config_free_eap_user(user); - } - - ret = -1; - break; - } - - if (ret == 0) { - hostapd_config_free_eap_users(conf->eap_user); - conf->eap_user = user_list; - } else { - hostapd_config_free_eap_users(user_list); - } - - return ret; -} - -int hapd_process_enterprise_config(struct hostapd_iface *iface, - struct wifi_connect_req_params *params) -{ - struct wifi_eap_cipher_config cipher_config = { - NULL, "DEFAULT:!EXP:!LOW", "CCMP", "CCMP", "AES-128-CMAC", NULL}; - int ret = 0; - - if (process_cipher_config(params, &cipher_config)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set wpa %d", WPA_PROTO_RSN)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set wpa_key_mgmt %s", cipher_config.key_mgmt)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set rsn_pairwise %s", cipher_config.pairwise_cipher)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set wpa_pairwise %s", cipher_config.pairwise_cipher)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set group_cipher %s", cipher_config.group_cipher)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set group_mgmt_cipher %s", cipher_config.group_mgmt_cipher)) { - goto out; - } - - if (cipher_config.tls_flags != NULL) { - if (!hostapd_cli_cmd_v("set tls_flags %s", cipher_config.tls_flags)) { - goto out; - } - } - - if (!hostapd_cli_cmd_v("set ieee8021x %d", 1)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set eapol_version %d", 2)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set eap_server %d", 1)) { - goto out; - } - - if (hapd_process_cert_data(iface->bss[0]->conf, "ca_cert_blob", - enterprise_creds.ca_cert, enterprise_creds.ca_cert_len)) { - goto out; - } - - if (hapd_process_cert_data(iface->bss[0]->conf, "server_cert_blob", - enterprise_creds.server_cert, enterprise_creds.server_cert_len)) { - goto out; - } - - if (hapd_process_cert_data(iface->bss[0]->conf, "private_key_blob", - enterprise_creds.server_key, enterprise_creds.server_key_len)) { - goto out; - } - - if (hapd_process_cert_data(iface->bss[0]->conf, "dh_blob", - enterprise_creds.dh_param, enterprise_creds.dh_param_len)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set private_key_passwd %s", params->key_passwd)) { - goto out; - } - - if (hostapd_process_eap_user(params, iface->bss[0]->conf)) { - goto out; - } - - return ret; -out: - return -1; -} -#endif - #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE static void wpas_remove_certs(struct wpa_supplicant *wpa_s) { @@ -1529,7 +1212,7 @@ int supplicant_disconnect(const struct device *dev) return wpas_disconnect_network(dev, WPAS_MODE_INFRA); } -static enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option) +enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option) { switch (supp_mfp_option) { case NO_MGMT_FRAME_PROTECTION: @@ -1707,7 +1390,7 @@ out: * supplicant. */ -static const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev) +const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev) { struct net_wifi_mgmt_offload *api = (struct net_wifi_mgmt_offload *)dev->api; @@ -1975,11 +1658,11 @@ int supplicant_reg_domain(const struct device *dev, goto out; } -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - if (!hostapd_cli_cmd_v("set country_code %s", reg_domain->country_code)) { - goto out; + if (IS_ENABLED(CONFIG_WIFI_NM_HOSTAPD_AP)) { + if (!hostapd_ap_reg_domain(reg_domain)) { + goto out; + } } -#endif ret = 0; @@ -2220,677 +1903,78 @@ int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_param } #ifdef CONFIG_AP -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -int hapd_state(const struct device *dev, int *state) +int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth) { - struct hostapd_iface *iface; - int ret = 0; - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); + struct wifi_ap_config_params params = {0}; - iface = get_hostapd_handle(dev); - if (!iface) { - wpa_printf(MSG_ERROR, "Device %s not found", dev->name); - ret = -ENOENT; - goto out; + if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) { + return -ENOTSUP; } - *state = iface->state; - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - return ret; + params.bandwidth = bandwidth; + params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH; + return wifi_mgmt_api->ap_config_params(dev, ¶ms); } -static int hapd_config_chan_center_seg0(struct wifi_connect_req_params *params) +int supplicant_ap_enable(const struct device *dev, + struct wifi_connect_req_params *params) { - int ret = 0; - uint8_t center_freq_seg0_idx = 0; - uint8_t oper_chwidth = CHANWIDTH_USE_HT; - const uint8_t *center_freq = NULL; - static const uint8_t center_freq_40MHz[] = {38, 46, 54, 62, 102, 110, - 118, 126, 134, 142, 151, 159}; - static const uint8_t center_freq_80MHz[] = {42, 58, 106, 122, 138, 155}; - uint8_t index, index_max, chan_idx, ch_offset = 0; - - /* Unless ACS is being used, both "channel" and "vht_oper_centr_freq_seg0_idx" - * parameters must be set. - */ - switch (params->bandwidth) { - case WIFI_FREQ_BANDWIDTH_20MHZ: - oper_chwidth = CHANWIDTH_USE_HT; - center_freq_seg0_idx = params->channel; - break; - case WIFI_FREQ_BANDWIDTH_40MHZ: - oper_chwidth = CHANWIDTH_USE_HT; - center_freq = center_freq_40MHz; - index_max = ARRAY_SIZE(center_freq_40MHz); - ch_offset = 2; - break; - case WIFI_FREQ_BANDWIDTH_80MHZ: - oper_chwidth = CHANWIDTH_80MHZ; - center_freq = center_freq_80MHz; - index_max = ARRAY_SIZE(center_freq_80MHz); - ch_offset = 6; - break; - default: - return -EINVAL; - } + struct wpa_supplicant *wpa_s; + int ret; - if (params->bandwidth != WIFI_FREQ_BANDWIDTH_20MHZ) { - chan_idx = params->channel; - for (index = 0; index < index_max; index++) { - if ((chan_idx >= (center_freq[index] - ch_offset)) && - (chan_idx <= (center_freq[index] + ch_offset))) { - center_freq_seg0_idx = center_freq[index]; - break; - } - } + if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) { + wpa_printf(MSG_ERROR, + "Interface %s is down, dropping connect", + dev->name); + return -1; } - if (!hostapd_cli_cmd_v("set vht_oper_chwidth %d", oper_chwidth)) { - goto out; + ret = set_ap_bandwidth(dev, params->bandwidth); + if (ret && (ret != -ENOTSUP)) { + wpa_printf(MSG_ERROR, "Failed to set ap bandwidth"); + return -EINVAL; } - if (!hostapd_cli_cmd_v("set vht_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) { + + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + + wpa_s = get_wpa_s_handle(dev); + if (!wpa_s) { + ret = -1; + wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); goto out; } -#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX - if (!hostapd_cli_cmd_v("set he_oper_chwidth %d", oper_chwidth)) { + + if (wpa_s->wpa_state != WPA_DISCONNECTED) { + ret = -EBUSY; + wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name); goto out; } - if (!hostapd_cli_cmd_v("set he_oper_centr_freq_seg0_idx %d", center_freq_seg0_idx)) { + + /* No need to check for existing network to join for SoftAP */ + wpa_s->conf->ap_scan = 2; + /* Set BSS parameter max_num_sta to default configured value */ + wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA; + + ret = wpas_add_and_config_network(wpa_s, params, true); + if (ret) { + wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret); goto out; } -#endif - return ret; out: - return -EINVAL; + k_mutex_unlock(&wpa_supplicant_mutex); + + return ret; } -int hapd_config_network(struct hostapd_iface *iface, - struct wifi_connect_req_params *params) +int supplicant_ap_disable(const struct device *dev) { - int ret = 0; - - if (!hostapd_cli_cmd_v("set ssid %s", params->ssid)) { - goto out; - } - - if (params->channel == 0) { - if (params->band == 0) { - if (!hostapd_cli_cmd_v("set hw_mode g")) { - goto out; - } - } else if (params->band == 1) { - if (!hostapd_cli_cmd_v("set hw_mode a")) { - goto out; - } - } else { - wpa_printf(MSG_ERROR, "Invalid band %d", params->band); - goto out; - } - } else if (params->channel > 14) { - if (!hostapd_cli_cmd_v("set hw_mode a")) { - goto out; - } - } else { - if (!hostapd_cli_cmd_v("set hw_mode g")) { - goto out; - } - } - - if (!hostapd_cli_cmd_v("set channel %d", params->channel)) { - goto out; - } - - ret = hapd_config_chan_center_seg0(params); - if (ret) { - goto out; - } - - if (params->security != WIFI_SECURITY_TYPE_NONE) { - if (params->security == WIFI_SECURITY_TYPE_WPA_PSK) { - if (!hostapd_cli_cmd_v("set wpa 1")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) { - goto out; - } - } else if (params->security == WIFI_SECURITY_TYPE_PSK) { - if (!hostapd_cli_cmd_v("set wpa 2")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { - goto out; - } - if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { - goto out; - } - } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) { - if (!hostapd_cli_cmd_v("set wpa 2")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK-SHA256")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { - goto out; - } - if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { - goto out; - } - } else if (params->security == WIFI_SECURITY_TYPE_SAE_HNP || - params->security == WIFI_SECURITY_TYPE_SAE_H2E || - params->security == WIFI_SECURITY_TYPE_SAE_AUTO) { - if (!hostapd_cli_cmd_v("set wpa 2")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_key_mgmt SAE")) { - goto out; - } - if (!hostapd_cli_cmd_v("set sae_password %s", - params->sae_password ? params->sae_password : - params->psk)) { - goto out; - } - if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { - goto out; - } - if (params->security == WIFI_SECURITY_TYPE_SAE_H2E || - params->security == WIFI_SECURITY_TYPE_SAE_AUTO) { - if (!hostapd_cli_cmd_v("set sae_pwe %d", - (params->security == WIFI_SECURITY_TYPE_SAE_H2E) - ? 1 - : 2)) { - goto out; - } - } - } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) { - if (!hostapd_cli_cmd_v("set wpa 2")) { - goto out; - } - - if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK SAE")) { - goto out; - } - - if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set sae_password %s", - params->sae_password ? params->sae_password - : params->psk)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { - goto out; - } - - if (!hostapd_cli_cmd_v("set sae_pwe 2")) { - goto out; - } - } else if (params->security == WIFI_SECURITY_TYPE_DPP) { - if (!hostapd_cli_cmd_v("set wpa 2")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_key_mgmt WPA-PSK DPP")) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_passphrase %s", params->psk)) { - goto out; - } - if (!hostapd_cli_cmd_v("set wpa_pairwise CCMP")) { - goto out; - } - if (!hostapd_cli_cmd_v("set rsn_pairwise CCMP")) { - goto out; - } - if (!hostapd_cli_cmd_v("set dpp_configurator_connectivity 1")) { - goto out; - } -#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE - } else if (is_eap_valid_security(params->security)) { - if (hapd_process_enterprise_config(iface, params)) { - goto out; - } -#endif - } else { - wpa_printf(MSG_ERROR, "Security type %d is not supported", - params->security); - goto out; - } - } else { - if (!hostapd_cli_cmd_v("set wpa 0")) { - goto out; - } - iface->bss[0]->conf->wpa_key_mgmt = WPA_KEY_MGMT_NONE; - } - - if (!hostapd_cli_cmd_v("set ieee80211w %d", params->mfp)) { - goto out; - } - - if (!hostapd_cli_cmd_v("set ignore_broadcast_ssid %d", params->ignore_broadcast_ssid)) { - goto out; - } - - return ret; -out: - return -1; -} - -static int set_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params) -{ - const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); - - if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) { - return -ENOTSUP; - } - - return wifi_mgmt_api->ap_config_params(dev, params); -} - -int supplicant_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params) -{ - struct hostapd_iface *iface; - int ret = 0; - - ret = set_ap_config_params(dev, params); - if (ret && (ret != -ENOTSUP)) { - wpa_printf(MSG_ERROR, "Failed to set ap config params"); - return -EINVAL; - } - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - - iface = get_hostapd_handle(dev); - if (iface == NULL) { - ret = -ENOENT; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (iface->state > HAPD_IFACE_DISABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name); - goto out; - } - - if (params->type & WIFI_AP_CONFIG_PARAM_MAX_NUM_STA) { - if (!hostapd_cli_cmd_v("set max_num_sta %d", params->max_num_sta)) { - ret = -EINVAL; - wpa_printf(MSG_ERROR, "Failed to set maximum number of stations"); - goto out; - } - wpa_printf(MSG_INFO, "Set maximum number of stations: %d", params->max_num_sta); - } - - if (params->type & WIFI_AP_CONFIG_PARAM_HT_CAPAB) { - if (!hostapd_cli_cmd_v("set ht_capab %s", params->ht_capab)) { - ret = -EINVAL; - wpa_printf(MSG_ERROR, "Failed to set HT capabilities"); - goto out; - } - wpa_printf(MSG_INFO, "Set HT capabilities: %s", params->ht_capab); - } - - if (params->type & WIFI_AP_CONFIG_PARAM_VHT_CAPAB) { - if (!hostapd_cli_cmd_v("set vht_capab %s", params->vht_capab)) { - ret = -EINVAL; - wpa_printf(MSG_ERROR, "Failed to set VHT capabilities"); - goto out; - } - wpa_printf(MSG_INFO, "Set VHT capabilities: %s", params->vht_capab); - } - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - - return ret; -} - -int supplicant_ap_status(const struct device *dev, struct wifi_iface_status *status) -{ - int ret = 0; - struct hostapd_iface *iface; - struct hostapd_config *conf; - struct hostapd_data *hapd; - struct hostapd_bss_config *bss; - struct hostapd_ssid *ssid; - struct hostapd_hw_modes *hw_mode; - int proto; /* Wi-Fi secure protocol */ - int key_mgmt; /* Wi-Fi key management */ - int sae_pwe; - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - conf = iface->conf; - if (!conf) { - ret = -1; - wpa_printf(MSG_ERROR, "Conf %s not found", dev->name); - goto out; - } - - bss = conf->bss[0]; - if (!bss) { - ret = -1; - wpa_printf(MSG_ERROR, "Bss_conf %s not found", dev->name); - goto out; - } - - hapd = iface->bss[0]; - if (!hapd) { - ret = -1; - wpa_printf(MSG_ERROR, "Bss %s not found", dev->name); - goto out; - } - - status->state = iface->state; - ssid = &bss->ssid; - - os_memcpy(status->bssid, hapd->own_addr, WIFI_MAC_ADDR_LEN); - status->iface_mode = WIFI_MODE_AP; - status->band = wpas_band_to_zephyr(wpas_freq_to_band(iface->freq)); - key_mgmt = bss->wpa_key_mgmt; - proto = bss->wpa; - sae_pwe = bss->sae_pwe; - status->wpa3_ent_type = wpas_key_mgmt_to_zephyr_wpa3_ent(key_mgmt); - status->security = wpas_key_mgmt_to_zephyr(1, hapd->conf, key_mgmt, proto, sae_pwe); - status->mfp = get_mfp(bss->ieee80211w); - status->channel = conf->channel; - os_memcpy(status->ssid, ssid->ssid, ssid->ssid_len); - - status->dtim_period = bss->dtim_period; - status->beacon_interval = conf->beacon_int; - - hw_mode = iface->current_mode; - - status->link_mode = conf->ieee80211ax ? WIFI_6 - : conf->ieee80211ac ? WIFI_5 - : conf->ieee80211n ? WIFI_4 - : hw_mode->mode == HOSTAPD_MODE_IEEE80211G ? WIFI_3 - : hw_mode->mode == HOSTAPD_MODE_IEEE80211A ? WIFI_2 - : hw_mode->mode == HOSTAPD_MODE_IEEE80211B ? WIFI_1 - : WIFI_0; - status->twt_capable = (hw_mode->he_capab[IEEE80211_MODE_AP].mac_cap[0] & 0x04); - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - return ret; -} -#endif /* CONFIG_WIFI_NM_HOSTAPD_AP */ - -#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS -int supplicant_ap_wps_pbc(const struct device *dev) -{ - struct hostapd_iface *iface; - int ret = -1; + struct wpa_supplicant *wpa_s; + int ret = -1; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (iface->state != HAPD_IFACE_ENABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); - goto out; - } - - if (!hostapd_cli_cmd_v("wps_pbc")) { - goto out; - } - - wpas_api_ctrl.dev = dev; - wpas_api_ctrl.requested_op = WPS_PBC; - - ret = 0; - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - - return ret; -} - -int supplicant_ap_wps_pin(const struct device *dev, struct wifi_wps_config_params *params) -{ -#define WPS_PIN_EXPIRE_TIME 120 - struct hostapd_iface *iface; - char *get_pin_cmd = "WPS_AP_PIN random"; - int ret = 0; - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (iface->state != HAPD_IFACE_ENABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); - goto out; - } - - if (params->oper == WIFI_WPS_PIN_GET) { - if (zephyr_hostapd_cli_cmd_resp(get_pin_cmd, params->pin)) { - goto out; - } - } else if (params->oper == WIFI_WPS_PIN_SET) { - if (!hostapd_cli_cmd_v("wps_check_pin %s", params->pin)) { - goto out; - } - - if (!hostapd_cli_cmd_v("wps_pin any %s %d", params->pin, WPS_PIN_EXPIRE_TIME)) { - goto out; - } - - wpas_api_ctrl.dev = dev; - wpas_api_ctrl.requested_op = WPS_PIN; - } else { - wpa_printf(MSG_ERROR, "Error wps pin operation : %d", params->oper); - goto out; - } - - ret = 0; - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - - return ret; -} - - -int supplicant_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params) -{ - int ret = 0; - - if (params->oper == WIFI_WPS_PBC) { - ret = supplicant_ap_wps_pbc(dev); - } else if (params->oper == WIFI_WPS_PIN_GET || params->oper == WIFI_WPS_PIN_SET) { - ret = supplicant_ap_wps_pin(dev, params); - } - - return ret; -} -#endif - -static int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth) -{ - const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); - struct wifi_ap_config_params params = {0}; - - if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_config_params == NULL) { - return -ENOTSUP; - } - - params.bandwidth = bandwidth; - params.type = WIFI_AP_CONFIG_PARAM_BANDWIDTH; - return wifi_mgmt_api->ap_config_params(dev, ¶ms); -} - -int supplicant_ap_enable(const struct device *dev, - struct wifi_connect_req_params *params) -{ -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - struct hostapd_iface *iface; - struct hostapd_data *hapd; - struct wpa_driver_capa capa; -#else - struct wpa_supplicant *wpa_s; -#endif - int ret; - - if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) { - wpa_printf(MSG_ERROR, - "Interface %s is down, dropping connect", - dev->name); - return -1; - } - - ret = set_ap_bandwidth(dev, params->bandwidth); - if (ret && (ret != -ENOTSUP)) { - wpa_printf(MSG_ERROR, "Failed to set ap bandwidth"); - return -EINVAL; - } - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - iface->owner = iface; - - if (iface->state == HAPD_IFACE_ENABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in disable state", dev->name); - goto out; - } - - ret = hapd_config_network(iface, params); - if (ret) { - wpa_printf(MSG_ERROR, "Failed to configure network for AP: %d", ret); - goto out; - } - - hapd = iface->bss[0]; - if (!iface->extended_capa || !iface->extended_capa_mask) { - if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { - iface->extended_capa = capa.extended_capa; - iface->extended_capa_mask = capa.extended_capa_mask; - iface->extended_capa_len = capa.extended_capa_len; - iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; - - /* - * Override extended capa with per-interface type (AP), if - * available from the driver. - */ - hostapd_get_ext_capa(iface); - } else { - ret = -1; - wpa_printf(MSG_ERROR, "Failed to get capability for AP: %d", ret); - goto out; - } - } - - if (!hostapd_cli_cmd_v("enable")) { - goto out; - } - -#else - wpa_s = get_wpa_s_handle(dev); - if (!wpa_s) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (wpa_s->wpa_state != WPA_DISCONNECTED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in disconnected state", dev->name); - goto out; - } - - /* No need to check for existing network to join for SoftAP */ - wpa_s->conf->ap_scan = 2; - /* Set BSS parameter max_num_sta to default configured value */ - wpa_s->conf->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA; - - ret = wpas_add_and_config_network(wpa_s, params, true); - if (ret) { - wpa_printf(MSG_ERROR, "Failed to add and configure network for AP mode: %d", ret); - goto out; - } -#endif - -out: - k_mutex_unlock(&wpa_supplicant_mutex); - - return ret; -} - -int supplicant_ap_disable(const struct device *dev) -{ -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - struct hostapd_iface *iface; - int ret = 0; -#else - struct wpa_supplicant *wpa_s; - int ret = -1; -#endif - - k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -ENOENT; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (iface->state != HAPD_IFACE_ENABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); - goto out; - } - - if (!hostapd_cli_cmd_v("disable")) { - goto out; - } - - iface->freq = 0; -#else wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { ret = -1; @@ -2906,7 +1990,6 @@ int supplicant_ap_disable(const struct device *dev) /* Restore ap_scan to default value */ wpa_s->conf->ap_scan = 1; -#endif out: k_mutex_unlock(&wpa_supplicant_mutex); @@ -2916,43 +1999,11 @@ out: int supplicant_ap_sta_disconnect(const struct device *dev, const uint8_t *mac_addr) { -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - struct hostapd_iface *iface; - int ret = 0; -#else struct wpa_supplicant *wpa_s; int ret = -1; -#endif k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - iface = get_hostapd_handle(dev); - if (!iface) { - ret = -1; - wpa_printf(MSG_ERROR, "Interface %s not found", dev->name); - goto out; - } - - if (iface->state != HAPD_IFACE_ENABLED) { - ret = -EBUSY; - wpa_printf(MSG_ERROR, "Interface %s is not in enable state", dev->name); - goto out; - } - - if (!mac_addr) { - ret = -EINVAL; - wpa_printf(MSG_ERROR, "Invalid MAC address"); - goto out; - } - - if (!hostapd_cli_cmd_v("deauthenticate %02x:%02x:%02x:%02x:%02x:%02x", - mac_addr[0], mac_addr[1], mac_addr[2], - mac_addr[3], mac_addr[4], mac_addr[5])) { - goto out; - } - -#else wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { ret = -1; @@ -2973,7 +2024,6 @@ int supplicant_ap_sta_disconnect(const struct device *dev, } ret = 0; -#endif out: k_mutex_unlock(&wpa_supplicant_mutex); @@ -3049,10 +2099,9 @@ static void dpp_ssid_bin2str(char *dst, uint8_t *src, int max_len) } } -#define SUPPLICANT_DPP_CMD_BUF_SIZE 384 #define STR_CUR_TO_END(cur) (cur) = (&(cur)[0] + strlen((cur))) -static int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len) +int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len) { char *pos = cmd; char *end = cmd + max_len; @@ -3272,37 +2321,4 @@ int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *pa os_free(cmd); return 0; } - -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -int hapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params) -{ - int ret; - char *cmd = NULL; - - if (params == NULL) { - return -EINVAL; - } - - cmd = os_zalloc(SUPPLICANT_DPP_CMD_BUF_SIZE); - if (cmd == NULL) { - return -ENOMEM; - } - - /* leave one byte always be 0 */ - ret = dpp_params_to_cmd(params, cmd, SUPPLICANT_DPP_CMD_BUF_SIZE - 2); - if (ret) { - os_free(cmd); - return ret; - } - - wpa_printf(MSG_DEBUG, "hostapd_cli %s", cmd); - if (zephyr_hostapd_cli_cmd_resp(cmd, params->resp)) { - os_free(cmd); - return -ENOEXEC; - } - - os_free(cmd); - return 0; -} -#endif /* CONFIG_WIFI_NM_HOSTAPD_AP */ #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index cb4e7836f1c..ddd3c3d6698 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -8,6 +8,7 @@ #ifndef ZEPHYR_SUPP_MGMT_H #define ZEPHYR_SUPP_MGMT_H +#include #include #ifndef MAX_SSID_LEN @@ -20,6 +21,17 @@ #define MAC_STR_LEN 18 /* for ':' or '-' separated MAC address string */ #define CHAN_NUM_LEN 6 /* for space-separated channel numbers string */ +enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band); + +enum wifi_wpa3_enterprise_type wpas_key_mgmt_to_zephyr_wpa3_ent(int key_mgmt); + +enum wifi_security_type wpas_key_mgmt_to_zephyr(bool is_hapd, void *config, + int key_mgmt, int proto, int pwe); + +const struct wifi_mgmt_ops *const get_wifi_mgmt_api(const struct device *dev); + +enum wifi_mfp_options get_mfp(enum mfp_options supp_mfp_option); + /** * @brief Get version * @@ -194,6 +206,11 @@ int supplicant_mode(const struct device *dev, struct wifi_mode_info *mode); #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \ defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE +int is_eap_valid_security(int security); + +int process_cipher_config(struct wifi_connect_req_params *params, + struct wifi_eap_cipher_config *cipher_config); + /** Set Wi-Fi enterprise mode CA/client Cert and key * * @param dev Pointer to the device structure for the driver instance @@ -289,50 +306,7 @@ int supplicant_get_wifi_conn_params(const struct device *dev, int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params); #ifdef CONFIG_AP -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -/** - * @brief Get Wi-Fi AP Status - * - * @param dev Wi-Fi device - * @param params AP status - * @return 0 for OK; -1 for ERROR - */ -int hapd_state(const struct device *dev, int *state); - -/** - * @brief Wi-Fi AP configuration parameter. - * - * @param dev Wi-Fi device - * @param params AP parameters - * @return 0 for OK; -1 for ERROR - */ -int supplicant_ap_config_params(const struct device *dev, struct wifi_ap_config_params *params); -#else -static inline int hapd_state(const struct device *dev, int *state) -{ - return -EINVAL; -} -#endif - -#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS -/** Start AP WPS PBC/PIN - * - * @param dev Pointer to the device structure for the driver instance - * @param params wps operarion parameters - * - * @return 0 if ok, < 0 if error - */ -int supplicant_ap_wps_config(const struct device *dev, struct wifi_wps_config_params *params); -#endif - -/** - * @brief Get Wi-Fi SAP status - * - * @param dev Wi-Fi device - * @param status SAP status - * @return 0 for OK; -1 for ERROR - */ -int supplicant_ap_status(const struct device *dev, struct wifi_iface_status *status); +int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth); /** * @brief Set Wi-Fi AP configuration @@ -363,6 +337,10 @@ int supplicant_ap_sta_disconnect(const struct device *dev, #endif /* CONFIG_AP */ #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP +#define SUPPLICANT_DPP_CMD_BUF_SIZE 384 + +int dpp_params_to_cmd(struct wifi_dpp_params *params, char *cmd, size_t max_len); + /** * @brief Dispatch DPP operations for STA * @@ -371,16 +349,5 @@ int supplicant_ap_sta_disconnect(const struct device *dev, * @return 0 for OK; -1 for ERROR */ int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params); - -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -/** - * @brief Dispatch DPP operations for AP - * - * @param dev Wi-Fi interface name to use - * @param dpp_params DPP action enum and params in string - * @return 0 for OK; -1 for ERROR - */ -int hapd_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *params); -#endif /* CONFIG_WIFI_NM_HOSTAPD_AP */ #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ #endif /* ZEPHYR_SUPP_MGMT_H */ diff --git a/modules/hostap/src/supp_events.c b/modules/hostap/src/supp_events.c index 22b406e2fdc..596ffa6ff56 100644 --- a/modules/hostap/src/supp_events.c +++ b/modules/hostap/src/supp_events.c @@ -252,11 +252,7 @@ int supplicant_send_wifi_mgmt_disc_event(void *ctx, int reason_code) } #ifdef CONFIG_AP -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -static enum wifi_link_mode get_sta_link_mode(struct hostapd_iface *iface, struct sta_info *sta) -#else static enum wifi_link_mode get_sta_link_mode(struct wpa_supplicant *wpa_s, struct sta_info *sta) -#endif { if (sta->flags & WLAN_STA_HE) { return WIFI_6; @@ -264,37 +260,17 @@ static enum wifi_link_mode get_sta_link_mode(struct wpa_supplicant *wpa_s, struc return WIFI_5; } else if (sta->flags & WLAN_STA_HT) { return WIFI_4; -#ifndef CONFIG_WIFI_NM_HOSTAPD_AP } else if (sta->flags & WLAN_STA_NONERP) { return WIFI_1; } else if (wpa_s->assoc_freq > 4000) { return WIFI_2; } else if (wpa_s->assoc_freq > 2000) { return WIFI_3; -#else - } else if ((sta->flags & WLAN_STA_NONERP) || - (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B)) { - return WIFI_1; - } else if (iface->freq > 4000) { - return WIFI_2; - } else if (iface->freq > 2000) { - return WIFI_3; -#endif } else { return WIFI_LINK_MODE_UNKNOWN; } } -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -static bool is_twt_capable(struct hostapd_iface *iface, struct sta_info *sta) -{ -#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX - return hostapd_get_he_twt_responder(iface->bss[0], IEEE80211_MODE_AP); -#else - return false; -#endif -} -#else static bool is_twt_capable(struct wpa_supplicant *wpa_s, struct sta_info *sta) { #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX @@ -303,19 +279,13 @@ static bool is_twt_capable(struct wpa_supplicant *wpa_s, struct sta_info *sta) return false; #endif } -#endif int supplicant_send_wifi_mgmt_ap_status(void *ctx, enum net_event_wifi_cmd event, enum wifi_ap_status ap_status) { -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - struct hostapd_iface *iface = ctx; - char *ifname = iface->conf->bss[0]->iface; -#else struct wpa_supplicant *wpa_s = ctx; char *ifname = wpa_s->ifname; -#endif int status = ap_status; return supplicant_send_wifi_mgmt_event(ifname, @@ -329,13 +299,8 @@ int supplicant_send_wifi_mgmt_ap_sta_event(void *ctx, void *data) { struct sta_info *sta = data; -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP - struct hostapd_iface *ap_ctx = ctx; - char *ifname = ap_ctx->bss[0]->conf->iface; -#else struct wpa_supplicant *ap_ctx = ctx; char *ifname = ap_ctx->ifname; -#endif struct wifi_ap_sta_info sta_info = { 0 }; if (!ap_ctx || !sta) { @@ -463,42 +428,3 @@ int supplicant_generate_state_event(const char *ifname, return 0; } - -#if defined(CONFIG_WIFI_NM_HOSTAPD_AP) && defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP) -void hostapd_handle_dpp_event(void *ctx, char *buf, size_t len) -{ - struct hostapd_data *hapd = (struct hostapd_data *)ctx; - - if (hapd == NULL) { - return; - } - - struct hostapd_bss_config *conf = hapd->conf; - - if (conf == NULL || !(conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP)) { - return; - } - - /* check hostapd */ - if (!strncmp(buf, DPP_EVENT_CONNECTOR, sizeof(DPP_EVENT_CONNECTOR) - 1)) { - if (conf->dpp_connector) { - os_free(conf->dpp_connector); - } - - conf->dpp_connector = os_strdup(buf + sizeof(DPP_EVENT_CONNECTOR) - 1); - } else if (!strncmp(buf, DPP_EVENT_C_SIGN_KEY, sizeof(DPP_EVENT_C_SIGN_KEY) - 1)) { - if (conf->dpp_csign) { - wpabuf_free(conf->dpp_csign); - } - - conf->dpp_csign = wpabuf_parse_bin(buf + sizeof(DPP_EVENT_C_SIGN_KEY) - 1); - } else if (!strncmp(buf, DPP_EVENT_NET_ACCESS_KEY, sizeof(DPP_EVENT_NET_ACCESS_KEY) - 1)) { - if (conf->dpp_netaccesskey) { - wpabuf_free(conf->dpp_netaccesskey); - } - - conf->dpp_netaccesskey = - wpabuf_parse_bin(buf + sizeof(DPP_EVENT_NET_ACCESS_KEY) - 1); - } -} -#endif /* CONFIG_WIFI_NM_HOSTAPD_AP && CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ diff --git a/modules/hostap/src/supp_events.h b/modules/hostap/src/supp_events.h index 308a9e49734..dc922940d78 100644 --- a/modules/hostap/src/supp_events.h +++ b/modules/hostap/src/supp_events.h @@ -63,9 +63,6 @@ int supplicant_send_wifi_mgmt_ap_sta_event(void *ctx, enum net_event_wifi_cmd event, void *data); #endif /* CONFIG_AP */ -#if defined(CONFIG_WIFI_NM_HOSTAPD_AP) && defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP) -void hostapd_handle_dpp_event(void *ctx, char *buf, size_t len); -#endif #define REASON_CODE_LEN 18 #define NM_WIFI_EVENT_STR_LEN 64 diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 8b847e0a70e..120050a75c7 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -46,10 +46,7 @@ static K_THREAD_STACK_DEFINE(iface_wq_stack, CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_ST #include "wpa_cli_zephyr.h" #ifdef CONFIG_WIFI_NM_HOSTAPD_AP #include "hostapd.h" -#include "hostapd_cli_zephyr.h" -#include "eap_register.h" -#include "ap_drv_ops.h" -#include "l2_packet/l2_packet.h" +#include "hapd_main.h" #endif static const struct wifi_mgmt_ops mgmt_ops = { @@ -100,29 +97,6 @@ static const struct wifi_mgmt_ops mgmt_ops = { DEFINE_WIFI_NM_INSTANCE(wifi_supplicant, &mgmt_ops); -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -static const struct wifi_mgmt_ops mgmt_ap_ops = { - .ap_enable = supplicant_ap_enable, - .ap_disable = supplicant_ap_disable, - .ap_sta_disconnect = supplicant_ap_sta_disconnect, - .iface_status = supplicant_ap_status, -#ifdef CONFIG_WIFI_NM_HOSTAPD_WPS - .wps_config = supplicant_ap_wps_config, -#endif -#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP - .dpp_dispatch = hapd_dpp_dispatch, -#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */ - .ap_config_params = supplicant_ap_config_params, - .set_rts_threshold = supplicant_set_rts_threshold, -#ifdef CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE - .enterprise_creds = supplicant_add_enterprise_creds, -#endif - .set_btwt = supplicant_set_btwt, -}; - -DEFINE_WIFI_NM_INSTANCE(hostapd, &mgmt_ap_ops); -#endif - #define WRITE_TIMEOUT 100 /* ms */ #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_INF_MON #define INTERFACE_EVENT_MASK (NET_EVENT_IF_ADMIN_UP | NET_EVENT_IF_ADMIN_DOWN) @@ -141,38 +115,6 @@ struct supplicant_context { int (*iface_handler)(struct supplicant_context *ctx, struct net_if *iface); }; -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -struct hapd_global { - void **drv_priv; - size_t drv_count; -}; - -static struct hapd_global hglobal; - -#ifndef HOSTAPD_CLEANUP_INTERVAL -#define HOSTAPD_CLEANUP_INTERVAL 10 -#endif /* HOSTAPD_CLEANUP_INTERVAL */ - -static void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type, - const char *txt, size_t len); - -static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx) -{ - hostapd_periodic_iface(iface); - return 0; -} - -/* Periodic cleanup tasks */ -static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) -{ - struct hapd_interfaces *interfaces = eloop_ctx; - - eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, - hostapd_periodic, interfaces, NULL); - hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL); -} -#endif - static struct supplicant_context *get_default_context(void) { static struct supplicant_context ctx; @@ -185,6 +127,13 @@ struct wpa_global *zephyr_get_default_supplicant_context(void) return get_default_context()->supplicant; } +#ifdef CONFIG_WIFI_NM_HOSTAPD_AP +struct hapd_interfaces *zephyr_get_default_hapd_context(void) +{ + return &get_default_context()->hostapd; +} +#endif + struct k_work_q *get_workq(void) { return &get_default_context()->iface_wq; @@ -265,22 +214,6 @@ struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname) return wpa_s; } -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -struct hostapd_iface *zephyr_get_hapd_handle_by_ifname(const char *ifname) -{ - struct hostapd_data *hapd = NULL; - struct supplicant_context *ctx = get_default_context(); - - hapd = hostapd_get_iface(&ctx->hostapd, ifname); - if (!hapd) { - wpa_printf(MSG_ERROR, "%s: Unable to get hapd handle for %s\n", __func__, ifname); - return NULL; - } - - return hapd->iface; -} -#endif - static int get_iface_count(struct supplicant_context *ctx) { /* FIXME, should not access ifaces as it is supplicant internal data */ @@ -639,498 +572,6 @@ static int register_supplicant_event_socket(struct supplicant_context *ctx) return 0; } -#ifdef CONFIG_WIFI_NM_HOSTAPD_AP -struct hostapd_iface *hostapd_get_interface(const char *ifname) -{ - struct supplicant_context *ctx; - - ctx = get_default_context(); - (void)ifname; - return ctx->hostapd.iface[0]; -} - -static void hostapd_event_eapol_rx_cb(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - hostapd_event_eapol_rx(ctx, src_addr, buf, len, FRAME_ENCRYPTION_UNKNOWN, -1); -} - -static int hostapd_enable_iface_cb(struct hostapd_iface *hapd_iface) -{ - struct hostapd_data *bss; - - wpa_printf(MSG_DEBUG, "Enable interface %s", hapd_iface->conf->bss[0]->iface); - - bss = hapd_iface->bss[0]; - - bss->conf->start_disabled = 0; - - if (hostapd_config_check(hapd_iface->conf, 1) < 0) { - wpa_printf(MSG_INFO, "Invalid configuration - cannot enable"); - return -1; - } - - l2_packet_deinit(bss->l2); - bss->l2 = l2_packet_init(bss->conf->iface, bss->conf->bssid, ETH_P_EAPOL, - &hostapd_event_eapol_rx_cb, bss, 0); - if (bss->l2 == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize l2 for hostapd interface"); - return -1; - } - - if (hostapd_setup_interface(hapd_iface)) { - wpa_printf(MSG_ERROR, "Failed to initialize hostapd interface"); - return -1; - } - - return 0; -} - -static int hostapd_disable_iface_cb(struct hostapd_iface *hapd_iface) -{ - size_t j; - struct hostapd_data *hapd = NULL; - - wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); - - hapd_iface->driver_ap_teardown = !!(hapd_iface->drv_flags - & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); - -#ifdef NEED_AP_MLME - for (j = 0; j < hapd_iface->num_bss; j++) { - hostapd_cleanup_cs_params(hapd_iface->bss[j]); - } -#endif /* NEED_AP_MLME */ - - /* Same as hostapd_interface_deinit() without deinitializing control - * interface - */ - for (j = 0; j < hapd_iface->num_bss; j++) { - hapd = hapd_iface->bss[j]; - hostapd_bss_deinit_no_free(hapd); - hostapd_free_hapd_data(hapd); - } - - hostapd_drv_stop_ap(hapd); - - hostapd_cleanup_iface_partial(hapd_iface); - - wpa_printf(MSG_DEBUG, "Interface %s disabled", hapd_iface->bss[0]->conf->iface); - hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); - supplicant_send_wifi_mgmt_ap_status(hapd_iface, - NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT, - WIFI_STATUS_AP_SUCCESS); - hostapd_config_free(hapd_iface->conf); - hapd_iface->conf = hapd_iface->interfaces->config_read_cb(hapd_iface->config_fname); - for (j = 0; j < hapd_iface->num_bss; j++) { - hapd = hapd_iface->bss[j]; - hapd->iconf = hapd_iface->conf; - hapd->conf = hapd_iface->conf->bss[j]; - hapd->driver = hapd_iface->conf->driver; - } - - return 0; -} - -static int hostapd_global_init(struct hapd_interfaces *interfaces, const char *entropy_file) -{ - int i; - - os_memset(&hglobal, 0, sizeof(struct hapd_global)); - - if (eap_server_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - interfaces->eloop_initialized = 1; - - for (i = 0; wpa_drivers[i]; i++) { - hglobal.drv_count++; - } - - if (hglobal.drv_count == 0) { - wpa_printf(MSG_ERROR, "No drivers enabled"); - return -1; - } - hglobal.drv_priv = os_calloc(hglobal.drv_count, sizeof(void *)); - if (hglobal.drv_priv == NULL) { - return -1; - } - - return 0; -} - -static int hostapd_driver_init(struct hostapd_iface *iface) -{ - struct wpa_init_params params; - size_t i; - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_bss_config *conf = hapd->conf; - u8 *b = conf->bssid; - struct wpa_driver_capa capa; - - if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { - wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); - return -1; - } - - /* Initialize the driver interface */ - if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) { - b = NULL; - } - - os_memset(¶ms, 0, sizeof(params)); - for (i = 0; wpa_drivers[i]; i++) { - if (wpa_drivers[i] != hapd->driver) - continue; - - if (hglobal.drv_priv[i] == NULL && wpa_drivers[i]->global_init) { - hglobal.drv_priv[i] = wpa_drivers[i]->global_init(iface->interfaces); - if (hglobal.drv_priv[i] == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize driver '%s'", - wpa_drivers[i]->name); - return -1; - } - hglobal.drv_count++; - } - - params.global_priv = hglobal.drv_priv[i]; - break; - } - params.bssid = b; - params.ifname = hapd->conf->iface; - params.driver_params = hapd->iconf->driver_params; - params.use_pae_group_addr = hapd->conf->use_pae_group_addr; - params.num_bridge = hapd->iface->num_bss; - params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); - if (params.bridge == NULL) { - return -1; - } - for (i = 0; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; - - if (bss->conf->bridge[0]) { - params.bridge[i] = bss->conf->bridge; - } - } - - params.own_addr = hapd->own_addr; - - hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); - os_free(params.bridge); - if (hapd->drv_priv == NULL) { - wpa_printf(MSG_ERROR, "%s driver initialization failed.", - hapd->driver->name); - hapd->driver = NULL; - return -1; - } - - if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { - struct wowlan_triggers *triggs; - - iface->drv_flags = capa.flags; - iface->drv_flags2 = capa.flags2; - iface->probe_resp_offloads = capa.probe_resp_offloads; - /* - * Use default extended capa values from per-radio information - */ - iface->extended_capa = capa.extended_capa; - iface->extended_capa_mask = capa.extended_capa_mask; - iface->extended_capa_len = capa.extended_capa_len; - iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; - - /* - * Override extended capa with per-interface type (AP), if - * available from the driver. - */ - hostapd_get_ext_capa(iface); - - triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); - if (triggs && hapd->driver->set_wowlan) { - if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) { - wpa_printf(MSG_ERROR, "set_wowlan failed"); - } - } - os_free(triggs); - } - - return 0; -} - -struct hostapd_config *hostapd_config_read2(const char *fname) -{ - struct hostapd_config *conf; - const struct device *dev; - char ifname[IFNAMSIZ + 1] = {0}; - int errors = 0; - size_t i; - int aCWmin = 4, aCWmax = 10; - /* background traffic */ - struct hostapd_wmm_ac_params ac_bk = {aCWmin, aCWmax, 9, 0, 0}; - /* best effort traffic */ - struct hostapd_wmm_ac_params ac_be = {aCWmin, aCWmax - 4, 5, 0, 0}; - /* video traffic */ - struct hostapd_wmm_ac_params ac_vi = {aCWmin - 1, aCWmin, 3, - 3008 / 32, 0}; - /* voice traffic */ - struct hostapd_wmm_ac_params ac_vo = {aCWmin - 2, aCWmin - 1, 3, - 1504 / 32, 0}; - - dev = net_if_get_device(net_if_get_wifi_sap()); - strncpy(ifname, dev->name, IFNAMSIZ); - ifname[IFNAMSIZ] = '\0'; - - conf = hostapd_config_defaults(); - if (conf == NULL) { - return NULL; - } - - conf->wmm_ac_params[0] = ac_be; - conf->wmm_ac_params[1] = ac_bk; - conf->wmm_ac_params[2] = ac_vi; - conf->wmm_ac_params[3] = ac_vo; - - /* set default driver based on configuration */ - conf->driver = wpa_drivers[0]; - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "No driver wrappers registered!"); - hostapd_config_free(conf); - return NULL; - } - conf->last_bss = conf->bss[0]; - struct hostapd_bss_config *bss; - - bss = conf->last_bss; - bss->start_disabled = 1; - bss->max_num_sta = CONFIG_WIFI_MGMT_AP_MAX_NUM_STA; - bss->dtim_period = 1; - os_strlcpy(conf->bss[0]->iface, ifname, sizeof(conf->bss[0]->iface)); - bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; - bss->logger_stdout = 0xffff; - bss->nas_identifier = os_strdup("ap.example.com"); - os_memcpy(conf->country, "US ", 3); - conf->hw_mode = HOSTAPD_MODE_IEEE80211G; - bss->wps_state = WPS_STATE_CONFIGURED; - bss->eap_server = 1; -#ifdef CONFIG_WPS - bss->ap_setup_locked = 1; -#endif - conf->channel = 1; - conf->acs = conf->channel == 0; -#ifdef CONFIG_ACS - conf->acs_num_scans = 1; -#endif - conf->ieee80211n = 1; - conf->ieee80211h = 0; - conf->ieee80211d = 1; - conf->acs_exclude_dfs = 1; - conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; - bss->auth_algs = 1; - bss->okc = 1; - conf->no_pri_sec_switch = 1; - conf->ht_op_mode_fixed = 1; - conf->ieee80211ac = 1; - conf->vht_oper_chwidth = CHANWIDTH_USE_HT; - conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX; -#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX - conf->ieee80211ax = 1; - conf->he_oper_chwidth = CHANWIDTH_USE_HT; - conf->he_phy_capab.he_su_beamformer = 0; - conf->he_phy_capab.he_su_beamformee = 1; - conf->he_phy_capab.he_mu_beamformer = 0; - conf->he_op.he_bss_color = 1; - conf->he_op.he_default_pe_duration = 0; - /* Set default basic MCS/NSS set to single stream MCS 0-7 */ - conf->he_op.he_basic_mcs_nss_set = 0xfffc; -#endif - - for (i = 0; i < conf->num_bss; i++) { - hostapd_set_security_params(conf->bss[i], 1); - } - - if (hostapd_config_check(conf, 1)) { - errors++; - } - -#ifndef WPA_IGNORE_CONFIG_ERRORS - if (errors) { - wpa_printf(MSG_ERROR, "%d errors found in configuration file '%s'", - errors, fname); - hostapd_config_free(conf); - conf = NULL; - } -#endif /* WPA_IGNORE_CONFIG_ERRORS */ - return conf; -} - -static struct hostapd_iface *hostapd_interface_init(struct hapd_interfaces *interfaces, - const char *if_name, - const char *config_fname, - int debug) -{ - struct hostapd_iface *iface; - int k; - - wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname); - iface = hostapd_init(interfaces, config_fname); - if (!iface) { - return NULL; - } - - if (if_name) { - os_strlcpy(iface->conf->bss[0]->iface, if_name, - sizeof(iface->conf->bss[0]->iface)); - } - - iface->interfaces = interfaces; - - for (k = 0; k < debug; k++) { - if (iface->bss[0]->conf->logger_stdout_level > 0) { - iface->bss[0]->conf->logger_stdout_level--; - } - } - - if (iface->conf->bss[0]->iface[0] == '\0' && - !hostapd_drv_none(iface->bss[0])) { - wpa_printf(MSG_ERROR, - "Interface name not specified in %s, nor by '-i' parameter", - config_fname); - hostapd_interface_deinit_free(iface); - return NULL; - } - - iface->bss[0]->is_hostapd = 1; - - return iface; -} - -static void zephyr_hostapd_init(struct supplicant_context *ctx) -{ - struct hapd_interfaces *interfaces = &ctx->hostapd; - size_t i; - int ret, debug = 0; - struct net_if *iface; - char ifname[IFNAMSIZ + 1] = { 0 }; - const char *entropy_file = NULL; - size_t num_bss_configs = 0; - int start_ifaces_in_sync = 0; -#ifdef CONFIG_DPP - struct dpp_global_config dpp_conf; -#endif /* CONFIG_DPP */ - - os_memset(interfaces, 0, sizeof(struct hapd_interfaces)); - interfaces->reload_config = hostapd_reload_config; - interfaces->config_read_cb = hostapd_config_read2; - interfaces->for_each_interface = hostapd_for_each_interface; - interfaces->driver_init = hostapd_driver_init; - interfaces->global_ctrl_sock = -1; - dl_list_init(&interfaces->global_ctrl_dst); -#ifdef CONFIG_DPP - os_memset(&dpp_conf, 0, sizeof(dpp_conf)); - dpp_conf.cb_ctx = interfaces; - interfaces->dpp = dpp_global_init(&dpp_conf); - if (!interfaces->dpp) { - return; - } -#endif /* CONFIG_DPP */ - - interfaces->count = 1; - if (interfaces->count || num_bss_configs) { - interfaces->iface = os_calloc(interfaces->count + num_bss_configs, - sizeof(struct hostapd_iface *)); - if (interfaces->iface == NULL) { - wpa_printf(MSG_ERROR, "malloc failed"); - return; - } - } - - if (hostapd_global_init(interfaces, entropy_file)) { - wpa_printf(MSG_ERROR, "Failed to initialize global context"); - return; - } - - eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, - hostapd_periodic, interfaces, NULL); - - iface = net_if_get_wifi_sap(); - ret = net_if_get_name(iface, ifname, sizeof(ifname) - 1); - if (ret < 0) { - LOG_ERR("Cannot get interface %d (%p) name", net_if_get_by_iface(iface), iface); - goto out; - } - - for (i = 0; i < interfaces->count; i++) { - interfaces->iface[i] = hostapd_interface_init(interfaces, ifname, - "hostapd.conf", debug); - if (!interfaces->iface[i]) { - wpa_printf(MSG_ERROR, "Failed to initialize interface"); - goto out; - } - if (start_ifaces_in_sync) { - interfaces->iface[i]->need_to_start_in_sync = 0; - } - } - - /* - * Enable configured interfaces. Depending on channel configuration, - * this may complete full initialization before returning or use a - * callback mechanism to complete setup in case of operations like HT - * co-ex scans, ACS, or DFS are needed to determine channel parameters. - * In such case, the interface will be enabled from eloop context within - * hostapd_global_run(). - */ - interfaces->terminate_on_error = 0; - for (i = 0; i < interfaces->count; i++) { - if (hostapd_driver_init(interfaces->iface[i])) { - goto out; - } - - interfaces->iface[i]->enable_iface_cb = hostapd_enable_iface_cb; - interfaces->iface[i]->disable_iface_cb = hostapd_disable_iface_cb; - zephyr_hostapd_ctrl_init((void *)interfaces->iface[i]->bss[0]); - } - -out: - return; -} - -static const char *zephyr_hostap_msg_ifname_cb(void *ctx) -{ - if (ctx == NULL) { - return NULL; - } - - if ((*((int *)ctx)) == 0) { - struct wpa_supplicant *wpa_s = ctx; - - return wpa_s->ifname; - } - - struct hostapd_data *hapd = ctx; - - if (hapd && hapd->conf) { - return hapd->conf->iface; - } - - return NULL; -} - -static void zephyr_hostap_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type, - const char *txt, size_t len) -{ - if (ctx == NULL) { - return; - } - - if ((*((int *)ctx)) == 0) { - wpa_supplicant_msg_send(ctx, level, type, txt, len); - } else { - hostapd_msg_send(ctx, level, type, txt, len); - } -} -#endif - static void handler(void) { struct supplicant_context *ctx; @@ -1186,7 +627,7 @@ static void handler(void) submit_iface_work(ctx, NULL, setup_interface_monitoring); #ifdef CONFIG_WIFI_NM_HOSTAPD_AP - zephyr_hostapd_init(ctx); + zephyr_hostapd_init(&ctx->hostapd); wpa_msg_register_ifname_cb(zephyr_hostap_msg_ifname_cb); #endif diff --git a/modules/hostap/src/supp_main.h b/modules/hostap/src/supp_main.h index 22e6d79035c..60ac642f9c7 100644 --- a/modules/hostap/src/supp_main.h +++ b/modules/hostap/src/supp_main.h @@ -55,15 +55,11 @@ struct wpa_global *zephyr_get_default_supplicant_context(void); struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname); #ifdef CONFIG_WIFI_NM_HOSTAPD_AP -#include "common.h" -#include "wpa_debug_zephyr.h" - -struct hostapd_iface *zephyr_get_hapd_handle_by_ifname(const char *ifname); -void wpa_supplicant_msg_send(void *ctx, int level, enum wpa_msg_type type, const char *txt, - size_t len); -void hostapd_msg_send(void *ctx, int level, enum wpa_msg_type type, const char *buf, size_t len); +struct hapd_interfaces *zephyr_get_default_hapd_context(void); #endif +struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname); + struct wpa_supplicant_event_msg { #ifdef CONFIG_WIFI_NM_HOSTAPD_AP int hostapd; diff --git a/west.yml b/west.yml index d268c509859..3b933c22d7a 100644 --- a/west.yml +++ b/west.yml @@ -203,7 +203,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 6af2fd7a9b21a567866585384d28963daeb7d350 + revision: 4c94d433ba1a7638a0f3a319ab0adb43238f9be3 path: modules/hal/nxp groups: - hal @@ -274,7 +274,7 @@ manifest: - hal - name: hostap path: modules/lib/hostap - revision: e83c94958cab8e2327c85e484f50cbf570f5ac3f + revision: f72b2d4402cb6e8d29d93e0866bc3e8ec4d7ddbc - name: liblc3 revision: 48bbd3eacd36e99a57317a0a4867002e0b09e183 path: modules/lib/liblc3