Skip to content

Commit

Permalink
Merge branch 'feature/wps_registrar_example' into 'master'
Browse files Browse the repository at this point in the history
WiFi: Add softAP WPS registrar example and events

See merge request espressif/esp-idf!18450
  • Loading branch information
jack0c committed Dec 5, 2022
2 parents 12180da + 7f3b18d commit f27a95c
Show file tree
Hide file tree
Showing 30 changed files with 470 additions and 149 deletions.
29 changes: 29 additions & 0 deletions components/esp_wifi/include/esp_wifi_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,12 @@ typedef enum {

WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START, /**< ESP32 connectionless module wake interval start */

WIFI_EVENT_AP_WPS_RG_SUCCESS, /**< Soft-AP wps succeeds in registrar mode */
WIFI_EVENT_AP_WPS_RG_FAILED, /**< Soft-AP wps fails in registrar mode */
WIFI_EVENT_AP_WPS_RG_TIMEOUT, /**< Soft-AP wps timeout in registrar mode */
WIFI_EVENT_AP_WPS_RG_PIN, /**< Soft-AP wps pin code in registrar mode */
WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP, /**< Soft-AP wps overlap in registrar mode */

WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
} wifi_event_t;

Expand Down Expand Up @@ -789,6 +795,29 @@ typedef struct {
uint32_t context; /**< Context to identify the request */
} wifi_event_roc_done_t;

/** Argument structure for WIFI_EVENT_AP_WPS_RG_PIN event */
typedef struct {
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
} wifi_event_ap_wps_rg_pin_t;

typedef enum {
WPS_AP_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */
WPS_AP_FAIL_REASON_CONFIG, /**< WPS failed due to incorrect config */
WPS_AP_FAIL_REASON_AUTH, /**< WPS failed during auth */
WPS_AP_FAIL_REASON_MAX,
} wps_fail_reason_t;

/** Argument structure for WIFI_EVENT_AP_WPS_RG_FAILED event */
typedef struct {
wps_fail_reason_t reason; /**< WPS failure reason wps_fail_reason_t */
uint8_t peer_macaddr[6]; /**< Enrollee mac address */
} wifi_event_ap_wps_rg_fail_reason_t;

/** Argument structure for WIFI_EVENT_AP_WPS_RG_SUCCESS event */
typedef struct {
uint8_t peer_macaddr[6]; /**< Enrollee mac address */
} wifi_event_ap_wps_rg_success_t;

#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 5 additions & 1 deletion components/wpa_supplicant/esp_supplicant/include/esp_wps.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ esp_err_t esp_wifi_wps_start(int timeout_ms);
*
* @attention WPS can only be used when softAP is enabled.
*
* @param wps_type_t wps_type : WPS type, so far only WPS_TYPE_PBC and WPS_TYPE_PIN is supported
* @param esp_wps_config_t config: wps configuration to be used.
*
* @return
* - ESP_OK : succeed
Expand All @@ -145,6 +145,10 @@ esp_err_t esp_wifi_ap_wps_disable(void);
*
* @attention WPS can only be used when softAP is enabled.
*
* @param pin : Pin to be used in case of WPS mode is pin.
* If Pin is not provided, device will use the pin generated/provided
* during esp_wifi_ap_wps_enable() and reported in WIFI_EVENT_AP_WPS_RG_PIN
*
* @return
* - ESP_OK : succeed
* - ESP_ERR_WIFI_WPS_TYPE : wps type is invalid
Expand Down
33 changes: 25 additions & 8 deletions components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extern void *s_wps_api_lock;
extern void *s_wps_api_sem;
extern bool s_wps_enabled;

