MCUXpresso_MIMXRT1021xxxxx/middleware/wireless/wpa_supplicant-rtos/freertos/src/supp_api.c
Yilin Sun 763d32be90
Updated SDK to v2.15.000
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-03-15 22:23:36 +08:00

4968 lines
130 KiB
C

/** @file supp_api.c
*
* @brief This file provides wpa supplicant APIs.
*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "fsl_os_abstraction.h"
#include "includes.h"
#include "utils/common.h"
#include "common/defs.h"
#include "common/ptksa_cache.h"
#include "wpa_supplicant/config.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "ap.h"
#include "crc32.h"
#include "supp_main.h"
#include "supp_api.h"
#include "wpa_supplicant/bss.h"
#include "wpa_supplicant/wps_supplicant.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant/wnm_sta.h"
#include "eap_defs.h"
#include "eap.h"
#include "crypto/tls.h"
#include "wpa_supplicant/scan.h"
#include "wpa_supplicant/sme.h"
#ifdef CONFIG_HOSTAPD
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/wps_hostapd.h"
#include "ap/sta_info.h"
#endif
#ifdef CONFIG_DPP
#include "ap/dpp_hostapd.h"
#include "wpa_supplicant/dpp_supplicant.h"
#endif
#define EAP_TTLS_AUTH_PAP 1
#define EAP_TTLS_AUTH_CHAP 2
#define EAP_TTLS_AUTH_MSCHAP 4
#define EAP_TTLS_AUTH_MSCHAPV2 8
enum supp_thread_state
{
SUPP_THREAD_STOPPED = 0,
SUPP_THREAD_RUNNING,
};
unsigned char bandwidth = 2;
unsigned char h_hidden_ssid = 0;
unsigned short h_beacon_int = 100;
int h_max_num_sta = 8;
int cli_main(int, const char **);
OSA_SEMAPHORE_HANDLE_DEFINE(wpaSuppReadySemaphoreHandle);
#ifdef CONFIG_HOSTAPD
OSA_SEMAPHORE_HANDLE_DEFINE(hostapdReadySemaphoreHandle);
#endif
extern struct wpa_global *global;
OSA_MUTEX_HANDLE_DEFINE(wpa_supplicant_mutex);
struct wpa_supp_api_ctrl
{
const struct netif *dev;
enum requested_ops requested_op;
enum supp_thread_state supp_thread_state;
};
static struct wpa_supp_api_ctrl wpa_supp_api_ctrl;
static void wpa_supp_scan_res_fail_handler(struct wpa_supplicant *wpa_s);
static inline struct wpa_supplicant *get_wpa_s_handle(const struct netif *dev)
{
struct wpa_supplicant *wpa_s = NULL;
int ret = OSA_SemaphoreWait((osa_semaphore_handle_t)wpaSuppReadySemaphoreHandle, osaWaitForever_c);
char ifname[NETIF_NAMESIZE];
if (ret)
{
wpa_printf(MSG_DEBUG, "%s: WPA supplicant not ready: %d", __func__, ret);
return NULL;
}
OSA_SemaphorePost((osa_semaphore_handle_t)wpaSuppReadySemaphoreHandle);
#ifdef CONFIG_ZEPHYR
const struct device *dev_temp = NULL;
dev_temp = net_if_get_device((struct net_if *)dev);
strncpy(ifname, dev_temp->name, NETIF_NAMESIZE - 1);
ifname[NETIF_NAMESIZE - 1] = '\0';
#else
(void)netifapi_netif_index_to_name(dev->num + 1, ifname);
#endif
wpa_s = wpa_supplicant_get_iface(global, ifname);
if (!wpa_s)
{
wpa_printf(MSG_DEBUG, "%s: Unable to get wpa_s handle for %s", __func__, ifname);
return NULL;
}
return wpa_s;
}
#ifdef CONFIG_HOSTAPD
static inline struct hostapd_iface *get_hostapd_handle(const struct netif *dev)
{
struct hostapd_iface *hapd_s = NULL;
int ret = OSA_SemaphoreWait((osa_semaphore_handle_t)hostapdReadySemaphoreHandle, osaWaitForever_c);
char ifname[NETIF_NAMESIZE];
if (ret)
{
wpa_printf(MSG_DEBUG, "%s: HOSTAPD not ready: %d", __func__, ret);
return NULL;
}
OSA_SemaphorePost((osa_semaphore_handle_t)hostapdReadySemaphoreHandle);
#ifdef CONFIG_ZEPHYR
const struct device *dev_temp = NULL;
dev_temp = net_if_get_device((struct net_if *)dev);
strncpy(ifname, dev_temp->name, NETIF_NAMESIZE - 1);
ifname[NETIF_NAMESIZE - 1] = '\0';
#else
(void)netifapi_netif_index_to_name(dev->num + 1, ifname);
#endif
hapd_s = hostapd_get_interface(ifname);
if (!hapd_s)
{
wpa_printf(MSG_DEBUG, "%s: Unable to get hapd_s handle for %s", __func__, ifname);
return NULL;
}
return hapd_s;
}
#endif
int wpa_supp_req_status(enum requested_ops ops)
{
int status = -1;
struct wpa_supplicant *wpa_s;
struct wpa_supp_api_ctrl *ctrl = &wpa_supp_api_ctrl;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (ops == START)
{
struct hostapd_iface *hapd_s;
hapd_s = get_hostapd_handle(ctrl->dev);
if (!hapd_s)
{
status = -1;
goto out;
}
if (hapd_s->state == HAPD_IFACE_ENABLED)
status = 0;
}
else
{
#endif
wpa_s = get_wpa_s_handle(ctrl->dev);
if (!wpa_s)
{
goto out;
}
if ((ctrl->requested_op == CONNECT) || (ctrl->requested_op == START) || (ctrl->requested_op == RECONNECT))
{
if (wpa_s->wpa_state == WPA_COMPLETED)
status = 0;
}
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return status;
}
static int *freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
{
struct wpa_freq_range_list ranges;
int *freqs = NULL;
struct hostapd_hw_modes *mode;
u16 i;
if (wpa_s->hw.modes == NULL)
return NULL;
os_memset(&ranges, 0, sizeof(ranges));
if (freq_range_list_parse(&ranges, val) < 0)
return NULL;
for (i = 0; i < wpa_s->hw.num_modes; i++)
{
int j;
// Skip HOSTAPD_MODE_IEEE80211B
if (i == HOSTAPD_MODE_IEEE80211B)
{
continue;
}
mode = &wpa_s->hw.modes[i];
for (j = 0; j < mode->num_channels; j++)
{
unsigned int freq;
if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
freq = mode->channels[j].freq;
if (!freq_range_list_includes(&ranges, freq))
continue;
int_array_add_unique(&freqs, freq);
}
}
os_free(ranges.range);
return freqs;
}
int wpa_supp_scan(const struct netif *dev, wlan_scan_params_v2_t *params)
{
unsigned int manual_scan_passive = 0;
unsigned int manual_scan_use_id = 0;
unsigned int manual_scan_only_new = 1;
unsigned int scan_only = 0;
unsigned int scan_id_count = 0;
int scan_id[MAX_SCAN_ID] = {0};
void (*scan_res_handler)(struct wpa_supplicant * wpa_s, struct wpa_scan_results * scan_res);
int *manual_scan_freqs = NULL;
struct wpa_ssid_value *ssid = NULL;
unsigned int ssid_count = 0;
char frequency[256] = {0};
char *pos = frequency;
struct wpa_supplicant *wpa_s;
int ret = 0, i, freq;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
{
ret = -1;
goto out;
}
if (radio_work_pending(wpa_s, "scan"))
{
wpa_printf(MSG_DEBUG, "Pending scan scheduled - reject new request");
ret = -1;
goto out;
}
if (params)
{
if (params->scan_only)
scan_only = 1;
if (params->num_channels)
{
for (i = 0; i < params->num_channels; i++)
{
freq = ieee80211_chan_to_freq(NULL, 81, params->chan_list[i].chan_number);
if (freq <= 0)
{
freq = ieee80211_chan_to_freq(NULL, 128, params->chan_list[i].chan_number);
}
if (freq <= 0)
{
wpa_printf(MSG_DEBUG, "Invalid channel %d", params->chan_list[i].chan_number);
ret = -1;
goto out;
}
if (i == (params->num_channels - 1))
{
(void)sprintf(pos, "%d", freq);
}
else
{
ret = sprintf(pos, "%d,", freq);
if (ret < 0)
{
ret = -1;
goto out;
}
pos += ret;
}
}
manual_scan_freqs = freq_range_to_channel_list(wpa_s, frequency);
if (manual_scan_freqs == NULL)
{
ret = -1;
goto out;
}
}
if (params->is_bssid)
{
os_memcpy(wpa_s->next_scan_bssid, params->bssid, ETH_ALEN);
wpa_s->next_scan_bssid_wildcard_ssid = 0;
}
if (params->is_ssid)
{
ssid = os_zalloc(sizeof(*ssid));
if (ssid == NULL)
{
ret = -1;
goto out;
}
ssid->ssid_len = os_strlen((const char *)&params->ssid[0]);
os_memcpy(ssid->ssid, &params->ssid[0], ssid->ssid_len);
wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", ssid->ssid, ssid->ssid_len);
ssid_count++;
}
}
wpa_s->num_ssids_from_scan_req = ssid_count;
os_free(wpa_s->ssids_from_scan_req);
if (ssid_count)
{
wpa_s->ssids_from_scan_req = ssid;
}
else
{
wpa_s->ssids_from_scan_req = NULL;
}
if (scan_only)
scan_res_handler = scan_only_handler;
else if (wpa_s->scan_res_handler == scan_only_handler)
scan_res_handler = NULL;
else
scan_res_handler = wpa_s->scan_res_handler;
if (!wpa_s->sched_scanning && !wpa_s->scanning &&
((wpa_s->wpa_state <= WPA_SCANNING) || (wpa_s->wpa_state == WPA_COMPLETED)))
{
wpa_s->manual_scan_passive = manual_scan_passive;
wpa_s->manual_scan_use_id = manual_scan_use_id;
wpa_s->manual_scan_only_new = manual_scan_only_new;
wpa_s->scan_id_count = scan_id_count;
os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
wpa_s->scan_res_handler = scan_res_handler;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = manual_scan_freqs;
manual_scan_freqs = NULL;
wpa_s->normal_scans = 0;
wpa_s->scan_req = MANUAL_SCAN_REQ;
wpa_s->after_wps = 0;
wpa_s->known_wps_freq = 0;
wpa_supplicant_req_scan(wpa_s, 0, 0);
if (wpa_s->manual_scan_use_id)
{
wpa_s->manual_scan_id++;
wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", wpa_s->manual_scan_id);
}
}
else if (wpa_s->sched_scanning)
{
wpa_s->manual_scan_passive = manual_scan_passive;
wpa_s->manual_scan_use_id = manual_scan_use_id;
wpa_s->manual_scan_only_new = manual_scan_only_new;
wpa_s->scan_id_count = scan_id_count;
os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
wpa_s->scan_res_handler = scan_res_handler;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = manual_scan_freqs;
manual_scan_freqs = NULL;
wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_s->scan_req = MANUAL_SCAN_REQ;
wpa_supplicant_req_scan(wpa_s, 0, 0);
if (wpa_s->manual_scan_use_id)
{
wpa_s->manual_scan_id++;
wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", wpa_s->manual_scan_id);
}
}
else
{
wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
ret = -1;
goto out;
}
send_wpa_supplicant_dummy_event();
ret = 0;
out:
if (ret != 0)
{
os_free(manual_scan_freqs);
}
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_abort_scan(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_s->scan_res_fail_handler = wpa_supp_scan_res_fail_handler;
ret = wpas_abort_ongoing_scan(wpa_s);
if (ret != 0)
{
goto out;
}
send_wpa_supplicant_dummy_event();
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_cancel_scan(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
if (wpa_s->wpa_state == WPA_SCANNING || wpa_s->wpa_state == WPA_DISCONNECTED)
wpa_supplicant_cancel_scan(wpa_s);
send_wpa_supplicant_dummy_event();
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
static int wpa_config_process_blob(struct wpa_config *config, char *name, u8 *data, size_t data_len)
{
struct wpa_config_blob *blob;
blob = os_zalloc(sizeof(*blob));
if (blob == NULL)
{
return -1;
}
blob->data = os_zalloc(data_len);
if (blob->data == NULL)
{
os_free(blob);
return -1;
}
blob->name = os_strdup(name);
if (blob->name == NULL)
{
wpa_config_free_blob(blob);
return -1;
}
os_memcpy(blob->data, data, data_len);
blob->len = data_len;
wpa_config_set_blob(config, blob);
return 0;
}
#endif
#ifdef CONFIG_HOSTAPD
#ifdef CONFIG_WPA_SUPP_CRYPTO_AP_ENTERPRISE
static struct hostapd_eap_user *hostapd_config_read_default_eap_user(struct wlan_network *network,
struct hostapd_eap_user **pnew_user)
{
struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
#if 0
size_t i;
unsigned char *id[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8"};
#endif
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
#ifdef CONFIG_EAP_PEAP
if (
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_PEAP_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_TLS
(network->security.type == WLAN_SECURITY_EAP_PEAP_TLS) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_PEAP_GTC) ||
#endif
false)
{
user->methods[0].method = EAP_TYPE_PEAP;
user->methods[0].vendor = EAP_VENDOR_IETF;
}
#endif
#ifdef CONFIG_EAP_TTLS
if (
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_TTLS_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_TLS
(network->security.type == WLAN_SECURITY_EAP_TTLS) ||
#endif
false)
{
user->methods[0].method = EAP_TYPE_TTLS;
user->methods[0].vendor = EAP_VENDOR_IETF;
}
#endif
#ifdef CONFIG_EAP_FAST
if (
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_FAST_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_FAST_GTC) ||
#endif
false)
{
user->methods[0].method = EAP_TYPE_FAST;
user->methods[0].vendor = EAP_VENDOR_IETF;
}
#endif
if (tail == NULL)
{
tail = new_user = user;
}
else
{
tail->next = user;
tail = user;
}
*pnew_user = new_user;
return tail;
failed:
if (new_user)
hostapd_config_free_eap_user(new_user);
return NULL;
}
static int hostapd_config_read_default2_eap_user(struct wlan_network *network,
struct hostapd_bss_config *conf)
{
struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
u8 i, idx = 0, idx_inc = 0, idx_max = 9;
char *id[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8"};
u32 method;
#ifdef CONFIG_EAP_SIM
if (network->security.type == WLAN_SECURITY_EAP_SIM)
{
idx = 1;
idx_inc = 2;
idx_max = 6;
method = EAP_TYPE_SIM;
}
#endif
#ifdef CONFIG_EAP_AKA
if (network->security.type == WLAN_SECURITY_EAP_AKA)
{
idx = 0;
idx_inc = 2;
idx_max = 5;
method = EAP_TYPE_AKA;
}
#endif
#ifdef CONFIG_EAP_AKA_PRIME
if (network->security.type == WLAN_SECURITY_EAP_AKA_PRIME)
{
idx = 6;
idx_inc = 1;
idx_max = 9;
method = EAP_TYPE_AKA_PRIME;
}
#endif
for (i = idx; i < idx_max; i += idx_inc)
{
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
user->identity = os_memdup(id[i], os_strlen(id[i]));
if (user->identity == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP identity");
goto failed;
}
user->identity_len = os_strlen(id[i]);
user->wildcard_prefix = 1;
user->methods[0].method = method;
user->methods[0].vendor = EAP_VENDOR_IETF;
if (tail == NULL)
{
tail = new_user = user;
}
else
{
tail->next = user;
tail = user;
}
}
hostapd_config_free_eap_users(conf->eap_user);
conf->eap_user = new_user;
return 0;
failed:
if (new_user)
hostapd_config_free_eap_user(new_user);
return -1;
}
#ifdef CONFIG_EAP_TLS
static int hostapd_config_read_eap_user(const size_t nusers,
const char (*identities)[IDENTITY_MAX_LENGTH],
struct hostapd_bss_config *conf)
{
struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
size_t i;
int ret = 0;
if (!nusers)
{
wpa_printf(MSG_DEBUG, "EAP users not found.");
return -1;
}
for (i = 0; i < nusers; i++)
{
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
user->identity = os_memdup(identities[i], os_strlen(identities[i]));
if (user->identity == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP identity");
goto failed;
}
user->identity_len = os_strlen(identities[i]);
user->methods[0].method = EAP_TYPE_TLS;
user->methods[0].vendor = EAP_VENDOR_IETF;
if (tail == NULL)
{
tail = new_user = 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 = new_user;
}
else
{
hostapd_config_free_eap_users(new_user);
}
return ret;
}
#endif
static int hostapd_config_read_eap_phase2_user(struct wlan_network *network, struct hostapd_bss_config *conf)
{
struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
size_t i, nusers = network->security.nusers;
int ret = 0;
const char *identity, *password;
if (!nusers)
{
wpa_printf(MSG_DEBUG, "EAP users not found.");
return -1;
}
tail = hostapd_config_read_default_eap_user(network, &new_user);
for (i = 0; i < nusers; i++)
{
identity = (const char *)&network->security.identities[i];
password = (const char *)&network->security.passwords[i];
if (
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_PEAP_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_PEAP_GTC) ||
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_FAST_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_FAST_GTC) ||
#endif
#endif
false)
{
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
user->identity = os_memdup(identity, os_strlen(identity));
if (user->identity == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP identity");
goto failed;
}
user->identity_len = os_strlen(identity);
#ifdef CONFIG_EAP_MSCHAPV2
user->methods[0].method = EAP_TYPE_MSCHAPV2;
user->methods[0].vendor = EAP_VENDOR_IETF;
#endif
#ifdef CONFIG_EAP_GTC
user->methods[1].method = EAP_TYPE_GTC;
user->methods[1].vendor = EAP_VENDOR_IETF;
#endif
user->password = os_memdup(password, os_strlen(password));
if (user->password == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP password");
goto failed;
}
user->password_len = os_strlen(password);
user->phase2 = 1;
if (tail == NULL)
{
tail = new_user = user;
}
else
{
tail->next = user;
tail = user;
}
}
#ifdef CONFIG_EAP_TLS
if (
#ifdef CONFIG_EAP_PEAP
(network->security.type == WLAN_SECURITY_EAP_PEAP_TLS) ||
#endif
#ifdef CONFIG_EAP_TTLS
(network->security.type == WLAN_SECURITY_EAP_TTLS) ||
#endif
false)
{
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
user->identity = os_memdup(identity, os_strlen(identity));
if (user->identity == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP identity");
goto failed;
}
user->identity_len = os_strlen(identity);
user->methods[0].method = EAP_TYPE_TLS;
user->methods[0].vendor = EAP_VENDOR_IETF;
user->password = os_memdup(password, os_strlen(password));
if (user->password == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP password");
goto failed;
}
user->password_len = os_strlen(password);
user->phase2 = 1;
if (tail == NULL)
{
tail = new_user = user;
}
else
{
tail->next = user;
tail = user;
}
}
#endif
#ifdef CONFIG_EAP_TTLS
#ifdef CONFIG_EAP_MSCHAPV2
if (network->security.type == WLAN_SECURITY_EAP_TTLS_MSCHAPV2)
{
user = os_zalloc(sizeof(*user));
if (user == NULL)
{
wpa_printf(MSG_DEBUG, "EAP user allocation failed");
goto failed;
}
user->force_version = -1;
user->identity = os_memdup(identity, os_strlen(identity));
if (user->identity == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP identity");
goto failed;
}
user->identity_len = os_strlen(identity);
user->methods[0].method = EAP_TYPE_NONE;
user->methods[0].vendor = EAP_VENDOR_IETF;
user->ttls_auth |= EAP_TTLS_AUTH_PAP;
user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
user->password = os_memdup(password, os_strlen(password));
if (user->password == NULL)
{
wpa_printf(MSG_DEBUG,
"Failed to allocate "
"memory for EAP password");
goto failed;
}
user->password_len = os_strlen(password);
user->phase2 = 1;
if (tail == NULL)
{
tail = new_user = user;
}
else
{
tail->next = user;
tail = user;
}
}
#endif
#endif
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 = new_user;
}
else
{
hostapd_config_free_eap_users(new_user);
}
return ret;
}
#endif
#ifdef CONFIG_WPA_SUPP_WPA3
static int parse_sae_password(struct hostapd_bss_config *bss, const char *sae_password)
{
struct sae_password_entry *pw;
pw = os_zalloc(sizeof(*pw));
if (!pw)
return -1;
os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */
#ifdef CONFIG_SAE_PK
pos2 = os_strstr(pos, "|pk=");
if (pos2)
{
const char *epos;
char *tmp;
if (!end)
end = pos2;
pos2 += 4;
epos = os_strchr(pos2, '|');
if (epos)
{
tmp = os_malloc(epos - pos2 + 1);
if (!tmp)
goto fail;
os_memcpy(tmp, pos2, epos - pos2);
tmp[epos - pos2] = '\0';
}
else
{
tmp = os_strdup(pos2);
if (!tmp)
goto fail;
}
pw->pk = sae_parse_pk(tmp);
str_clear_free(tmp);
if (!pw->pk)
goto fail;
}
#endif /* CONFIG_SAE_PK */
pw->password = os_strdup(sae_password);
if (!pw->password)
goto fail;
#ifdef CONFIG_SAE_PK
if (pw->pk &&
#ifdef CONFIG_TESTING_OPTIONS
!bss->sae_pk_password_check_skip &&
#endif /* CONFIG_TESTING_OPTIONS */
!sae_pk_valid_password(pw->password))
{
wpa_printf(MSG_INFO, "Invalid SAE password for a SAE-PK sae_password entry");
goto fail;
}
#endif /* CONFIG_SAE_PK */
pw->next = bss->sae_passwords;
bss->sae_passwords = pw;
return 0;
fail:
// str_clear_free(pw->password);
// os_free(pw->identifier);
#ifdef CONFIG_SAE_PK
sae_deinit_pk(pw->pk);
#endif /* CONFIG_SAE_PK */
os_free(pw);
return -1;
}
#endif
static int wpa_parse_intlist(int **int_list, char *val)
{
int *list;
int count;
char *pos, *end;
os_free(*int_list);
*int_list = NULL;
pos = val;
count = 0;
while (*pos != '\0')
{
if (*pos == ' ')
count++;
pos++;
}
list = os_malloc(sizeof(int) * (count + 2));
if (list == NULL)
return -1;
pos = val;
count = 0;
while (*pos != '\0')
{
end = os_strchr(pos, ' ');
if (end)
*end = '\0';
list[count++] = atoi(pos);
if (!end)
break;
pos = end + 1;
}
list[count] = -1;
*int_list = list;
return 0;
}
static int hostapd_update_bss(struct hostapd_iface *hapd_s, struct wlan_network *network)
{
struct hostapd_config *conf;
struct hostapd_bss_config *bss;
struct hostapd_ssid *ssid;
struct hostapd_data *hapd;
#if defined(CONFIG_WPA_SUPP_WPA3) || defined(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE)
int ret = -1;
#endif
hapd = hapd_s->bss[0];
conf = hapd_s->conf;
bss = conf->last_bss;
hapd_s->freq = 0;
bss->max_num_sta = 10;
os_memcpy(bss->bssid, network->bssid, ETH_ALEN);
os_memcpy(hapd->own_addr, network->bssid, ETH_ALEN);
conf->acs_exclude_dfs = 1;
if (network->channel > 14 || (network->channel == 0 && network->acs_band == 1))
{
conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
}
else
{
conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
}
conf->channel = network->channel;
conf->acs = conf->channel == 0;
if(conf->ieee80211d)
{
conf->spectrum_mgmt_required = 1;
conf->local_pwr_constraint = 3;
}
else
{
conf->spectrum_mgmt_required = 0;
conf->local_pwr_constraint = -1;
}
conf->obss_interval = 10;
if (network->dot11n)
{
conf->ieee80211n = 1;
conf->ht_capab = network->ht_capab;
conf->ht40_plus_minus_allowed = 1;
conf->secondary_channel = 0;
bss->wmm_enabled = 1;
bss->wmm_uapsd = 0;
if (network->sec_channel_offset == 1)
{
conf->secondary_channel = 1;
}
else if (network->sec_channel_offset == 3)
{
conf->secondary_channel = -1;
}
}
else
{
conf->ieee80211n = 0;
conf->ht_capab = 0;
conf->secondary_channel = 0;
bss->wmm_enabled = 0;
}
#ifdef CONFIG_11AC
if (network->dot11ac)
{
conf->ieee80211ac = 1;
if (conf->acs == 0)
{
if (network->channel > 14)
{
conf->vht_oper_chwidth = network->vht_oper_chwidth;
}
else
{
conf->vht_oper_chwidth = 0;
conf->vht_oper_centr_freq_seg0_idx = 0;
}
}
conf->vht_capab = network->vht_capab;
}
else
{
conf->ieee80211ac = 0;
}
#endif
#ifdef CONFIG_11AX
if (network->dot11ax)
{
conf->ieee80211ax = 1;
if (conf->acs == 0)
{
if (network->channel > 14)
{
conf->he_oper_chwidth = network->he_oper_chwidth;
}
else
{
conf->he_oper_chwidth = 0;
conf->he_oper_centr_freq_seg0_idx = 0;
}
}
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;
}
else
{
conf->ieee80211ax = 0;
}
#endif
conf->no_pri_sec_switch = 1;
conf->ht_op_mode_fixed = 1;
ssid = &bss->ssid;
ssid->ssid_len = os_strlen(network->ssid);
if (ssid->ssid_len > SSID_MAX_LEN || ssid->ssid_len < 1)
{
wpa_printf(MSG_DEBUG, "invalid SSID '%s'", ssid->ssid);
return -1;
}
os_memcpy(ssid->ssid, network->ssid, ssid->ssid_len);
ssid->ssid_set = 1;
ssid->short_ssid = crc32(ssid->ssid, ssid->ssid_len);
bss->wpa_key_mgmt = network->security.key_mgmt;
if (network->security.type != WLAN_SECURITY_NONE)
{
bss->wpa = WPA_PROTO_RSN;
bss->wpa_group = network->security.group_cipher;
bss->rsn_pairwise = network->security.pairwise_cipher;
bss->wpa_pairwise = network->security.pairwise_cipher;
bss->group_mgmt_cipher = network->security.group_mgmt_cipher;
}
switch (network->security.type)
{
#ifdef CONFIG_WPA_SUPP_CRYPTO_AP_ENTERPRISE
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_TLS:
case WLAN_SECURITY_EAP_TLS_SHA256:
#ifdef CONFIG_11R
case WLAN_SECURITY_EAP_TLS_FT:
case WLAN_SECURITY_EAP_TLS_FT_SHA384:
#endif
#endif
#ifdef CONFIG_EAP_TTLS
case WLAN_SECURITY_EAP_TTLS:
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_TTLS_MSCHAPV2:
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_PEAP_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_PEAP_TLS:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_PEAP_GTC:
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_FAST_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_FAST_GTC:
#endif
#endif
#ifdef CONFIG_EAP_SIM
case WLAN_SECURITY_EAP_SIM:
#endif
#ifdef CONFIG_EAP_AKA
case WLAN_SECURITY_EAP_AKA:
#endif
#ifdef CONFIG_EAP_AKA_PRIME
case WLAN_SECURITY_EAP_AKA_PRIME:
#endif
if (network->security.type == WLAN_SECURITY_EAP_TLS_SHA256)
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
}
#ifdef CONFIG_11R
else if (network->security.type == WLAN_SECURITY_EAP_TLS_FT)
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_FT_IEEE8021X;
bss->mobility_domain[0] = 'a';
bss->mobility_domain[1] = '1';
bss->pmk_r1_push = 1;
bss->ft_over_ds = 0;
bss->ft_psk_generate_local = 1;
}
else if (network->security.type == WLAN_SECURITY_EAP_TLS_FT_SHA384)
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
bss->mobility_domain[0] = 'a';
bss->mobility_domain[1] = '2';
bss->pmk_r1_push = 1;
bss->ft_over_ds = 0;
bss->ft_psk_generate_local = 1;
}
#endif
else
{
if (network->security.wpa3_sb_192)
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
bss->tls_flags |= TLS_CONN_SUITEB;
}
else if (network->security.wpa3_sb)
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
bss->tls_flags |= TLS_CONN_SUITEB;
}
else
{
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
}
}
bss->ieee802_1x = 1; /* use IEEE 802.1X */
bss->eapol_version = 2;
bss->eap_server = 1;
#ifdef CONFIG_EAP_FAST
if (
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_FAST_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_FAST_GTC)
#endif
|| false)
{
size_t idlen = os_strlen(network->security.pac_opaque_encr_key);
if (idlen != 32)
{
wpa_printf(MSG_ERROR, "Invalid pac_opaque_encr_key");
return -1;
}
os_free(bss->pac_opaque_encr_key);
bss->pac_opaque_encr_key = os_malloc(16);
if (bss->pac_opaque_encr_key == NULL)
{
wpa_printf(MSG_ERROR, "No memory for pac_opaque_encr_key");
return -1;
}
else if (hexstr2bin(network->security.pac_opaque_encr_key, bss->pac_opaque_encr_key, 16))
{
wpa_printf(MSG_ERROR, "Invalid pac_opaque_encr_key");
return -1;
}
idlen = os_strlen(network->security.a_id);
if (idlen & 1)
{
wpa_printf(MSG_ERROR, "Invalid eap_fast_a_id");
return -1;
}
os_free(bss->eap_fast_a_id);
bss->eap_fast_a_id = os_malloc(idlen / 2);
if (bss->eap_fast_a_id == NULL || hexstr2bin(network->security.a_id, bss->eap_fast_a_id, idlen / 2))
{
wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id");
os_free(bss->eap_fast_a_id);
bss->eap_fast_a_id = NULL;
return -1;
}
else
{
bss->eap_fast_a_id_len = idlen / 2;
}
bss->eap_fast_a_id_info =
dup_binstr("hostapd FAST/MSCHAPv2 GTC", os_strlen("hostapd FAST/MSCHAPv2 GTC"));
bss->eap_fast_prov = network->security.fast_prov;
}
#endif
bss->ca_cert_blob_len = network->security.ca_cert_len;
bss->ca_cert_blob = network->security.ca_cert_data;
bss->server_cert_blob_len = network->security.server_cert_len;
bss->server_cert_blob = network->security.server_cert_data;
bss->private_key_blob_len = network->security.server_key_len;
bss->private_key_blob = network->security.server_key_data;
bss->dh_blob_len = network->security.dh_len;
bss->dh_blob = network->security.dh_data;
str_clear_free(bss->private_key_passwd);
bss->private_key_passwd =
dup_binstr(network->security.server_key_passwd, os_strlen(network->security.server_key_passwd));
#ifdef CONFIG_EAP_TLS
if ((network->security.type == WLAN_SECURITY_EAP_TLS) ||
(network->security.type == WLAN_SECURITY_EAP_TLS_SHA256)
#ifdef CONFIG_11R
|| (network->security.type == WLAN_SECURITY_EAP_TLS_FT) ||
(network->security.type == WLAN_SECURITY_EAP_TLS_FT_SHA384)
#endif
)
{
ret = hostapd_config_read_eap_user(network->security.nusers, network->security.identities, bss);
if (ret != 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to read eap users", __func__);
return -1;
}
}
#endif
if (
#ifdef CONFIG_EAP_SIM
(network->security.type == WLAN_SECURITY_EAP_SIM) ||
#endif
#ifdef CONFIG_EAP_AKA
(network->security.type == WLAN_SECURITY_EAP_AKA) ||
#endif
#ifdef CONFIG_EAP_AKA_PRIME
(network->security.type == WLAN_SECURITY_EAP_AKA_PRIME) ||
#endif
false)
{
ret = hostapd_config_read_default2_eap_user(network, bss);
if (ret != 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to read eap users", __func__);
return -1;
}
}
if (
#ifdef CONFIG_EAP_TTLS
(network->security.type == WLAN_SECURITY_EAP_TTLS) ||
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_TTLS_MSCHAPV2) ||
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_PEAP_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_TTLS
(network->security.type == WLAN_SECURITY_EAP_PEAP_TLS) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_PEAP_GTC) ||
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
(network->security.type == WLAN_SECURITY_EAP_FAST_MSCHAPV2) ||
#endif
#ifdef CONFIG_EAP_GTC
(network->security.type == WLAN_SECURITY_EAP_FAST_GTC) ||
#endif
#endif
false)
{
ret = hostapd_config_read_eap_phase2_user(network, bss);
if (ret != 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to read eap phase2 users", __func__);
return -1;
}
}
break;
#endif
#ifdef CONFIG_WPA_SUPP_WPA3
case WLAN_SECURITY_WPA3_SAE:
case WLAN_SECURITY_WPA2_WPA3_SAE_MIXED:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA3_FT_SAE:
if (network->security.type == WLAN_SECURITY_WPA3_FT_SAE)
{
bss->mobility_domain[0] = 'a';
bss->mobility_domain[1] = '3';
bss->pmk_r1_push = 1;
bss->ft_over_ds = 0;
bss->ft_psk_generate_local = 1;
}
else
#endif
if (network->security.type == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED)
{
if (network->security.pmk_valid && bss->ssid.wpa_psk)
{
os_memcpy(bss->ssid.wpa_psk->psk, network->security.pmk, PMK_LEN);
bss->ssid.wpa_psk->group = 1;
bss->ssid.wpa_psk_set = 1;
}
else
{
bss->ssid.wpa_passphrase = os_strdup(network->security.psk);
if (bss->ssid.wpa_passphrase)
{
hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
bss->ssid.wpa_passphrase_set = 1;
}
else
{
wpa_printf(MSG_DEBUG, "%s:Failed to copy passphrase", __func__);
return -1;
}
}
}
if (wpa_parse_intlist(&bss->sae_groups, network->security.sae_groups))
{
wpa_printf(MSG_ERROR, "Invalid sae_groups value");
return -1;
}
bss->sae_pwe = network->security.pwe_derivation;
bss->transition_disable = network->security.transition_disable;
ret = parse_sae_password(bss, network->security.password);
if (ret != 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to set sae_password", __func__);
return -1;
}
break;
#endif
#ifdef CONFIG_OWE
case WLAN_SECURITY_OWE_ONLY:
if (wpa_parse_intlist(&bss->owe_groups, network->security.owe_groups))
{
wpa_printf(MSG_ERROR, "Invalid owe_groups value");
return -1;
}
break;
#endif
case WLAN_SECURITY_WPA2:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA2_FT:
#endif
case WLAN_SECURITY_WPA_WPA2_MIXED:
#ifdef CONFIG_11R
if (network->security.type == WLAN_SECURITY_WPA2_FT)
{
bss->mobility_domain[0] = 'a';
bss->mobility_domain[1] = '4';
bss->pmk_r1_push = 1;
bss->ft_over_ds = 0;
bss->ft_psk_generate_local = 1;
}
else
#endif
{
if (network->security.type == WLAN_SECURITY_WPA_WPA2_MIXED)
{
bss->wpa = WPA_PROTO_WPA | WPA_PROTO_RSN;
}
}
if (network->security.pmk_valid && bss->ssid.wpa_psk)
{
os_memcpy(bss->ssid.wpa_psk->psk, network->security.pmk, PMK_LEN);
bss->ssid.wpa_psk->group = 1;
bss->ssid.wpa_psk_set = 1;
}
else
{
// str_clear_free(bss->ssid.wpa_passphrase);
bss->ssid.wpa_passphrase = os_strdup(network->security.psk);
if (bss->ssid.wpa_passphrase)
{
hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
bss->ssid.wpa_passphrase_set = 1;
}
else
{
wpa_printf(MSG_DEBUG, "%s:Failed to copy passphrase", __func__);
return -1;
}
}
break;
#ifdef CONFIG_DPP
case WLAN_SECURITY_DPP:
bss->wpa_key_mgmt = WPA_KEY_MGMT_DPP;
break;
#endif
default:
break;
}
#ifdef CONFIG_DPP
if ((network->security.key_mgmt & WLAN_KEY_MGMT_DPP) || (network->security.key_mgmt & WLAN_KEY_MGMT_PSK) ||
(network->security.key_mgmt & WLAN_KEY_MGMT_SAE) || (network->security.key_mgmt & WLAN_KEY_MGMT_IEEE8021X))
{
if (network->security.dpp_connector)
{
os_free(bss->dpp_connector);
bss->dpp_connector = os_strdup((const char *)network->security.dpp_connector);
}
if (network->security.dpp_c_sign_key)
{
wpabuf_free(bss->dpp_csign);
bss->dpp_csign = wpabuf_parse_bin((const char *)network->security.dpp_c_sign_key);
if (!bss->dpp_csign)
{
wpa_printf(MSG_ERROR, "%s: Invalid dpp_csign '%s'", __func__, network->security.dpp_c_sign_key);
return -1;
}
}
if (network->security.dpp_net_access_key)
{
wpabuf_free(bss->dpp_netaccesskey);
bss->dpp_netaccesskey = wpabuf_parse_bin((const char *)network->security.dpp_net_access_key);
if (!bss->dpp_netaccesskey)
{
wpa_printf(MSG_ERROR, "%s: Invalid dpp_netaccesskey '%s'", __func__, network->security.dpp_net_access_key);
return -1;
}
}
#ifdef CONFIG_DPP2
/* Add channels from scan results for APs that advertise Configurator
* Connectivity element */
bss->dpp_configurator_connectivity = 1;
#endif /* CONFIG_DPP2 */
}
#endif
if ((network->security.mfpc) && (network->security.mfpr))
bss->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
else if (network->security.mfpc)
bss->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
return 0;
}
static void hostapd_reset_bss(struct hostapd_bss_config *bss)
{
bss->wpa_key_mgmt = 0;
bss->wpa = 0;
bss->wpa_group = 0;
bss->rsn_pairwise = 0;
bss->wpa_pairwise = 0;
bss->group_mgmt_cipher = 0;
#ifdef CONFIG_11R
bss->pmk_r1_push = 0;
bss->ft_over_ds = 0;
bss->ft_psk_generate_local = 0;
#endif
bss->tls_flags = 0;
bss->ieee802_1x = 0;
bss->eapol_version = 0;
bss->eap_server = 0;
bss->sae_pwe = 0;
bss->transition_disable = 0;
bss->ssid.wpa_passphrase_set = 0;
bss->ieee80211w = NO_MGMT_FRAME_PROTECTION;
}
#ifdef CONFIG_WPA_SUPP_WPA3
static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
{
struct sae_password_entry *pw, *tmp;
pw = conf->sae_passwords;
conf->sae_passwords = NULL;
while (pw)
{
tmp = pw;
pw = pw->next;
str_clear_free(tmp->password);
os_free(tmp->identifier);
#ifdef CONFIG_SAE
sae_deinit_pt(tmp->pt);
#endif /* CONFIG_SAE */
#ifdef CONFIG_SAE_PK
sae_deinit_pk(tmp->pk);
#endif /* CONFIG_SAE_PK */
os_free(tmp);
}
}
#endif
static int hostapd_free_bss(struct hostapd_iface *hapd_s, struct wlan_network *network)
{
struct hostapd_config *conf;
struct hostapd_bss_config *bss;
conf = hapd_s->conf;
bss = conf->last_bss;
switch (network->security.type)
{
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_TLS:
case WLAN_SECURITY_EAP_TLS_SHA256:
#ifdef CONFIG_11R
case WLAN_SECURITY_EAP_TLS_FT:
case WLAN_SECURITY_EAP_TLS_FT_SHA384:
#endif
#endif
#ifdef CONFIG_EAP_TTLS
case WLAN_SECURITY_EAP_TTLS:
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_TTLS_MSCHAPV2:
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_PEAP_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_PEAP_TLS:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_PEAP_GTC:
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_FAST_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_FAST_GTC:
#endif
if (bss->pac_opaque_encr_key)
{
os_free(bss->pac_opaque_encr_key);
bss->pac_opaque_encr_key = NULL;
}
if (bss->eap_fast_a_id)
{
os_free(bss->eap_fast_a_id);
bss->eap_fast_a_id = NULL;
}
str_clear_free(bss->eap_fast_a_id_info);
bss->eap_fast_a_id_info = NULL;
#endif
hostapd_config_free_eap_users(bss->eap_user);
bss->eap_user = NULL;
break;
#endif
#ifdef CONFIG_WPA_SUPP_WPA3
case WLAN_SECURITY_WPA2_WPA3_SAE_MIXED:
str_clear_free(bss->ssid.wpa_passphrase);
bss->ssid.wpa_passphrase = NULL;
hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
case WLAN_SECURITY_WPA3_SAE:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA3_FT_SAE:
#endif
hostapd_config_free_sae_passwords(bss);
break;
#endif
#ifdef CONFIG_OWE
case WLAN_SECURITY_OWE_ONLY:
break;
#endif
case WLAN_SECURITY_WPA2:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA2_FT:
#endif
case WLAN_SECURITY_WPA_WPA2_MIXED:
str_clear_free(bss->ssid.wpa_passphrase);
bss->ssid.wpa_passphrase = NULL;
hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
break;
default:
break;
}
hostapd_reset_bss(bss);
if (bss->accept_mac)
{
os_free(bss->accept_mac);
bss->accept_mac =0;
}
if (bss->deny_mac)
{
os_free(bss->deny_mac);
bss->deny_mac = 0;
}
return 0;
}
#endif
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
static void str2hex(const char *str, char *strH)
{
unsigned int i, j;
for (i = 0, j = 0; i < strlen(str); i++, j += 2)
{
sprintf((char*)strH + j, "%02X", str[i]);
}
strH[j] = '\0';
}
#endif
int wpa_supp_add_network(const struct netif *dev, struct wlan_network *network)
{
int ret = 0;
struct wpa_ssid *ssid = NULL;
bool pmf = true;
struct wpa_supplicant *wpa_s;
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
char phase1[256] = {0};
char *openssl_ciphers;
char HashH[65] = {0};
char hashstr[128] = {0};
#endif
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
#endif
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (network->role == WLAN_BSS_ROLE_UAP)
{
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ssid = wpa_supplicant_add_network(wpa_s);
ssid->ssid = os_zalloc(sizeof(u8) * MAX_SSID_LEN);
ssid->ssid_len = os_strlen(network->ssid);
memcpy(ssid->ssid, network->ssid, ssid->ssid_len);
ssid->disabled = 1;
ssid->key_mgmt = network->security.key_mgmt;
ssid->scan_ssid = 1;
//ssid->proactive_key_caching = network->security.pkc;
if (network->security.type == WLAN_SECURITY_WILDCARD)
{
if (network->security.psk_len)
{
network->security.type = WLAN_SECURITY_WPA2;
}
else
{
network->security.type = WLAN_SECURITY_NONE;
}
}
if (network->security.type != WLAN_SECURITY_NONE)
{
ssid->proto = WPA_PROTO_RSN;
ssid->group_cipher = network->security.group_cipher;
ssid->pairwise_cipher = network->security.pairwise_cipher;
ssid->group_mgmt_cipher = network->security.group_mgmt_cipher;
}
if (network->channel != 0U)
{
/* We use global channel list here and also use the widest
* op_class for 5GHz channels as there is no user input
* for these.
*/
int freq = ieee80211_chan_to_freq(NULL, 81, network->channel);
if (freq <= 0)
{
freq = ieee80211_chan_to_freq(NULL, 128, network->channel);
}
if (freq <= 0)
{
wpa_printf(MSG_DEBUG, "Invalid channel %d", network->channel);
ret = -1;
goto out;
}
if (network->role == WLAN_BSS_ROLE_UAP)
{
ssid->frequency = freq;
}
else
{
ssid->scan_freq = os_zalloc(2 * sizeof(int));
if (!ssid->scan_freq)
{
ret = -1;
goto out;
}
ssid->scan_freq[0] = freq;
ssid->scan_freq[1] = 0;
ssid->freq_list = os_zalloc(2 * sizeof(int));
if (!ssid->freq_list)
{
os_free(ssid->scan_freq);
ret = -1;
goto out;
}
ssid->freq_list[0] = freq;
ssid->freq_list[1] = 0;
}
}
wpa_s->conf->filter_ssids = 1;
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
openssl_ciphers = "DEFAULT:!EXP:!LOW";
#endif
if (network->role == WLAN_BSS_ROLE_UAP)
{
wpa_s->conf->ap_scan = 2;
ssid->mode = WPAS_MODE_AP;
}
else
{
wpa_s->conf->ap_scan = 1;
ssid->mode = WPAS_MODE_INFRA;
}
switch (network->security.type)
{
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_TLS:
case WLAN_SECURITY_EAP_TLS_SHA256:
#ifdef CONFIG_11R
case WLAN_SECURITY_EAP_TLS_FT:
case WLAN_SECURITY_EAP_TLS_FT_SHA384:
#endif
#endif
#ifdef CONFIG_EAP_TTLS
case WLAN_SECURITY_EAP_TTLS:
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_TTLS_MSCHAPV2:
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_PEAP_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_PEAP_TLS:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_PEAP_GTC:
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_FAST_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_FAST_GTC:
#endif
#endif
#ifdef CONFIG_EAP_SIM
case WLAN_SECURITY_EAP_SIM:
#endif
#ifdef CONFIG_EAP_AKA
case WLAN_SECURITY_EAP_AKA:
#endif
#ifdef CONFIG_EAP_AKA_PRIME
case WLAN_SECURITY_EAP_AKA_PRIME:
#endif
if (network->role == WLAN_BSS_ROLE_UAP)
{
ret = -1;
goto out;
}
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
#ifdef CONFIG_EAP_TLS
if (network->security.type == WLAN_SECURITY_EAP_TLS_SHA256)
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
#ifdef CONFIG_11R
else if (network->security.type == WLAN_SECURITY_EAP_TLS_FT)
ssid->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
else if (network->security.type == WLAN_SECURITY_EAP_TLS_FT_SHA384)
{
ssid->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
openssl_ciphers = "SUITEB192";
}
#endif
else
#endif
#endif
{
if (network->security.wpa3_sb_192)
{
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
openssl_ciphers = "SUITEB192";
}
else if (network->security.wpa3_sb)
{
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
openssl_ciphers = "SUITEB128";
}
else
{
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
}
}
str_clear_free((char *)wpa_s->conf->openssl_ciphers);
wpa_s->conf->openssl_ciphers = dup_binstr(openssl_ciphers, os_strlen(openssl_ciphers));
ssid->eap.eap_methods = os_zalloc(sizeof(struct eap_method_type));
if (!ssid->eap.eap_methods)
{
ret = -1;
goto out;
}
ssid->eap.eap_methods->vendor = EAP_VENDOR_IETF;
ssid->eap.eap_methods->method = EAP_TYPE_TLS;
ssid->eap.anonymous_identity_len = os_strlen(network->security.anonymous_identity);
if (ssid->eap.anonymous_identity_len)
{
str_clear_free((char *)ssid->eap.anonymous_identity);
ssid->eap.anonymous_identity =
(u8 *)dup_binstr(network->security.anonymous_identity, ssid->eap.anonymous_identity_len);
}
ssid->eap.identity_len = os_strlen(network->security.identity);
if (ssid->eap.identity_len)
{
str_clear_free((char *)ssid->eap.identity);
ssid->eap.identity = (u8 *)dup_binstr(network->security.identity, ssid->eap.identity_len);
}
ssid->eap.password_len = os_strlen(network->security.eap_password);
if (ssid->eap.password_len)
{
str_clear_free((char *)ssid->eap.password);
ssid->eap.password = (u8 *)dup_binstr(network->security.eap_password, ssid->eap.password_len);
}
if (os_strlen(network->security.domain_match))
{
str_clear_free(ssid->eap.cert.domain_match);
ssid->eap.cert.domain_match = dup_binstr(network->security.domain_match, os_strlen(network->security.domain_match));
}
if (os_strlen(network->security.domain_suffix_match))
{
str_clear_free(ssid->eap.cert.domain_suffix_match);
ssid->eap.cert.domain_suffix_match = dup_binstr(network->security.domain_suffix_match, os_strlen(network->security.domain_suffix_match));
}
if (os_strlen(network->security.ca_cert_hash))
{
str2hex(network->security.ca_cert_hash, HashH);
os_snprintf(hashstr, os_strlen(hashstr), "hash://server/sha256/%s", HashH);
str_clear_free(ssid->eap.cert.ca_cert);
ssid->eap.cert.ca_cert = dup_binstr(hashstr, os_strlen(hashstr));
}
else if (network->security.ca_cert_len)
{
wpa_config_process_blob(wpa_s->conf, "ca_cert", network->security.ca_cert_data,
network->security.ca_cert_len);
str_clear_free(ssid->eap.cert.ca_cert);
ssid->eap.cert.ca_cert = dup_binstr("blob://ca_cert", os_strlen("blob://ca_cert"));
}
if (network->security.client_cert_len)
{
wpa_config_process_blob(wpa_s->conf, "client_cert", network->security.client_cert_data,
network->security.client_cert_len);
str_clear_free(ssid->eap.cert.client_cert);
ssid->eap.cert.client_cert = dup_binstr("blob://client_cert", os_strlen("blob://client_cert"));
}
if (network->security.client_key_len)
{
wpa_config_process_blob(wpa_s->conf, "private_key", network->security.client_key_data,
network->security.client_key_len);
str_clear_free(ssid->eap.cert.private_key);
ssid->eap.cert.private_key = dup_binstr("blob://private_key", os_strlen("blob://private_key"));
str_clear_free(ssid->eap.cert.private_key_passwd);
ssid->eap.cert.private_key_passwd =
dup_binstr(network->security.client_key_passwd, os_strlen(network->security.client_key_passwd));
}
if (network->security.ca_cert2_len)
{
wpa_config_process_blob(wpa_s->conf, "ca_cert2", network->security.ca_cert2_data,
network->security.ca_cert2_len);
str_clear_free(ssid->eap.phase2_cert.ca_cert);
ssid->eap.phase2_cert.ca_cert = dup_binstr("blob://ca_cert2", os_strlen("blob://ca_cert2"));
}
else
{
str_clear_free(ssid->eap.phase2_cert.ca_cert);
ssid->eap.phase2_cert.ca_cert = dup_binstr("blob://ca_cert", os_strlen("blob://ca_cert"));
}
if (network->security.client_cert2_len)
{
wpa_config_process_blob(wpa_s->conf, "client_cert2", network->security.client_cert2_data,
network->security.client_cert2_len);
str_clear_free(ssid->eap.phase2_cert.client_cert);
ssid->eap.phase2_cert.client_cert =
dup_binstr("blob://client_cert2", os_strlen("blob://client_cert2"));
}
else
{
str_clear_free(ssid->eap.phase2_cert.client_cert);
ssid->eap.phase2_cert.client_cert =
dup_binstr("blob://client_cert", os_strlen("blob://client_cert"));
}
if (network->security.client_key2_len)
{
wpa_config_process_blob(wpa_s->conf, "private_key2", network->security.client_key2_data,
network->security.client_key2_len);
str_clear_free(ssid->eap.phase2_cert.private_key);
ssid->eap.phase2_cert.private_key =
dup_binstr("blob://private_key2", os_strlen("blob://private_key2"));
str_clear_free(ssid->eap.phase2_cert.private_key_passwd);
ssid->eap.phase2_cert.private_key_passwd = dup_binstr(
network->security.client_key2_passwd, os_strlen(network->security.client_key2_passwd));
}
else
{
ssid->eap.phase2_cert.private_key =
dup_binstr("blob://private_key", os_strlen("blob://private_key"));
str_clear_free(ssid->eap.phase2_cert.private_key_passwd);
ssid->eap.phase2_cert.private_key_passwd =
dup_binstr(network->security.client_key_passwd, os_strlen(network->security.client_key_passwd));
}
str_clear_free(ssid->eap.pac_file);
ssid->eap.pac_file = dup_binstr("blob://eap-fast-pac", os_strlen("blob://eap-fast-pac"));
#ifdef CONFIG_EAP_TTLS
if (network->security.type == WLAN_SECURITY_EAP_TTLS)
{
ssid->eap.eap_methods->method = EAP_TYPE_TTLS;
const char *phase2 = "autheap=TLS";
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#ifdef CONFIG_EAP_MSCHAPV2
if (network->security.type == WLAN_SECURITY_EAP_TTLS_MSCHAPV2)
{
ssid->eap.eap_methods->method = EAP_TYPE_TTLS;
const char *phase2 = "auth=MSCHAPV2";
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
if (network->security.type == WLAN_SECURITY_EAP_PEAP_MSCHAPV2)
{
ssid->eap.eap_methods->method = EAP_TYPE_PEAP;
const char *phase2 = "auth=MSCHAPV2";
os_snprintf(phase1, sizeof(phase1), "peapver=%d peaplabel=%d crypto_binding=%d", network->security.eap_ver,
network->security.peap_label, network->security.eap_crypto_binding);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#ifdef CONFIG_EAP_TLS
if (network->security.type == WLAN_SECURITY_EAP_PEAP_TLS)
{
ssid->eap.eap_methods->method = EAP_TYPE_PEAP;
const char *phase2 = "auth=TLS";
os_snprintf(phase1, sizeof(phase1), "peapver=%d peaplabel=%d crypto_binding=%d", network->security.eap_ver,
network->security.peap_label, network->security.eap_crypto_binding);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#ifdef CONFIG_EAP_GTC
if (network->security.type == WLAN_SECURITY_EAP_PEAP_GTC)
{
ssid->eap.eap_methods->method = EAP_TYPE_PEAP;
const char *phase2 = "auth=GTC";
os_snprintf(phase1, sizeof(phase1), "peapver=%d peaplabel=%d crypto_binding=%d", network->security.eap_ver,
network->security.peap_label, network->security.eap_crypto_binding);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#endif
#ifdef CONFIG_EAP_SIM
if (network->security.type == WLAN_SECURITY_EAP_SIM)
{
os_snprintf(phase1, sizeof(phase1), "result_ind=%d", network->security.eap_result_ind);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
ssid->eap.eap_methods->method = EAP_TYPE_SIM;
}
#endif
#ifdef CONFIG_EAP_AKA
if (network->security.type == WLAN_SECURITY_EAP_AKA)
{
os_snprintf(phase1, sizeof(phase1), "result_ind=%d", network->security.eap_result_ind);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
ssid->eap.eap_methods->method = EAP_TYPE_AKA;
}
#endif
#ifdef CONFIG_EAP_AKA_PRIME
if (network->security.type == WLAN_SECURITY_EAP_AKA_PRIME)
{
os_snprintf(phase1, sizeof(phase1), "result_ind=%d", network->security.eap_result_ind);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
ssid->eap.eap_methods->method = EAP_TYPE_AKA_PRIME;
}
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
if (network->security.type == WLAN_SECURITY_EAP_FAST_MSCHAPV2)
{
ssid->eap.eap_methods->method = EAP_TYPE_FAST;
int prov = 3;
const char *phase2 = "auth=MSCHAPV2";
os_snprintf(phase1, sizeof(phase1), "fast_provisioning=%d fast_pac_format=binary", prov);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#ifdef CONFIG_EAP_GTC
if (network->security.type == WLAN_SECURITY_EAP_FAST_GTC)
{
ssid->eap.eap_methods->method = EAP_TYPE_FAST;
int prov = 3;
const char *phase2 = "auth=GTC";
os_snprintf(phase1, sizeof(phase1), "fast_provisioning=%d fast_pac_format=binary", prov);
str_clear_free(ssid->eap.phase1);
ssid->eap.phase1 = dup_binstr(phase1, os_strlen(phase1));
str_clear_free(ssid->eap.phase2);
ssid->eap.phase2 = dup_binstr(phase2, os_strlen(phase2));
}
#endif
#endif
break;
#endif
#ifdef CONFIG_WPA_SUPP_WPA3
case WLAN_SECURITY_WPA3_SAE:
case WLAN_SECURITY_WPA2_WPA3_SAE_MIXED:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA3_FT_SAE:
if (network->security.type == WLAN_SECURITY_WPA3_FT_SAE)
{
if (network->role == WLAN_BSS_ROLE_UAP)
{
ret = -1;
goto out;
}
}
else
#endif
if (network->security.type == WLAN_SECURITY_WPA2_WPA3_SAE_MIXED)
{
str_clear_free(ssid->passphrase);
ssid->passphrase = dup_binstr(network->security.psk, network->security.psk_len);
if (ssid->passphrase == NULL)
{
wpa_printf(MSG_DEBUG, "%s:Failed to copy passphrase\n", __func__);
ret = -1;
goto out;
}
wpa_config_update_psk(ssid);
}
if (wpa_parse_intlist(&wpa_s->conf->sae_groups, network->security.sae_groups))
{
wpa_printf(MSG_ERROR, "Invalid sae_groups value");
return -1;
}
wpa_s->conf->sae_pwe = network->security.pwe_derivation;
ssid->transition_disable = network->security.transition_disable;
str_clear_free(ssid->sae_password);
ssid->sae_password = dup_binstr(network->security.password, network->security.password_len);
if (ssid->sae_password == NULL)
{
wpa_printf(MSG_DEBUG, "%s:Failed to copy sae_password\n", __func__);
ret = -1;
goto out;
}
break;
#endif
#ifdef CONFIG_OWE
case WLAN_SECURITY_OWE_ONLY:
ssid->owe_only = 1;
break;
#endif
case WLAN_SECURITY_WPA:
case WLAN_SECURITY_WPA2:
case WLAN_SECURITY_WPA_WPA2_MIXED:
#ifdef CONFIG_11R
case WLAN_SECURITY_WPA2_FT:
if (network->security.type == WLAN_SECURITY_WPA2_FT)
{
if (network->role == WLAN_BSS_ROLE_UAP)
{
ret = -1;
goto out;
}
}
#endif
ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
ssid->proto = WPA_PROTO_RSN;
ssid->pairwise_cipher = WPA_CIPHER_CCMP;
if ((network->security.type == WLAN_SECURITY_WPA) || (network->security.type == WLAN_SECURITY_WPA_WPA2_MIXED))
{
ssid->proto |= WPA_PROTO_WPA;
ssid->group_cipher |= WPA_CIPHER_TKIP;
ssid->pairwise_cipher |= WPA_CIPHER_TKIP;
}
if (network->security.type == WLAN_SECURITY_WPA2)
{
ssid->group_cipher |= WPA_CIPHER_TKIP;
}
if (network->security.pmk_valid)
{
os_memcpy(ssid->psk, network->security.pmk, PMK_LEN);
ssid->psk_set = 1;
}
else
{
str_clear_free(ssid->passphrase);
ssid->passphrase = dup_binstr(network->security.psk, network->security.psk_len);
if (ssid->passphrase == NULL)
{
wpa_printf(MSG_DEBUG, "%s:Failed to copy passphrase\n", __func__);
ret = -1;
goto out;
}
wpa_config_update_psk(ssid);
}
break;
default:
break;
}
if (pmf)
{
if ((network->security.mfpc) && (network->security.mfpr))
ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
else if (network->security.mfpc)
ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
}
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
wpa_config_update_prio_list(wpa_s->conf);
network->id = ssid->id;
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = ADD;
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
static void wpa_supp_scan_res_fail_handler(struct wpa_supplicant *wpa_s)
{
if (wpa_s->scan_work)
{
struct wpa_radio_work *work = wpa_s->scan_work;
wpa_s->scan_work = NULL;
radio_work_done(work);
}
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
}
int wpa_supp_connect(const struct netif *dev, struct wlan_network *network)
{
struct wpa_ssid *ssid = NULL, *ssid_prev = NULL;
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ssid = ssid_prev = wpa_s->conf->ssid;
while (ssid)
{
if (network->id == ssid->id)
{
break;
}
ssid_prev = ssid;
ssid = ssid->next;
}
if (ssid == NULL)
{
ret = -1;
goto out;
}
/* the specific connect ssid isn't in the foremost */
if (ssid != ssid_prev)
{
/* remove the specific connect ssid to the foremost in the conf->ssid list */
ssid_prev->next = ssid->next;
ssid->next = wpa_s->conf->ssid;
wpa_s->conf->ssid = ssid;
}
if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid && wpa_s->wpa_state >= WPA_AUTHENTICATING)
{
/* We are already associated with the selected network */
wpa_printf(MSG_DEBUG,
"Already associated with the "
"selected network - do Deauthentication");
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
goto out;
}
wpa_s->scan_min_time.sec = 0;
wpa_s->scan_min_time.usec = 0;
//wpa_supplicant_enable_network(wpa_s, ssid);
wpa_supplicant_select_network(wpa_s, ssid);
send_wpa_supplicant_dummy_event();
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = CONNECT;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_disable(const struct netif *dev, struct wlan_network *network)
{
struct wpa_ssid *ssid = NULL;
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ssid = wpa_s->conf->ssid;
while (ssid)
{
if (network->id == ssid->id)
{
break;
}
ssid = ssid->next;
}
if (ssid == NULL)
{
ret = -1;
goto out;
}
wpa_supplicant_disable_network(wpa_s, ssid);
send_wpa_supplicant_dummy_event();
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_disconnect(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#if 0
sme_clear_on_disassoc(wpa_s);
wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = NULL;
#ifdef CONFIG_SAE
os_free(wpa_s->sme.sae_rejected_groups);
wpa_s->sme.sae_rejected_groups = NULL;
#endif /* CONFIG_SAE */
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
os_free(wpa_s->select_network_scan_freqs);
wpa_s->select_network_scan_freqs = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
os_free(wpa_s->last_scan_res);
wpa_s->last_scan_res = NULL;
#endif
wpa_s->scan_res_fail_handler = NULL;
eapol_sm_invalidate_cached_session(wpa_s->eapol);
wpas_request_disconnection(wpa_s);
send_wpa_supplicant_dummy_event();
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = DISCONNECT;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_remove_network(const struct netif *dev, struct wlan_network *network)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
#endif
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (network->role == WLAN_BSS_ROLE_UAP)
{
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s || network->id == -1)
{
ret = -1;
goto out;
}
switch (network->security.type)
{
#ifdef CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_TLS:
case WLAN_SECURITY_EAP_TLS_SHA256:
#ifdef CONFIG_11R
case WLAN_SECURITY_EAP_TLS_FT:
case WLAN_SECURITY_EAP_TLS_FT_SHA384:
#endif
#endif
#ifdef CONFIG_EAP_TTLS
case WLAN_SECURITY_EAP_TTLS:
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_TTLS_MSCHAPV2:
#endif
#endif
#ifdef CONFIG_EAP_PEAP
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_PEAP_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_TLS
case WLAN_SECURITY_EAP_PEAP_TLS:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_PEAP_GTC:
#endif
#endif
#ifdef CONFIG_EAP_FAST
#ifdef CONFIG_EAP_MSCHAPV2
case WLAN_SECURITY_EAP_FAST_MSCHAPV2:
#endif
#ifdef CONFIG_EAP_GTC
case WLAN_SECURITY_EAP_FAST_GTC:
#endif
#endif
#ifdef CONFIG_EAP_SIM
case WLAN_SECURITY_EAP_SIM:
#endif
#ifdef CONFIG_EAP_AKA
case WLAN_SECURITY_EAP_AKA:
#endif
#ifdef CONFIG_EAP_AKA_PRIME
case WLAN_SECURITY_EAP_AKA_PRIME:
#endif
wpa_config_remove_blob(wpa_s->conf, "ca_cert");
wpa_config_remove_blob(wpa_s->conf, "client_cert");
wpa_config_remove_blob(wpa_s->conf, "private_key");
wpa_config_remove_blob(wpa_s->conf, "ca_cert2");
wpa_config_remove_blob(wpa_s->conf, "cloent_cert2");
wpa_config_remove_blob(wpa_s->conf, "private_key2");
break;
#endif
default:
break;
}
ret = wpa_supplicant_remove_network(wpa_s, network->id);
if (ret == -1)
{
wpa_printf(MSG_DEBUG,
"Could not find network "
"id=%d",
network->id);
ret = -1;
goto out;
}
if (ret == -2)
{
wpa_printf(MSG_DEBUG,
"Not able to remove the "
"network id=%d",
network->id);
ret = -1;
goto out;
}
ret = 0;
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = REMOVE;
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_pmksa_list(const struct netif *dev, char *buf, size_t buflen)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
size_t reply_len = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
#ifdef CONFIG_AP
reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len], buflen - reply_len);
#endif /* CONFIG_AP */
if (reply_len == 0)
{
ret = -1;
}
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_pmksa_flush(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
#ifdef CONFIG_AP
wpas_ap_pmksa_cache_flush(wpa_s);
#endif /* CONFIG_AP */
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_reassociate(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpas_request_connection(wpa_s);
send_wpa_supplicant_dummy_event();
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = RECONNECT;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_set_autoconnect(const struct netif *dev, int enable)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_s->auto_reconnect_disabled = !enable;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_set_scan_interval(const struct netif *dev, int scan_int)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ret = wpa_supplicant_set_scan_interval(wpa_s, scan_int);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
void wpa_supp_set_ap_max_num_sta(const struct netif *dev, unsigned int max_num_sta)
{
h_max_num_sta = (int)max_num_sta;
}
void wpa_supp_set_ap_beacon_int(const struct netif *dev, unsigned short beacon_int)
{
h_beacon_int = beacon_int;
}
void wpa_supp_set_ap_bw(const struct netif *dev, unsigned char bw)
{
bandwidth = bw;
}
void wpa_supp_set_ap_hidden_ssid(const struct netif *dev, const t_u8 hidden_ssid)
{
h_hidden_ssid = hidden_ssid;
}
int wpa_supp_set_ap_country(const struct netif *dev, const char *country, const unsigned char country3)
{
int ret = 0;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
struct hostapd_config *conf;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
conf = hapd_s->conf;
conf->country[0] = country[0];
conf->country[1] = country[1];
conf->country[2] = country3;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#else
struct wpa_ssid *ssid = NULL;
struct wpa_supplicant *wpa_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_s->conf->country[0] = country[0];
wpa_s->conf->country[1] = country[1];
wpa_s->conf->country[2] = country3;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#endif
return ret;
}
void wpa_supp_set_ap_11d_state(const struct netif *dev, int state)
{
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
struct hostapd_config *conf;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
goto out;
}
conf = hapd_s->conf;
conf->ieee80211d = state ? 1 : 0;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#endif
}
int wpa_supp_start_ap(const struct netif *dev, struct wlan_network *network, int reload)
{
int ret = 0;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
struct hostapd_config *conf;
struct hostapd_bss_config *bss;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
ret = hostapd_update_bss(hapd_s, network);
if (ret != 0)
{
ret = -1;
goto out;
}
conf = hapd_s->conf;
bss = conf->last_bss;
bss->ignore_broadcast_ssid = h_hidden_ssid;
conf->beacon_int = h_beacon_int;
bss->max_num_sta = h_max_num_sta;
if (bandwidth == 1)
{
conf->secondary_channel = 0;
conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
conf->ht_capab &= ~HT_CAP_INFO_SHORT_GI40MHZ;
#ifdef CONFIG_11AC
conf->vht_oper_chwidth = CHANWIDTH_USE_HT;
conf->vht_oper_centr_freq_seg0_idx = network->channel;
#endif
#ifdef CONFIG_11AX
conf->he_oper_chwidth = CHANWIDTH_USE_HT;
conf->he_oper_centr_freq_seg0_idx = network->channel;
#endif
}
else if (bandwidth == 2)
{
conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
#ifdef CONFIG_11AC
conf->vht_oper_chwidth = CHANWIDTH_USE_HT;
if (network->channel >= 36 && network->channel <= 40)
{
conf->vht_oper_centr_freq_seg0_idx = 38;
}
else if (network->channel >= 44 && network->channel <= 48)
{
conf->vht_oper_centr_freq_seg0_idx = 46;
}
else if (network->channel >= 149 && network->channel <= 153)
{
conf->vht_oper_centr_freq_seg0_idx = 151;
}
else if (network->channel >= 157 && network->channel <= 161)
{
conf->vht_oper_centr_freq_seg0_idx = 159;
}
else if (network->channel >= 165 && network->channel <= 169)
{
conf->vht_oper_centr_freq_seg1_idx = 167;
}
else if (network->channel >= 173 && network->channel <= 177)
{
conf->vht_oper_centr_freq_seg0_idx = 175;
}
#endif
#ifdef CONFIG_11AX
conf->he_oper_chwidth = CHANWIDTH_USE_HT;
if (network->channel >= 36 && network->channel <= 40)
{
conf->he_oper_centr_freq_seg0_idx = 38;
}
else if (network->channel >= 44 && network->channel <= 48)
{
conf->he_oper_centr_freq_seg0_idx = 46;
}
else if (network->channel >= 149 && network->channel <= 153)
{
conf->he_oper_centr_freq_seg0_idx = 151;
}
else if (network->channel >= 157 && network->channel <= 161)
{
conf->he_oper_centr_freq_seg0_idx = 159;
}
else if (network->channel >= 165 && network->channel <= 169)
{
conf->he_oper_centr_freq_seg0_idx = 167;
}
else if (network->channel >= 173 && network->channel <= 177)
{
conf->he_oper_centr_freq_seg0_idx = 175;
}
#endif
}
else if (bandwidth == 3)
{
conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
#ifdef CONFIG_11AC
conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
if (network->channel >= 36 && network->channel <= 48)
{
conf->vht_oper_centr_freq_seg0_idx = 42;
}
else if (network->channel >= 149 && network->channel <= 161)
{
conf->vht_oper_centr_freq_seg0_idx = 155;
}
else if (network->channel >= 165 && network->channel <= 177)
{
conf->vht_oper_centr_freq_seg0_idx = 171;
}
#endif
#ifdef CONFIG_11AX
conf->he_oper_chwidth = CHANWIDTH_80MHZ;
if (network->channel >= 36 && network->channel <= 48)
{
conf->he_oper_centr_freq_seg0_idx = 42;
}
else if (network->channel >= 149 && network->channel <= 161)
{
conf->he_oper_centr_freq_seg0_idx = 155;
}
else if (network->channel >= 165 && network->channel <= 177)
{
conf->he_oper_centr_freq_seg0_idx = 171;
}
#endif
}
if (reload)
{
ret = hostapd_reload_iface(hapd_s);
}
else
{
ret = hostapd_enable_iface(hapd_s);
}
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = START;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#else
struct wpa_ssid *ssid = NULL;
struct wpa_supplicant *wpa_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ssid = wpa_s->conf->ssid;
while (ssid)
{
if (network->id == ssid->id)
{
break;
}
ssid = ssid->next;
}
if (ssid == NULL)
{
ret = -1;
goto out;
}
wpa_s->connect_without_scan = ssid;
wpa_supplicant_enable_network(wpa_s, ssid);
wpa_supplicant_select_network(wpa_s, ssid);
send_wpa_supplicant_dummy_event();
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = START;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#endif
return ret;
}
int wpa_supp_stop_ap(const struct netif *dev, struct wlan_network *network)
{
int ret = 0;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
ret = hostapd_disable_iface(hapd_s);
bandwidth = 2;
h_hidden_ssid = 0;
h_beacon_int = 100;
h_max_num_sta = 8;
ret = hostapd_free_bss(hapd_s, network);
if (ret != 0)
{
ret = -1;
goto out;
}
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#else
struct wpa_supplicant *wpa_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ret = wpas_ap_stop_ap(wpa_s);
// wpa_supplicant_ap_deinit(wpa_s);
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = STOP;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
#endif
return ret;
}
void wpa_supp_set_bgscan(const struct netif *dev, const int short_interval, const int signal_threshold, const int long_interval)
{
struct wpa_supplicant *wpa_s;
char bgscan_str[128] = {0};
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
goto out;
}
snprintf(bgscan_str, 128, "simple:%d:%d:%d", short_interval, signal_threshold, long_interval);
os_free(wpa_s->conf->bgscan);
wpa_s->conf->bgscan = os_strdup(bgscan_str);
//wpa_supplicant_reset_bgscan(wpa_s);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
}
int wpa_supp_set_okc(const struct netif *dev, unsigned char okc)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_s->conf->okc = okc;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_roam(const struct netif *dev, unsigned char *bssid)
{
struct wpa_supplicant *wpa_s;
// struct wpa_bss *bss;
// struct wpa_ssid *ssid;
struct wpa_radio_work *already_connecting;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#if 0
ssid = wpa_s->current_ssid;
wpa_printf(MSG_DEBUG, "ROAM " MACSTR, MAC2STR(bssid));
if (!ssid)
{
wpa_printf(MSG_DEBUG,
"ROAM: No network "
"configuration known for the target AP");
ret = -1;
goto out;
}
bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
if (!bss)
{
wpa_printf(MSG_DEBUG,
"ROAM: Target AP not found "
"from BSS table");
ret = -1;
goto out;
}
/*
* TODO: Find best network configuration block from configuration to
* allow roaming to other networks
*/
#endif
already_connecting = radio_work_pending(wpa_s, "sme-connect");
wpa_s->own_reconnect_req = 1;
// wpa_supplicant_connect(wpa_s, bss, ssid);
send_wpa_supplicant_dummy_event();
/*
* Indicate that an explicitly requested roam is in progress so scan
* results that come in before the 'sme-connect' radio work gets
* executed do not override the original connection attempt.
*/
if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
wpa_s->roam_in_progress = true;
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = ROAM;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
static void wpas_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
{
struct wpa_supplicant *wpa_s = ctx;
size_t len;
const u8 *data;
/*
* Neighbor Report element (IEEE P802.11-REVmc/D5.0)
* BSSID[6]
* BSSID Information[4]
* Operating Class[1]
* Channel Number[1]
* PHY Type[1]
* Optional Subelements[variable]
*/
#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0)
{
wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
goto out;
}
data = wpabuf_head_u8(neighbor_rep);
len = wpabuf_len(neighbor_rep);
while (len >= 2 + NR_IE_MIN_LEN)
{
const u8 *nr;
char lci[256 * 2 + 1];
char civic[256 * 2 + 1];
u8 nr_len = data[1];
const u8 *pos = data, *end;
if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || nr_len < NR_IE_MIN_LEN)
{
wpa_dbg(wpa_s, MSG_DEBUG, "CTRL: Invalid Neighbor Report element: id=%u len=%u", data[0], nr_len);
goto out;
}
if (2U + nr_len > len)
{
wpa_dbg(wpa_s, MSG_DEBUG, "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", data[0], len,
nr_len);
goto out;
}
pos += 2;
end = pos + nr_len;
nr = pos;
pos += NR_IE_MIN_LEN;
lci[0] = '\0';
civic[0] = '\0';
while (end - pos > 2)
{
u8 s_id, s_len;
s_id = *pos++;
s_len = *pos++;
if (s_len > end - pos)
goto out;
if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3)
{
/* Measurement Token[1] */
/* Measurement Report Mode[1] */
/* Measurement Type[1] */
/* Measurement Report[variable] */
switch (pos[2])
{
case MEASURE_TYPE_LCI:
if (lci[0])
break;
wpa_snprintf_hex(lci, sizeof(lci), pos, s_len);
break;
case MEASURE_TYPE_LOCATION_CIVIC:
if (civic[0])
break;
wpa_snprintf_hex(civic, sizeof(civic), pos, s_len);
break;
}
}
pos += s_len;
}
wpa_msg_ctrl(wpa_s, MSG_INFO,
RRM_EVENT_NEIGHBOR_REP_RXED "bssid=" MACSTR " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], nr[ETH_ALEN + 6],
lci[0] ? " lci=" : "", lci, civic[0] ? " civic=" : "", civic);
data = end;
len -= 2 + nr_len;
}
wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_COMPLETED);
out:
wpabuf_free(neighbor_rep);
}
int wpa_supp_send_neighbor_rep(const struct netif *dev, char *pssid, int lci, int civic)
{
struct wpa_supplicant *wpa_s;
struct wpa_ssid_value ssid, *ssid_p = NULL;
int ret;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (wpa_s == NULL)
{
ret = -1;
goto out;
}
if (pssid != NULL)
{
os_memset(&ssid, 0x00, sizeof(struct wpa_ssid_value));
ssid.ssid_len = os_strlen(pssid);
os_memcpy(ssid.ssid, pssid, ssid.ssid_len);
ssid_p = &ssid;
}
ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, wpas_neighbor_rep_cb, wpa_s);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_send_btm_query(const struct netif *dev, int query_reason)
{
struct wpa_supplicant *wpa_s;
int ret;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ret = wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, NULL, 0);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_mbo_update_non_pref_chan(const struct netif *dev, const char *non_pref_chan)
{
struct wpa_supplicant *wpa_s;
int ret;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ret = wpas_mbo_update_non_pref_chan(wpa_s, non_pref_chan);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_mbo_set_cell_capa(const struct netif *dev, unsigned char mbo_cell_capa)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpas_mbo_update_cell_capa(wpa_s, mbo_cell_capa);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_mbo_set_oce(const struct netif *dev, unsigned char oce)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_s->conf->oce = oce;
if (wpa_s->conf->oce)
{
if ((wpa_s->conf->oce & OCE_STA) && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
wpa_s->enable_oce = OCE_STA;
if ((wpa_s->conf->oce & OCE_STA_CFON) && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON))
{
/* TODO: Need to add STA-CFON support */
wpa_printf(MSG_DEBUG, "OCE STA-CFON feature is not yet supported");
ret = -1;
}
}
else
{
wpa_s->enable_oce = 0;
}
wpa_supplicant_set_default_scan_ies(wpa_s);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#ifdef CONFIG_11R
int wpa_supp_ft_ds(const struct netif *dev, unsigned char *bssid)
{
struct wpa_supplicant *wpa_s;
struct wpa_bss *bss;
const u8 *mdie;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
bss = wpa_bss_get_bssid(wpa_s, bssid);
if (bss)
mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
else
mdie = NULL;
ret = wpa_ft_start_over_ds(wpa_s->wpa, bssid, mdie);
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = FT_DS;
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#endif /* CONFIG_11R */
int wpa_supp_notify_assoc(const struct netif *dev)
{
struct wpa_supplicant *wpa_s;
struct wpa_bss *bss;
const u8 *mdie;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
wpa_sm_notify_assoc(wpa_s->wpa, wpa_s->current_bss->bssid);
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#ifdef CONFIG_HOSTAPD
int wpa_supp_get_sta_info(const struct netif *dev, unsigned char *sta_addr, unsigned char *is_11n_enabled)
{
// struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
struct sta_info *sta;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
sta = ap_get_sta(hapd, sta_addr);
if (!sta)
{
ret = -1;
goto out;
}
if (sta->flags & WLAN_STA_HT)
{
*is_11n_enabled = 1;
}
else
{
*is_11n_enabled = 0;
}
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#endif
#ifdef CONFIG_WPA_SUPP_WPS
int wpa_supp_start_wps_pbc(const struct netif *dev, int is_ap)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_wps_button_pushed(hapd, NULL);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = wpa_supplicant_ap_wps_pbc(wpa_s, NULL, NULL);
goto out;
}
#endif /* CONFIG_AP */
ret = wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = WPS_PBC;
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_start_wps_pin(const struct netif *dev, const char *pin, int is_ap)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_wps_add_pin(hapd, NULL, "any", pin, 0);
if (ret != 0)
{
ret = -1;
goto out;
}
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = wpa_supplicant_ap_wps_pin(wpa_s, NULL, pin, NULL, 0, 0);
goto out;
}
#endif /* CONFIG_AP */
if (pin)
{
ret = wpas_wps_start_pin(wpa_s, NULL, pin, 0, DEV_PW_DEFAULT);
goto out;
}
ret = wpas_wps_start_pin(wpa_s, NULL, NULL, 0, DEV_PW_DEFAULT);
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = WPS_PIN;
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_wps_pin_valid(const struct netif *dev, const unsigned char *tpin)
{
(void)dev;
char pin[9];
size_t len;
char *pos;
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", (u8 *)tpin, os_strlen((const char *)tpin));
for (pos = (char *)tpin, len = 0; *pos != '\0'; pos++)
{
if (*pos < '0' || *pos > '9')
continue;
pin[len++] = *pos;
if (len == 9)
{
wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
return -1;
}
}
if (len != 4 && len != 8)
{
wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int)len);
return -1;
}
pin[len] = '\0';
if (len == 8)
{
unsigned int pin_val;
pin_val = atoi(pin);
if (!wps_pin_valid(pin_val))
{
wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
return -1;
}
}
return 0;
}
int wpa_supp_wps_generate_pin(const struct netif *dev, unsigned int *pin)
{
(void)dev;
return wps_generate_pin(pin);
}
int wpa_supp_cancel_wps(const struct netif *dev, int is_ap)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_wps_cancel(hapd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
ret = wpas_wps_cancel(wpa_s);
wpa_supp_api_ctrl.dev = dev;
wpa_supp_api_ctrl.requested_op = WPS_CANCEL;
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#endif
#ifdef CONFIG_DPP
int wpa_supp_dpp_bootstrap_gen(const struct netif *dev, int is_ap, const char *buf)
{
struct wpa_supplicant *wpa_s;
int id = -1;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
goto out;
}
hapd = hapd_s->bss[0];
id = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf);
if (id < 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to generate bootstrap\n", __func__);
}
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
goto out;
}
#endif /* CONFIG_AP */
id = dpp_bootstrap_gen(wpa_s->dpp, buf);
if (id < 0)
{
wpa_printf(MSG_DEBUG, "%s:Failed to generate bootstrap\n", __func__);
}
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return id;
}
const char *wpa_supp_dpp_bootstrap_get_uri(const struct netif *dev, int is_ap, unsigned int id)
{
struct wpa_supplicant *wpa_s;
const char *uri = NULL;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
goto out;
}
hapd = hapd_s->bss[0];
uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp, id);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
goto out;
}
#endif /* CONFIG_AP */
uri = dpp_bootstrap_get_uri(wpa_s->dpp, id);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return uri;
}
int wpa_supp_dpp_listen(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_dpp_listen(hapd, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
wpa_s->conf->dpp_config_processing = 2;
ret = wpas_dpp_listen(wpa_s, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_stop_listen(const struct netif *dev, int is_ap)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
hostapd_dpp_listen_stop(hapd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
wpas_dpp_listen_stop(wpa_s);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_configurator_add(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = dpp_configurator_add(hapd->iface->interfaces->dpp, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
ret = dpp_configurator_add(wpa_s->dpp, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
void wpa_supp_dpp_configurator_params(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
goto out;
}
hapd = hapd_s->bss[0];
os_free(hapd->dpp_configurator_params);
hapd->dpp_configurator_params = os_strdup(cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
goto out;
}
#endif /* CONFIG_AP */
os_free(wpa_s->dpp_configurator_params);
wpa_s->dpp_configurator_params = os_strdup(cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
}
void wpa_supp_dpp_mud_url(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s || !hapd_s->conf)
{
goto out;
}
hapd = hapd_s->bss[0];
os_free(hapd->conf->dpp_mud_url);
hapd->conf->dpp_mud_url = os_strdup(cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s || !wpa_s->conf)
{
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
goto out;
}
#endif /* CONFIG_AP */
os_free(wpa_s->conf->dpp_mud_url);
wpa_s->conf->dpp_mud_url = os_strdup(cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
}
int wpa_supp_dpp_configurator_get_key(const struct netif *dev, int is_ap, unsigned int id, char *buf, size_t buflen)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = dpp_configurator_get_key_id(hapd->iface->interfaces->dpp, id, buf, buflen);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
ret = dpp_configurator_get_key_id(wpa_s->dpp, id, buf, buflen);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_qr_code(const struct netif *dev, int is_ap, char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_dpp_qr_code(hapd, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
ret = wpas_dpp_qr_code(wpa_s, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_auth_init(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
hapd->dpp_resp_wait_time = 5000;
ret = hostapd_dpp_auth_init(hapd, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
wpa_s->dpp_resp_wait_time = 5000;
wpa_s->conf->dpp_config_processing = 2;
ret = wpas_dpp_auth_init(wpa_s, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_pkex_add(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
hapd->dpp_resp_wait_time = 5000;
ret = hostapd_dpp_pkex_add(hapd, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
wpa_s->dpp_resp_wait_time = 5000;
wpa_s->conf->dpp_config_processing = 2;
ret = wpas_dpp_pkex_add(wpa_s, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_chirp(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
hapd->dpp_resp_wait_time = 5000;
#ifdef CONFIG_DPP2
ret = hostapd_dpp_chirp(hapd, cmd);
#endif
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
wpa_s->dpp_resp_wait_time = 5000;
wpa_s->conf->dpp_config_processing = 2;
#ifdef CONFIG_DPP2
ret = wpas_dpp_chirp(wpa_s, cmd);
#endif
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_reconfig(const struct netif *dev, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_DPP2
ret = wpas_dpp_reconfig(wpa_s, cmd);
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
int wpa_supp_dpp_configurator_sign(const struct netif *dev, int is_ap, const char *cmd)
{
struct wpa_supplicant *wpa_s;
int ret = 0;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (is_ap)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
hapd = hapd_s->bss[0];
ret = hostapd_dpp_configurator_sign(hapd, cmd);
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
ret = -1;
goto out;
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
{
ret = -1;
goto out;
}
#endif /* CONFIG_AP */
ret = wpas_dpp_configurator_sign(wpa_s, cmd);
#ifdef CONFIG_HOSTAPD
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
#endif /* CONFIG_DPP */
static inline enum wlan_security_type wpas_key_mgmt_to_wpa(int key_mgmt)
{
switch (key_mgmt)
{
case WPA_KEY_MGMT_NONE:
return WLAN_SECURITY_NONE;
case WPA_KEY_MGMT_PSK:
case WPA_KEY_MGMT_PSK_SHA256:
return WLAN_SECURITY_WPA2;
#ifdef CONFIG_OWE
case WPA_KEY_MGMT_OWE:
return WLAN_SECURITY_OWE_ONLY;
#endif
case WPA_KEY_MGMT_SAE:
return WLAN_SECURITY_WPA3_SAE;
default:
return WLAN_SECURITY_WILDCARD;
}
}
int wpa_supp_status(const struct netif *dev)
{
int status = 0;
struct wpa_supplicant *wpa_s;
struct wpa_supp_api_ctrl *ctrl = &wpa_supp_api_ctrl;
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
status = -1;
goto out;
}
ctrl->supp_thread_state = SUPP_THREAD_RUNNING;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
status = -1;
goto out;
}
#endif
out:
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return status;
}
int wpa_supp_network_status(const struct netif *dev, struct wlan_network *network)
{
struct wpa_supplicant *wpa_s;
int ret = -1;
struct wpa_signal_info *si = NULL;
#ifdef CONFIG_HOSTAPD
struct hostapd_iface *hapd_s;
#endif
OSA_MutexLock((osa_mutex_handle_t)wpa_supplicant_mutex, osaWaitForever_c);
#ifdef CONFIG_HOSTAPD
if (network->role == WLAN_BSS_ROLE_UAP)
{
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
ret = -1;
goto out;
}
}
else
{
#endif
wpa_s = get_wpa_s_handle(dev);
if (!wpa_s)
{
goto out;
}
si = os_zalloc(sizeof(struct wpa_signal_info));
if (!si)
{
goto out;
}
if (wpa_s->wpa_state >= WPA_ASSOCIATED)
{
struct wpa_ssid *ssid = wpa_s->current_ssid;
u8 channel;
os_memcpy(network->bssid, wpa_s->bssid, ETH_ALEN);
if (ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
{
network->security.mfpc = 1;
network->security.mfpr = 1;
}
else if (ssid->ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL)
{
network->security.mfpc = 1;
}
ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel);
network->channel = channel;
if (ssid)
{
u8 *_ssid = ssid->ssid;
size_t ssid_len = ssid->ssid_len;
u8 ssid_buf[SSID_MAX_LEN] = {0};
if (ssid_len == 0)
{
int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
if (_res < 0)
ssid_len = 0;
else
ssid_len = _res;
_ssid = ssid_buf;
}
os_memcpy(network->ssid, _ssid, ssid_len);
if (os_strstr(network->name, "wps_network"))
{
os_memset(network->name, 0x00, sizeof(network->name));
os_memcpy(network->name, _ssid, ssid_len);
network->id = ssid->id;
network->wps_network = true;
network->security.type = wpas_key_mgmt_to_wpa(ssid->key_mgmt);
if (ssid->export_keys)
{
if (ssid->psk_set)
{
network->security.pmk_valid = true;
os_memcpy(network->security.pmk, ssid->psk, PMK_LEN);
}
else if (network->security.type == WLAN_SECURITY_WPA3_SAE)
{
network->security.password_len = os_strlen(ssid->passphrase);
os_memcpy(network->security.password, ssid->passphrase, network->security.password_len);
}
else
{
network->security.psk_len = os_strlen(ssid->passphrase);
os_memcpy(network->security.psk, ssid->passphrase, network->security.psk_len);
}
}
}
}
network->beacon_period = wpa_s->current_bss->beacon_int;
ret = wpa_drv_signal_poll(wpa_s, si);
if (!ret)
{
network->rssi = si->current_signal;
}
else
{
network->rssi = -WPA_INVALID_NOISE;
}
network->dot11n = wpa_s->connection_ht;
#ifdef CONFIG_11AC
network->dot11ac = wpa_s->connection_vht;
#endif
#ifdef CONFIG_11AX
network->dot11ax = wpa_s->connection_he;
#endif
#ifdef CONFIG_11K
network->neighbor_report_supported = wpa_s->rrm.rrm_used == 1 ? true : false;
#endif
#ifdef CONFIG_11V
if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_BSS_TRANSITION))
{
network->bss_transition_supported = true;
}
else
{
network->bss_transition_supported = false;
}
#endif
}
else
{
ret = 0;
}
#ifdef CONFIG_HOSTAPD
}
#endif
out:
os_free(si);
OSA_MutexUnlock((osa_mutex_handle_t)wpa_supplicant_mutex);
return ret;
}
static int wpa_supp_add_acl_maclist(struct mac_acl_entry **acl, int *num, int vlan_id, const u8 *addr)
{
struct mac_acl_entry *newacl;
newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
if (!newacl)
{
wpa_printf(MSG_ERROR, "MAC list reallocation failed");
return -1;
}
*acl = newacl;
os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id));
(*acl)[*num].vlan_id.untagged = vlan_id;
(*acl)[*num].vlan_id.notempty = !!vlan_id;
(*num)++;
return 0;
}
int wpa_supp_set_mac_acl(const struct netif *dev, int filter_mode, char mac_count, unsigned char *mac_addr)
{
struct hostapd_iface *hapd_s;
struct hostapd_data *hapd;
struct hostapd_bss_config *bss;
hapd_s = get_hostapd_handle(dev);
if (!hapd_s)
{
return -1;
}
hapd = hapd_s->bss[0];
bss = hapd->conf;
switch(filter_mode)
{
case 0:
bss->macaddr_acl = 0;
if (bss->accept_mac)
os_free(bss->accept_mac);
bss->accept_mac = NULL;
bss->num_accept_mac = 0;
if (bss->deny_mac)
os_free(bss->deny_mac);
bss->deny_mac = NULL;
bss->num_deny_mac = 0;
break;
case 1:
for (int num = 0; num < mac_count;)
{
if (wpa_supp_add_acl_maclist(&bss->accept_mac, &num, 0, &mac_addr[num*WLAN_MAC_ADDR_LENGTH]) < 0)
{
wpa_printf(MSG_ERROR, "Line %d: add accept_mac fail", __LINE__);
return -1;
}
}
bss->num_accept_mac = mac_count;
bss->macaddr_acl = 1;
break;
case 2:
for (int num = 0; num < mac_count;)
{
if (wpa_supp_add_acl_maclist(&bss->deny_mac, &num, 0, &mac_addr[num*WLAN_MAC_ADDR_LENGTH]) < 0)
{
wpa_printf(MSG_ERROR, "Line %d: add deny_mac fail", __LINE__);
return -1;
}
}
bss->num_deny_mac = mac_count;
bss->macaddr_acl = 0;
break;
default:
return -1;
}
return 0;
}
static void (*msg_cb_ptr)(const char *txt, size_t len);
static void wpa_supplicant_msg_cb(void *ctx, int level, enum wpa_msg_type type, const char *txt, size_t len)
{
msg_cb_ptr(txt, len);
}
int wpa_supp_init(void (*msg_cb)(const char *txt, size_t len))
{
osa_status_t status;
status = OSA_MutexCreate((osa_mutex_handle_t)wpa_supplicant_mutex);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to initialize wpa supp mutex");
return -1;
}
status = OSA_SemaphoreCreateBinary((osa_semaphore_handle_t)wpaSuppReadySemaphoreHandle);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to initialize wpa supp ready semaphore");
return -1;
}
msg_cb_ptr = msg_cb;
wpa_msg_register_cb(wpa_supplicant_msg_cb);
#ifdef CONFIG_HOSTAPD
status = OSA_SemaphoreCreateBinary((osa_semaphore_handle_t)hostapdReadySemaphoreHandle);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to initialize wpa hostapd ready semaphore");
return -1;
}
#endif
return 0;
}
int wpa_supp_deinit(void)
{
osa_status_t status;
status = OSA_MutexDestroy((osa_mutex_handle_t)wpa_supplicant_mutex);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to destroy wpa supp mutex");
return -1;
}
status = OSA_SemaphoreDestroy((osa_semaphore_handle_t)wpaSuppReadySemaphoreHandle);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to destroy wpa supp ready semaphore");
return -1;
}
#ifdef CONFIG_HOSTAPD
status = OSA_SemaphoreDestroy((osa_semaphore_handle_t)hostapdReadySemaphoreHandle);
if (status != KOSA_StatusSuccess)
{
wpa_printf(MSG_DEBUG, "Failed to destroy wpa hostapd ready semaphore");
return -1;
}
#endif
return 0;
}