From e24005c8dbb3eea9d6469ca8aebbcee34c1abf8a Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Fri, 20 Sep 2024 14:46:05 +0800 Subject: [PATCH] fix(esp_wifi): Add support for 5ghz channel list for easy connect --- components/esp_common/src/esp_err_to_name.c | 5 + .../esp_supplicant/include/esp_dpp.h | 4 + .../esp_supplicant/src/esp_dpp.c | 106 ++++++++++++------ .../src/common/ieee802_11_common.c | 56 +++++++-- 4 files changed, 130 insertions(+), 41 deletions(-) diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index c344dd519a..3fe660c929 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -469,6 +469,11 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_DPP_AUTH_TIMEOUT ERR_TBL_IT(ESP_ERR_DPP_AUTH_TIMEOUT), /* 12442 0x309a DPP Auth response was not received in time */ +# endif +# ifdef ESP_ERR_DPP_INVALID_LIST + ERR_TBL_IT(ESP_ERR_DPP_INVALID_LIST), /* 12443 0x309b Channel list given in + esp_supp_dpp_bootstrap_gen() is not + valid or too big */ # endif // components/esp_common/include/esp_err.h # ifdef ESP_ERR_MESH_BASE diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h index 2b07a54281..ec38d3c70f 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h @@ -17,11 +17,14 @@ extern "C" { #endif #define ESP_DPP_AUTH_TIMEOUT_SECS 1 +#define ESP_DPP_MAX_CHAN_COUNT 5 #define ESP_ERR_DPP_FAILURE (ESP_ERR_WIFI_BASE + 151) /*!< Generic failure during DPP Operation */ #define ESP_ERR_DPP_TX_FAILURE (ESP_ERR_WIFI_BASE + 152) /*!< DPP Frame Tx failed OR not Acked */ #define ESP_ERR_DPP_INVALID_ATTR (ESP_ERR_WIFI_BASE + 153) /*!< Encountered invalid DPP Attribute */ #define ESP_ERR_DPP_AUTH_TIMEOUT (ESP_ERR_WIFI_BASE + 154) /*!< DPP Auth response was not received in time */ +#define ESP_ERR_DPP_INVALID_LIST (ESP_ERR_WIFI_BASE + 155) /*!< Channel list given in esp_supp_dpp_bootstrap_gen() is not valid or too big */ + /** @brief Types of Bootstrap Methods for DPP. */ typedef enum dpp_bootstrap_type { DPP_BOOTSTRAP_QR_CODE, /**< QR Code Method */ @@ -83,6 +86,7 @@ esp_err_t esp_supp_dpp_deinit(void); * * @return * - ESP_OK: Success + * - ESP_ERR_DPP_INVALID_LIST: Channel list not valid * - ESP_FAIL: Failure */ esp_err_t diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c index 99a55d11ab..0bb8c6b166 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c @@ -15,6 +15,7 @@ #include "esp_event.h" #include "esp_wifi.h" #include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" #include "esp_wps_i.h" #include "rsn_supp/wpa.h" #include "rsn_supp/pmksa_cache.h" @@ -575,6 +576,7 @@ static void esp_dpp_task(void *pvParameters) break; } channel = p->chan_list[counter++ % p->num_chan]; + wpa_printf(MSG_DEBUG, "Listening on channel=%d", channel); ret = esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, channel, BOOTSTRAP_ROC_WAIT_TIME, s_action_rx_cb); if (ret != ESP_OK) { @@ -687,47 +689,81 @@ static void offchan_event_handler(void *arg, esp_event_base_t event_base, static char *esp_dpp_parse_chan_list(const char *chan_list) { struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; - char *uri_channels = os_zalloc(14 * 6 + 1); - const char *pos = chan_list; - const char *pos2; - char *pos3 = uri_channels; + size_t max_uri_len = ESP_DPP_MAX_CHAN_COUNT * 8 + strlen(" chan=") + 1; + + char *uri_channels = os_zalloc(max_uri_len); + if (!uri_channels) { + wpa_printf(MSG_WARNING, "DPP: URI allocation failed"); + return NULL; + } + + char *uri_ptr = uri_channels; params->num_chan = 0; - os_memcpy(pos3, " chan=", strlen(" chan=")); - pos3 += strlen(" chan="); + /* Append " chan=" at the beginning of the URI */ + strcpy(uri_ptr, " chan="); + uri_ptr += strlen(" chan="); - while (pos && *pos) { - int channel; - int len = strlen(chan_list); + while (*chan_list && params->num_chan < ESP_DPP_MAX_CHAN_COUNT) { + int channel = 0; - pos2 = pos; - while (*pos2 >= '0' && *pos2 <= '9') { - pos2++; + /* Parse the channel number */ + while (*chan_list >= '0' && *chan_list <= '9') { + channel = channel * 10 + (*chan_list - '0'); + chan_list++; } - if (*pos2 == ',' || *pos2 == ' ' || *pos2 == '\0') { - channel = atoi(pos); - if (channel < 1 || channel > 14) { - os_free(uri_channels); - return NULL; + + /* Validate the channel number */ + if (CHANNEL_TO_BIT_NUMBER(channel) == 0) { + wpa_printf(MSG_WARNING, "DPP: Skipping invalid channel %d", channel); + /* Skip to the next valid entry */ + while (*chan_list == ',' || *chan_list == ' ') { + chan_list++; } - params->chan_list[params->num_chan++] = channel; - os_memcpy(pos3, "81/", strlen("81/")); - pos3 += strlen("81/"); - os_memcpy(pos3, pos, (pos2 - pos)); - pos3 += (pos2 - pos); - *pos3++ = ','; - - pos = pos2 + 1; - } - while (*pos == ',' || *pos == ' ' || *pos == '\0') { - pos++; + continue; // Skip the bad channel and move to the next one } - if (((int)(pos - chan_list) >= len)) { - break; + /* Get the operating class for the channel */ + u8 oper_class = get_operating_class(channel, 0); + if (oper_class == 0) { + wpa_printf(MSG_WARNING, "DPP: Skipping channel %d due to missing operating class", channel); + /* Skip to the next valid entry */ + while (*chan_list == ',' || *chan_list == ' ') { + chan_list++; + } + continue; /* Skip to the next channel if no operating class found */ + } + + /* Add the valid channel to the list */ + params->chan_list[params->num_chan++] = channel; + + /* Check if there's space left in uri_channels buffer */ + size_t remaining_space = max_uri_len - (uri_ptr - uri_channels); + if (remaining_space <= 8) { // Oper class + "/" + channel + "," + null terminator + wpa_printf(MSG_ERROR, "DPP: Not enough space in URI buffer"); + os_free(uri_channels); + return NULL; + } + + /* Append the operating class and channel to the URI */ + uri_ptr += sprintf(uri_ptr, "%d/%d,", oper_class, channel); + + /* Skip any delimiters (comma or space) */ + while (*chan_list == ',' || *chan_list == ' ') { + chan_list++; } } - *(pos3 - 1) = ' '; + + if (!params->num_chan) { + wpa_printf(MSG_ERROR, "DPP: No valid channel in the list"); + os_free(uri_channels); + return NULL; + } + + /* Replace the last comma with a space if there was content added */ + if (uri_ptr > uri_channels && *(uri_ptr - 1) == ',') { + *(uri_ptr - 1) = ' '; + } return uri_channels; } @@ -742,10 +778,16 @@ esp_supp_dpp_bootstrap_gen(const char *chan_list, enum dpp_bootstrap_type type, } struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; char *uri_chan_list = esp_dpp_parse_chan_list(chan_list); + + if (params->num_chan > ESP_DPP_MAX_CHAN_COUNT) { + os_free(uri_chan_list); + return ESP_ERR_DPP_INVALID_LIST; + } + char *command = os_zalloc(1200); int ret; - if (!uri_chan_list || !command || params->num_chan >= 14 || params->num_chan == 0) { + if (!uri_chan_list || !command || params->num_chan > ESP_DPP_MAX_CHAN_COUNT || params->num_chan == 0) { wpa_printf(MSG_ERROR, "Invalid Channel list - %s", chan_list); if (command) { os_free(command); diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 61a753f442..1c24c1972b 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -357,16 +357,54 @@ int ieee802_11_ext_capab(const u8 *ie, unsigned int capab) u8 get_operating_class(u8 chan, int sec_channel) { - u8 op_class; + u8 op_class = 0; - if (chan < 1 || chan > 14) - return 0; - if (sec_channel == 1) - op_class = 83; - else if (sec_channel == -1) - op_class = 84; - else - op_class = 81; + if (chan >= 1 && chan < 14) { + if (sec_channel == 1) + op_class = 83; + else if (sec_channel == -1) + op_class = 84; + else + op_class = 81; + } + + if (chan == 14) + op_class = 82; + +#if SOC_WIFI_SUPPORT_5G + if (chan >= 36 && chan <= 48) { + if (sec_channel == 1) + op_class = 116; + else if (sec_channel == -1) + op_class = 117; + else + op_class = 115; + } + if (chan >= 52 && chan <= 64) { + if (sec_channel == 1) + op_class = 119; + else if (sec_channel == -1) + op_class = 120; + else + op_class = 118; + } + if (chan >= 149 && chan <= 177) { + if (sec_channel == 1) + op_class = 126; + else if (sec_channel == -1) + op_class = 127; + else + op_class = 125; + } + if (chan >= 100 && chan <= 144) { + if (sec_channel == 1) + op_class = 122; + else if (sec_channel == -1) + op_class = 123; + else + op_class = 121; + } +#endif return op_class; }