static int wifi_ap_wps_init(void)
static int wifi_ap_wps_init(const esp_wps_config_t *config)
{
struct wps_sm *sm = NULL;
uint8_t mac[ETH_ALEN];
Expand Down Expand Up @@ -69,13 +69,22 @@ static int wifi_ap_wps_init(void)
cfg.registrar = 1;
cfg.wps = sm->wps_ctx;

os_memcpy((void *)cfg.pin, config->pin, 8);
wps_init_cfg_pin(&cfg);
os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
if ((sm->wps = wps_init(&cfg)) == NULL) { /* alloc wps_data */
goto _err;
}

hostapd_init_wps(hostapd_get_hapd_data(), sm->wps, sm->wps_ctx);

/* Report PIN */
if (wps_get_type() == WPS_TYPE_PIN) {
wifi_event_sta_wps_er_pin_t evt;
os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PIN, &evt, sizeof(evt), OS_BLOCK);
}

return ESP_OK;

_err:
Expand All @@ -102,23 +111,26 @@ int wifi_ap_wps_deinit(void)
{
struct wps_sm *sm = gWpsSm;

hostapd_deinit_wps(hostapd_get_hapd_data());
if (gWpsSm == NULL) {
return ESP_FAIL;
}

hostapd_deinit_wps(hostapd_get_hapd_data());
if (sm->wps) {
sm->wps->registrar = 0;
wps_deinit(sm->wps);
sm->wps = NULL;
}
if (sm->dev) {
wps_dev_deinit(sm->dev);
sm->dev = NULL;
}

if (sm->wps_ctx) {
os_free(sm->wps_ctx);
sm->wps_ctx = NULL;
}
if (sm->wps) {
wps_deinit(sm->wps);
sm->wps = NULL;
}

os_free(gWpsSm);
gWpsSm = NULL;

Expand Down Expand Up @@ -146,7 +158,7 @@ int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
wps_set_type(config->wps_type);
wps_set_status(WPS_STATUS_DISABLE);

ret = wifi_ap_wps_init();
ret = wifi_ap_wps_init(config);

if (ret != 0) {
wps_set_type(WPS_STATUS_DISABLE);
Expand Down Expand Up @@ -199,8 +211,8 @@ int esp_wifi_ap_wps_disable(void)
}

wpa_printf(MSG_INFO, "wifi_wps_disable");
wps_set_status(WPS_STATUS_DISABLE);
wps_set_type(WPS_TYPE_DISABLE);
wps_set_status(WPS_STATUS_DISABLE);

wifi_ap_wps_deinit();

Expand Down Expand Up @@ -232,15 +244,20 @@ int esp_wifi_ap_wps_start(const unsigned char *pin)
}

if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d", wps_get_type(), wps_get_status());
API_MUTEX_GIVE();
return ESP_ERR_WIFI_WPS_TYPE;
}

if (esp_wifi_get_user_init_flag_internal() == 0) {
wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d", esp_wifi_get_user_init_flag_internal());
API_MUTEX_GIVE();
return ESP_ERR_WIFI_STATE;
}

if (!pin) {
pin = gWpsSm->wps->dev_password;
}
/* TODO ideally SoftAP mode should also do a single scan in PBC mode
* however softAP scanning is not available at the moment */
wps_set_status(WPS_STATUS_PENDING);
Expand Down
28 changes: 8 additions & 20 deletions components/wpa_supplicant/esp_supplicant/src/esp_wps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1188,22 +1188,7 @@ int wps_dev_deinit(struct wps_device_data *dev)
if (!dev) {
return ESP_FAIL;
}

if (dev->manufacturer) {
os_free(dev->manufacturer);
}
if (dev->model_name) {
os_free(dev->model_name);
}
if (dev->model_number) {
os_free(dev->model_number);
}
if (dev->device_name) {
os_free(dev->device_name);
}
if (dev->serial_number) {
os_free(dev->serial_number);
}
wps_device_data_free(dev);

if (s_factory_info) {
os_free(s_factory_info);
Expand Down Expand Up @@ -1358,21 +1343,23 @@ int wps_init_cfg_pin(struct wps_config *cfg)
}

cfg->pbc = 0;
if (os_strncmp((char *)cfg->pin, "00000000", 8) != 0) {

if ((os_strncmp((char *)cfg->pin, "00000000", 8) == 0) || !wps_pin_str_valid((char *)cfg->pin)) {
unsigned int spin = 0;

cfg->dev_pw_id = DEV_PW_DEFAULT;
cfg->pin_len = 8;
if (wps_generate_pin(&spin) < 0) {
return -1;
}
wpa_printf(MSG_INFO, "Provided PIN %s is not valid, generated a new PIN %08d", (char *)cfg->pin, spin);
os_snprintf((char *)cfg->pin, 9, "%08d", spin);
}

return 0;
}

int
wifi_station_wps_init(void)
static int wifi_station_wps_init(const esp_wps_config_t *config)
{
struct wps_funcs *wps_cb;
struct wps_sm *sm = NULL;
Expand Down Expand Up @@ -1408,6 +1395,7 @@ wifi_station_wps_init(void)

cfg.wps = sm->wps_ctx;

os_memcpy((void *)cfg.pin, config->pin, 8);
if (wps_init_cfg_pin(&cfg) < 0) {
goto _err;
}
Expand Down Expand Up @@ -1858,7 +1846,7 @@ int wifi_wps_enable_internal(const esp_wps_config_t *config)
wps_set_type(config->wps_type);
wps_set_status(WPS_STATUS_DISABLE);

ret = wifi_station_wps_init();
ret = wifi_station_wps_init(config);

if (ret != 0) {
wps_set_type(WPS_STATUS_DISABLE);
Expand Down
14 changes: 11 additions & 3 deletions components/wpa_supplicant/src/ap/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "wpa_auth.h"
#include "ap_config.h"
#include "sta_info.h"
#include "esp_wps_i.h"

static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
Expand Down Expand Up @@ -167,7 +168,6 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)

static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
u16 reason;

Expand All @@ -177,14 +177,21 @@ static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)

reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
esp_wifi_ap_deauth_internal(sta->addr, reason);
if (sta->flags & WLAN_STA_WPS)
hostapd_wps_eap_completed(hapd);
}


void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta)
{
#ifdef ESP_SUPPLICANT
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Scheduled disconnection of " MACSTR
" after EAP-Failure", MAC2STR(sta->addr));

esp_wifi_ap_deauth_internal(sta->addr, WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
if (wps_get_status() == WPS_STATUS_PENDING)
wps_set_status(WPS_STATUS_DISABLE);
#else
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Force disconnection of " MACSTR
" after EAP-Failure in 10 ms", MAC2STR(sta->addr));
Expand All @@ -197,6 +204,7 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
hapd, sta);
#endif
}


Expand Down
30 changes: 30 additions & 0 deletions components/wpa_supplicant/src/ap/wpa_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "esp_wifi.h"
#include "esp_private/wifi.h"
#include "esp_wpas_glue.h"
#include "esp_wps_i.h"

#define STATE_MACHINE_DATA struct wpa_state_machine
#define STATE_MACHINE_DEBUG_PREFIX "WPA"
Expand Down Expand Up @@ -2375,13 +2376,42 @@ bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, uint8_t
return true;
}

#ifdef CONFIG_WPS_REGISTRAR
static void ap_free_sta_timeout(void *ctx, void *data)
{
struct hostapd_data *hapd = (struct hostapd_data *) ctx;
u8 *addr = (u8 *) data;
struct sta_info *sta = ap_get_sta(hapd, addr);

if (sta) {
ap_free_sta(hapd, sta);
}

os_free(addr);
}
#endif

bool wpa_ap_remove(void* sta_info)
{
struct hostapd_data *hapd = hostapd_get_hapd_data();

if (!sta_info || !hapd) {
return false;
}

#ifdef CONFIG_WPS_REGISTRAR
wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status());
if (wps_get_status() == WPS_STATUS_PENDING) {
struct sta_info *sta = (struct sta_info *)sta_info;
u8 *addr = os_malloc(ETH_ALEN);

if (!addr) {
return false;
}
os_memcpy(addr, sta->addr, ETH_ALEN);
eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr);
} else
#endif
ap_free_sta(hapd, sta_info);

return true;
Expand Down
Loading

0 comments on commit f27a95c

Please sign in to comment.