mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-30 06:59:02 +08:00
feat(wifi): add 11kv roaming support
This commit is contained in:
@ -992,6 +992,33 @@ esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, b
|
|||||||
*/
|
*/
|
||||||
wifi_state_t esp_wifi_get_state(void);
|
wifi_state_t esp_wifi_get_state(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set RSSI threshold below which APP will get an event
|
||||||
|
*
|
||||||
|
* @attention This API needs to be called every time after WIFI_EVENT_STA_BSS_RSSI_LOW event is received.
|
||||||
|
*
|
||||||
|
* @param rssi threshold value in dbm between -100 to 0
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: succeed
|
||||||
|
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
|
||||||
|
* - ESP_ERR_WIFI_ARG: invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t esp_wifi_set_rssi_threshold(int32_t rssi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the TSF time
|
||||||
|
* In Station mode or SoftAP+Station mode if station is not connected or station doesn't receive at least
|
||||||
|
* one beacon after connected, will return 0
|
||||||
|
*
|
||||||
|
* @attention Enabling power save may cause the return value inaccurate, except WiFi modem sleep
|
||||||
|
*
|
||||||
|
* @param interface The interface whose tsf_time is to be retrieved.
|
||||||
|
*
|
||||||
|
* @return 0 or the TSF time
|
||||||
|
*/
|
||||||
|
int64_t esp_wifi_get_tsf_time(wifi_interface_t interface);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -272,6 +272,9 @@ typedef struct {
|
|||||||
wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */
|
wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */
|
||||||
wifi_fast_scan_threshold_t threshold; /**< When scan_method is set to WIFI_FAST_SCAN, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */
|
wifi_fast_scan_threshold_t threshold; /**< When scan_method is set to WIFI_FAST_SCAN, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */
|
||||||
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */
|
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */
|
||||||
|
uint32_t rm_enabled:1; /**< Whether radio measurements are enabled for the connection */
|
||||||
|
uint32_t btm_enabled:1; /**< Whether BTM is enabled for the connection */
|
||||||
|
uint32_t reserved:30; /**< Reserved for future feature set */
|
||||||
} wifi_sta_config_t;
|
} wifi_sta_config_t;
|
||||||
|
|
||||||
/** @brief Configuration data for ESP8266 AP or STA.
|
/** @brief Configuration data for ESP8266 AP or STA.
|
||||||
@ -481,6 +484,7 @@ typedef enum {
|
|||||||
WIFI_EVENT_STA_CONNECTED, /**< station connected to AP */
|
WIFI_EVENT_STA_CONNECTED, /**< station connected to AP */
|
||||||
WIFI_EVENT_STA_DISCONNECTED, /**< station disconnected from AP */
|
WIFI_EVENT_STA_DISCONNECTED, /**< station disconnected from AP */
|
||||||
WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by station changed */
|
WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by station changed */
|
||||||
|
WIFI_EVENT_STA_BSS_RSSI_LOW, /**< AP's RSSI crossed configured threshold */
|
||||||
WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< station wps succeeds in enrollee mode */
|
WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< station wps succeeds in enrollee mode */
|
||||||
WIFI_EVENT_STA_WPS_ER_FAILED, /**< station wps fails in enrollee mode */
|
WIFI_EVENT_STA_WPS_ER_FAILED, /**< station wps fails in enrollee mode */
|
||||||
WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< station wps timeout in enrollee mode */
|
WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< station wps timeout in enrollee mode */
|
||||||
@ -556,6 +560,11 @@ typedef struct {
|
|||||||
uint8_t reason; /**< reason of disconnection */
|
uint8_t reason; /**< reason of disconnection */
|
||||||
} wifi_event_sta_disconnected_t;
|
} wifi_event_sta_disconnected_t;
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_BSS_RSSI_LOW event */
|
||||||
|
typedef struct {
|
||||||
|
int32_t rssi; /**< RSSI value of bss */
|
||||||
|
} wifi_event_bss_rssi_low_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,6 +79,7 @@ esp_err_t esp_event_send_to_default_loop(system_event_t *event)
|
|||||||
HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_TIMEOUT);
|
HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_TIMEOUT);
|
||||||
HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_FAILED, sta_er_fail_reason);
|
HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_FAILED, sta_er_fail_reason);
|
||||||
HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_PIN, sta_er_pin);
|
HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_PIN, sta_er_pin);
|
||||||
|
HANDLE_SYS_EVENT_ARG(WIFI, STA_BSS_RSSI_LOW, bss_rssi_low);
|
||||||
|
|
||||||
/* AP events */
|
/* AP events */
|
||||||
HANDLE_SYS_EVENT(WIFI, AP_START);
|
HANDLE_SYS_EVENT(WIFI, AP_START);
|
||||||
@ -250,6 +251,11 @@ static void esp_system_event_debug(const system_event_t* event)
|
|||||||
MAC2STR(ap_probereqrecved->mac));
|
MAC2STR(ap_probereqrecved->mac));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYSTEM_EVENT_STA_BSS_RSSI_LOW: {
|
||||||
|
const system_event_bss_rssi_low_t *bss_rssi_low = &event->event_info.bss_rssi_low;
|
||||||
|
ESP_LOGD(TAG, "SYSTEM_EVENT_STA_BSS_RSSI_LOW, rssi:%d", bss_rssi_low->rssi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
case SYSTEM_EVENT_GOT_IP6: {
|
case SYSTEM_EVENT_GOT_IP6: {
|
||||||
const ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip;
|
const ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip;
|
||||||
|
@ -34,6 +34,7 @@ typedef enum {
|
|||||||
SYSTEM_EVENT_STA_CONNECTED, /*!< station connected to AP */
|
SYSTEM_EVENT_STA_CONNECTED, /*!< station connected to AP */
|
||||||
SYSTEM_EVENT_STA_DISCONNECTED, /*!< station disconnected from AP */
|
SYSTEM_EVENT_STA_DISCONNECTED, /*!< station disconnected from AP */
|
||||||
SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /*!< the auth mode of AP connected by station changed */
|
SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /*!< the auth mode of AP connected by station changed */
|
||||||
|
SYSTEM_EVENT_STA_BSS_RSSI_LOW, /*!< Connected BSS rssi goes below threshold */
|
||||||
SYSTEM_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */
|
SYSTEM_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */
|
||||||
SYSTEM_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */
|
SYSTEM_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /*!< station wps succeeds in enrollee mode */
|
SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /*!< station wps succeeds in enrollee mode */
|
||||||
@ -88,6 +89,9 @@ typedef wifi_event_ap_stadisconnected_t system_event_ap_stadisconnected_t;
|
|||||||
/** Argument structure of event */
|
/** Argument structure of event */
|
||||||
typedef wifi_event_ap_probe_req_rx_t system_event_ap_probe_req_rx_t;
|
typedef wifi_event_ap_probe_req_rx_t system_event_ap_probe_req_rx_t;
|
||||||
|
|
||||||
|
/** Argument structure of event */
|
||||||
|
typedef wifi_event_bss_rssi_low_t system_event_bss_rssi_low_t;
|
||||||
|
|
||||||
/** Argument structure of event */
|
/** Argument structure of event */
|
||||||
typedef ip_event_ap_staipassigned_t system_event_ap_staipassigned_t;
|
typedef ip_event_ap_staipassigned_t system_event_ap_staipassigned_t;
|
||||||
|
|
||||||
@ -109,6 +113,7 @@ typedef union {
|
|||||||
system_event_ap_staconnected_t sta_connected; /*!< a station connected to soft-AP */
|
system_event_ap_staconnected_t sta_connected; /*!< a station connected to soft-AP */
|
||||||
system_event_ap_stadisconnected_t sta_disconnected; /*!< a station disconnected to soft-AP */
|
system_event_ap_stadisconnected_t sta_disconnected; /*!< a station disconnected to soft-AP */
|
||||||
system_event_ap_probe_req_rx_t ap_probereqrecved; /*!< soft-AP receive probe request packet */
|
system_event_ap_probe_req_rx_t ap_probereqrecved; /*!< soft-AP receive probe request packet */
|
||||||
|
system_event_bss_rssi_low_t bss_rssi_low; /*!< Connected BSS rssi goes below threshold */
|
||||||
system_event_ap_staipassigned_t ap_staipassigned; /**< soft-AP assign an IP to the station*/
|
system_event_ap_staipassigned_t ap_staipassigned; /**< soft-AP assign an IP to the station*/
|
||||||
system_event_got_ip6_t got_ip6; /*!< station or ap or ethernet ipv6 addr state change to preferred */
|
system_event_got_ip6_t got_ip6; /*!< station or ap or ethernet ipv6 addr state change to preferred */
|
||||||
} system_event_info_t;
|
} system_event_info_t;
|
||||||
|
@ -6,6 +6,7 @@ set(srcs "port/os_xtensa.c"
|
|||||||
"src/common/sae.c"
|
"src/common/sae.c"
|
||||||
"src/common/wpa_common.c"
|
"src/common/wpa_common.c"
|
||||||
"src/common/dpp.c"
|
"src/common/dpp.c"
|
||||||
|
"src/utils/bitfield.c"
|
||||||
"src/crypto/aes-ctr.c"
|
"src/crypto/aes-ctr.c"
|
||||||
"src/crypto/aes-siv.c"
|
"src/crypto/aes-siv.c"
|
||||||
"src/crypto/sha256-kdf.c"
|
"src/crypto/sha256-kdf.c"
|
||||||
@ -106,7 +107,21 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}" "${tls_src}"
|
if (CONFIG_WPA_11KV_SUPPORT)
|
||||||
|
set(roaming_src
|
||||||
|
"src/common/rrm.c"
|
||||||
|
"src/common/wnm_sta.c"
|
||||||
|
"src/common/bss.c"
|
||||||
|
"src/common/scan.c"
|
||||||
|
"src/common/ieee802_11_common.c"
|
||||||
|
"src/esp_supplicant/esp_common.c"
|
||||||
|
"src/esp_supplicant/esp_scan.c"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(roaming_src "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS "${srcs}" "${tls_src}" "${roaming_src}"
|
||||||
INCLUDE_DIRS include port/include include/esp_supplicant
|
INCLUDE_DIRS include port/include include/esp_supplicant
|
||||||
PRIV_INCLUDE_DIRS src
|
PRIV_INCLUDE_DIRS src
|
||||||
PRIV_REQUIRES mbedtls freertos heap newlib)
|
PRIV_REQUIRES mbedtls freertos heap newlib)
|
||||||
@ -132,4 +147,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
|||||||
CONFIG_WPA3_SAE
|
CONFIG_WPA3_SAE
|
||||||
#CONFIG_SHA256
|
#CONFIG_SHA256
|
||||||
CONFIG_DPP
|
CONFIG_DPP
|
||||||
|
CONFIG_WNM
|
||||||
)
|
)
|
||||||
|
@ -50,4 +50,22 @@ config LTM_FAST
|
|||||||
button bit without setting virtual/phycial display/button bit which
|
button bit without setting virtual/phycial display/button bit which
|
||||||
will cause M2 validation fail, bypassing WPS-Config method validation.
|
will cause M2 validation fail, bypassing WPS-Config method validation.
|
||||||
|
|
||||||
|
menuconfig WPA_11KV_SUPPORT
|
||||||
|
bool "Enable 802.11k, 802.11v APIs handling in supplicant"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Select this option to enable 802.11k 802.11v APIs.
|
||||||
|
Only APIs which are helpful for network assisted roaming
|
||||||
|
are supported for now.
|
||||||
|
Enable this option with btm and rrm enabled in sta config
|
||||||
|
to make device ready for network assisted roaming.
|
||||||
|
|
||||||
|
if WPA_11KV_SUPPORT
|
||||||
|
config WPA_SCAN_CACHE
|
||||||
|
bool "Keep scan results in cache"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Keep scan results in cache, if not enabled, those
|
||||||
|
will be flushed immediately.
|
||||||
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -5,7 +5,7 @@ COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
|
COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
|
||||||
|
|
||||||
ifeq ($(CONFIG_WPA_MBEDTLS_CRYPTO), y)
|
ifeq ($(CONFIG_WPA_MBEDTLS_CRYPTO), y)
|
||||||
COMPONENT_OBJEXCLUDE := src/tls/asn1.o \
|
COMPONENT_OBJEXCLUDE += src/tls/asn1.o \
|
||||||
src/tls/bignum.o \
|
src/tls/bignum.o \
|
||||||
src/tls/pkcs1.o \
|
src/tls/pkcs1.o \
|
||||||
src/tls/pkcs5.o \
|
src/tls/pkcs5.o \
|
||||||
@ -25,5 +25,14 @@ ifeq ($(CONFIG_WPA_MBEDTLS_CRYPTO), y)
|
|||||||
else
|
else
|
||||||
COMPONENT_OBJEXCLUDE := src/crypto/tls_mbedtls.o
|
COMPONENT_OBJEXCLUDE := src/crypto/tls_mbedtls.o
|
||||||
endif
|
endif
|
||||||
|
ifneq ($(CONFIG_WPA_11KV_SUPPORT), y)
|
||||||
|
COMPONENT_OBJEXCLUDE += src/common/rrm.o \
|
||||||
|
src/common/wnm_sta.o \
|
||||||
|
src/common/bss.o \
|
||||||
|
src/common/scan.o \
|
||||||
|
src/common/ieee802_11_common.o \
|
||||||
|
src/esp_supplicant/esp_common.o \
|
||||||
|
src/esp_supplicant/esp_scan.o
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -DCONFIG_DPP -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP8266_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
CFLAGS += -DCONFIG_DPP -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP8266_WORKAROUND -DCONFIG_ECC -DCONFIG_WNM -D__ets__ -Wno-strict-aliasing
|
||||||
|
54
components/wpa_supplicant/include/esp_supplicant/esp_rrm.h
Executable file
54
components/wpa_supplicant/include/esp_supplicant/esp_rrm.h
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ESP_RRM_H
|
||||||
|
#define _ESP_RRM_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function type to get neighbor report
|
||||||
|
*
|
||||||
|
* @param ctx: neighbor report context
|
||||||
|
* @param report: neighbor report
|
||||||
|
* @param report_len: neighbor report length
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - void
|
||||||
|
*/
|
||||||
|
typedef void (*neighbor_rep_request_cb)(void *ctx, const uint8_t *report, size_t report_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send Radio measurement neighbor report request to connect AP
|
||||||
|
*
|
||||||
|
* @param cb: callback function for neighbor report
|
||||||
|
* @param cb_ctx: callback context
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - 0: success else failure
|
||||||
|
*/
|
||||||
|
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
|
||||||
|
void *cb_ctx);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
58
components/wpa_supplicant/include/esp_supplicant/esp_wnm.h
Executable file
58
components/wpa_supplicant/include/esp_supplicant/esp_wnm.h
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ESP_WNM_H
|
||||||
|
#define _ESP_WNM_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum btm_query_reason: Reason code for sending btm query
|
||||||
|
*/
|
||||||
|
enum btm_query_reason {
|
||||||
|
REASON_UNSPECIFIED = 0,
|
||||||
|
REASON_FRAME_LOSS = 1,
|
||||||
|
REASON_DELAY = 2,
|
||||||
|
REASON_QOS_CAPACITY = 3,
|
||||||
|
REASON_FIRST_ASSOC = 4,
|
||||||
|
REASON_LOAD_BALALNCE = 5,
|
||||||
|
REASON_BETTER_AP = 6,
|
||||||
|
REASON_CURRENT_DEAUTH = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send bss transition query to connected AP
|
||||||
|
*
|
||||||
|
* @param query_reason: reason for sending query
|
||||||
|
* @param btm_candidates: btm candidates list if available
|
||||||
|
* @param cand_list: whether candidate list to be included or not
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - 0: success else failure
|
||||||
|
*/
|
||||||
|
int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
|
||||||
|
const char *btm_candidates,
|
||||||
|
int cand_list);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "wpabuf.h"
|
#include "wpabuf.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "supplicant_opt.h"
|
||||||
|
|
||||||
#ifdef ESPRESSIF_USE
|
#ifdef ESPRESSIF_USE
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ void wpa_debug_print_timestamp(void);
|
|||||||
* Note: New line '\n' is added to the end of the text when printing to stdout.
|
* Note: New line '\n' is added to the end of the text when printing to stdout.
|
||||||
*/
|
*/
|
||||||
#define wpa_printf(level,fmt, args...) ESP_LOG_LEVEL_LOCAL(level, TAG, fmt, ##args)
|
#define wpa_printf(level,fmt, args...) ESP_LOG_LEVEL_LOCAL(level, TAG, fmt, ##args)
|
||||||
|
#define wpa_dbg(ctx, level, fmt, args...) wpa_printf(level, fmt, ##args)
|
||||||
|
|
||||||
void wpa_dump_mem(char* desc, uint8_t *addr, uint16_t len);
|
void wpa_dump_mem(char* desc, uint8_t *addr, uint16_t len);
|
||||||
static inline void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
|
static inline void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
|
||||||
@ -153,6 +155,7 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
|
|||||||
#define wpa_hexdump_buf_key(...) do {} while(0)
|
#define wpa_hexdump_buf_key(...) do {} while(0)
|
||||||
#define wpa_hexdump_ascii(...) do {} while(0)
|
#define wpa_hexdump_ascii(...) do {} while(0)
|
||||||
#define wpa_hexdump_ascii_key(...) do {} while(0)
|
#define wpa_hexdump_ascii_key(...) do {} while(0)
|
||||||
|
#define wpa_dbg(...) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define wpa_auth_logger
|
#define wpa_auth_logger
|
||||||
|
@ -40,6 +40,8 @@ struct os_time {
|
|||||||
suseconds_t usec;
|
suseconds_t usec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define os_reltime os_time
|
||||||
|
|
||||||
struct os_tm {
|
struct os_tm {
|
||||||
int sec; /* 0..59 or 60 for leap seconds */
|
int sec; /* 0..59 or 60 for leap seconds */
|
||||||
int min; /* 0..59 */
|
int min; /* 0..59 */
|
||||||
@ -55,7 +57,7 @@ struct os_tm {
|
|||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int os_get_time(struct os_time *t);
|
int os_get_time(struct os_time *t);
|
||||||
|
#define os_get_reltime os_get_time
|
||||||
|
|
||||||
/* Helper macros for handling struct os_time */
|
/* Helper macros for handling struct os_time */
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ int os_get_time(struct os_time *t);
|
|||||||
((a)->sec < (b)->sec || \
|
((a)->sec < (b)->sec || \
|
||||||
((a)->sec == (b)->sec && (a)->usec < (b)->usec))
|
((a)->sec == (b)->sec && (a)->usec < (b)->usec))
|
||||||
|
|
||||||
|
#define os_reltime_before os_time_before
|
||||||
#define os_time_sub(a, b, res) do { \
|
#define os_time_sub(a, b, res) do { \
|
||||||
(res)->sec = (a)->sec - (b)->sec; \
|
(res)->sec = (a)->sec - (b)->sec; \
|
||||||
(res)->usec = (a)->usec - (b)->usec; \
|
(res)->usec = (a)->usec - (b)->usec; \
|
||||||
@ -71,6 +74,7 @@ int os_get_time(struct os_time *t);
|
|||||||
(res)->usec += 1000000; \
|
(res)->usec += 1000000; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define os_reltime_sub os_time_sub
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* os_mktime - Convert broken-down time into seconds since 1970-01-01
|
* os_mktime - Convert broken-down time into seconds since 1970-01-01
|
||||||
@ -213,6 +217,10 @@ char * os_readfile(const char *name, size_t *len);
|
|||||||
#ifndef os_zalloc
|
#ifndef os_zalloc
|
||||||
#define os_zalloc(s) calloc(1, (s))
|
#define os_zalloc(s) calloc(1, (s))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef os_calloc
|
||||||
|
#define os_calloc(p, s) calloc((p), (s))
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef os_free
|
#ifndef os_free
|
||||||
#define os_free(p) free((p))
|
#define os_free(p) free((p))
|
||||||
#endif
|
#endif
|
||||||
@ -299,4 +307,11 @@ static inline int os_snprintf_error(size_t size, int res)
|
|||||||
{
|
{
|
||||||
return res < 0 || (unsigned int) res >= size;
|
return res < 0 || (unsigned int) res >= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
if (size && nmemb > (~(size_t) 0) / size)
|
||||||
|
return NULL;
|
||||||
|
return os_realloc(ptr, nmemb * size);
|
||||||
|
}
|
||||||
#endif /* OS_H */
|
#endif /* OS_H */
|
||||||
|
@ -28,4 +28,12 @@
|
|||||||
#define DEBUG_PRINT
|
#define DEBUG_PRINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_WPA_11KV_SUPPORT
|
||||||
|
#define ROAMING_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_WPA_SCAN_CACHE
|
||||||
|
#define SCAN_CACHE_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _SUPPLICANT_OPT_H */
|
#endif /* _SUPPLICANT_OPT_H */
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
@ -49,3 +50,10 @@ int os_get_random(unsigned char *buf, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void os_sleep(os_time_t sec, os_time_t usec)
|
||||||
|
{
|
||||||
|
if (sec)
|
||||||
|
sleep(sec);
|
||||||
|
if (usec)
|
||||||
|
usleep(usec);
|
||||||
|
}
|
||||||
|
@ -2177,7 +2177,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM_AP
|
||||||
/* update GTK when exiting WNM-Sleep Mode */
|
/* update GTK when exiting WNM-Sleep Mode */
|
||||||
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
|
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
|
||||||
{
|
{
|
||||||
@ -2254,7 +2254,7 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
|
|||||||
return pos - start;
|
return pos - start;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM_AP */
|
||||||
|
|
||||||
|
|
||||||
static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
|
static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
|
||||||
|
478
components/wpa_supplicant/src/common/bss.c
Executable file
478
components/wpa_supplicant/src/common/bss.c
Executable file
@ -0,0 +1,478 @@
|
|||||||
|
/*
|
||||||
|
* BSS table
|
||||||
|
* Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "common/ieee802_11_common.h"
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "eap_peer/eap.h"
|
||||||
|
#include "wpa_supplicant_i.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "scan.h"
|
||||||
|
#include "bss.h"
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
#include "esp_supplicant/esp_wifi_driver.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_BSS_COUNT 20
|
||||||
|
|
||||||
|
void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||||
|
const char *reason)
|
||||||
|
{
|
||||||
|
if (wpa_s->last_scan_res) {
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
|
||||||
|
if (wpa_s->last_scan_res[i] == bss) {
|
||||||
|
os_memmove(&wpa_s->last_scan_res[i],
|
||||||
|
&wpa_s->last_scan_res[i + 1],
|
||||||
|
(wpa_s->last_scan_res_used - i - 1)
|
||||||
|
* sizeof(struct wpa_bss *));
|
||||||
|
wpa_s->last_scan_res_used--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dl_list_del(&bss->list);
|
||||||
|
dl_list_del(&bss->list_id);
|
||||||
|
wpa_s->num_bss--;
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
|
||||||
|
" SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
|
||||||
|
wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
|
||||||
|
os_free(bss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @bssid: BSSID
|
||||||
|
* @ssid: SSID
|
||||||
|
* @ssid_len: Length of @ssid
|
||||||
|
* Returns: Pointer to the BSS entry or %NULL if not found
|
||||||
|
*/
|
||||||
|
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
|
const u8 *ssid, size_t ssid_len)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
|
||||||
|
bss->ssid_len == ssid_len &&
|
||||||
|
os_memcmp(bss->ssid, ssid, ssid_len) == 0)
|
||||||
|
return bss;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void calculate_update_time(const struct os_reltime *fetch_time,
|
||||||
|
unsigned int age_ms,
|
||||||
|
struct os_reltime *update_time)
|
||||||
|
{
|
||||||
|
os_time_t usec;
|
||||||
|
|
||||||
|
update_time->sec = fetch_time->sec;
|
||||||
|
update_time->usec = fetch_time->usec;
|
||||||
|
update_time->sec -= age_ms / 1000;
|
||||||
|
usec = (age_ms % 1000) * 1000;
|
||||||
|
if (update_time->usec < usec) {
|
||||||
|
update_time->sec--;
|
||||||
|
update_time->usec += 1000000;
|
||||||
|
}
|
||||||
|
update_time->usec -= usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
|
||||||
|
struct os_reltime *fetch_time)
|
||||||
|
{
|
||||||
|
dst->flags = src->flags;
|
||||||
|
os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
|
||||||
|
dst->channel = src->chan;
|
||||||
|
dst->beacon_int = src->beacon_int;
|
||||||
|
dst->caps = src->caps;
|
||||||
|
dst->noise = src->noise;
|
||||||
|
dst->level = src->level;
|
||||||
|
dst->tsf = src->tsf;
|
||||||
|
dst->parent_tsf = src->parent_tsf;
|
||||||
|
|
||||||
|
calculate_update_time(fetch_time, src->age, &dst->last_update);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
|
||||||
|
|
||||||
|
if (ssid->ssid == NULL || ssid->len == 0)
|
||||||
|
return 0;
|
||||||
|
if (ssid->len == bss->ssid_len &&
|
||||||
|
os_memcmp(ssid->ssid, bss->ssid, ssid->len) == 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
if (bss == wpa_s->current_bss)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (wpa_s->current_bss &&
|
||||||
|
(bss->ssid_len != wpa_s->current_bss->ssid_len ||
|
||||||
|
os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
|
||||||
|
bss->ssid_len) != 0))
|
||||||
|
return 0; /* SSID has changed */
|
||||||
|
|
||||||
|
return !is_zero_ether_addr(bss->bssid) && wpa_s->current_bss->bssid &&
|
||||||
|
(os_memcmp(bss->bssid, wpa_s->current_bss->bssid, ETH_ALEN) == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (!wpa_bss_known(wpa_s, bss)) {
|
||||||
|
wpa_bss_remove(wpa_s, bss, __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the oldest entry that does not match with any configured
|
||||||
|
* network.
|
||||||
|
*/
|
||||||
|
if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the oldest entry that isn't currently in use.
|
||||||
|
*/
|
||||||
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (!wpa_bss_in_use(wpa_s, bss)) {
|
||||||
|
wpa_bss_remove(wpa_s, bss, __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *ssid, size_t ssid_len,
|
||||||
|
struct wpa_scan_res *res,
|
||||||
|
struct os_reltime *fetch_time)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
|
if ((wpa_s->num_bss + 1 > MAX_BSS_COUNT) &&
|
||||||
|
(wpa_bss_remove_oldest(wpa_s) < 0)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Failed to clean older entries, rejecting scan result");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
|
||||||
|
if (bss == NULL)
|
||||||
|
return NULL;
|
||||||
|
bss->id = wpa_s->bss_next_id++;
|
||||||
|
bss->last_update_idx = wpa_s->bss_update_idx;
|
||||||
|
wpa_bss_copy_res(bss, res, fetch_time);
|
||||||
|
os_memcpy(bss->ssid, ssid, ssid_len);
|
||||||
|
bss->ssid_len = ssid_len;
|
||||||
|
bss->ie_len = res->ie_len;
|
||||||
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
|
os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
|
||||||
|
|
||||||
|
dl_list_add_tail(&wpa_s->bss, &bss->list);
|
||||||
|
dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
|
||||||
|
wpa_s->num_bss++;
|
||||||
|
wpa_dbg(wpa_s, MSG_INFO, "BSS: Add new id %u BSSID " MACSTR
|
||||||
|
" SSID '%s' chan %d",
|
||||||
|
bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
|
||||||
|
bss->channel);
|
||||||
|
return bss;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wpa_bss *
|
||||||
|
wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||||
|
struct wpa_scan_res *res, struct os_reltime *fetch_time)
|
||||||
|
{
|
||||||
|
if (bss->last_update_idx == wpa_s->bss_update_idx) {
|
||||||
|
struct os_reltime update_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some drivers (e.g., cfg80211) include multiple BSS entries
|
||||||
|
* for the same BSS if that BSS's channel changes. The BSS list
|
||||||
|
* implementation in wpa_supplicant does not do that and we need
|
||||||
|
* to filter out the obsolete results here to make sure only the
|
||||||
|
* most current BSS information remains in the table.
|
||||||
|
*/
|
||||||
|
wpa_printf(MSG_DEBUG, "BSS: " MACSTR
|
||||||
|
" has multiple entries in the scan results - select the most current one",
|
||||||
|
MAC2STR(bss->bssid));
|
||||||
|
calculate_update_time(fetch_time, res->age, &update_time);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Accept this BSS entry since it looks more current than the previous update");
|
||||||
|
}
|
||||||
|
|
||||||
|
bss->last_update_idx = wpa_s->bss_update_idx;
|
||||||
|
wpa_bss_copy_res(bss, res, fetch_time);
|
||||||
|
/* Move the entry to the end of the list */
|
||||||
|
dl_list_del(&bss->list);
|
||||||
|
if (bss->ie_len + bss->beacon_ie_len >=
|
||||||
|
res->ie_len + res->beacon_ie_len) {
|
||||||
|
os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
|
||||||
|
bss->ie_len = res->ie_len;
|
||||||
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
|
} else {
|
||||||
|
struct wpa_bss *nbss;
|
||||||
|
struct dl_list *prev = bss->list_id.prev;
|
||||||
|
dl_list_del(&bss->list_id);
|
||||||
|
nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
|
||||||
|
res->beacon_ie_len);
|
||||||
|
if (nbss) {
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
|
||||||
|
if (wpa_s->last_scan_res[i] == bss) {
|
||||||
|
wpa_s->last_scan_res[i] = nbss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wpa_s->current_bss == bss)
|
||||||
|
wpa_s->current_bss = nbss;
|
||||||
|
bss = nbss;
|
||||||
|
os_memcpy(bss + 1, res + 1,
|
||||||
|
res->ie_len + res->beacon_ie_len);
|
||||||
|
bss->ie_len = res->ie_len;
|
||||||
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
|
}
|
||||||
|
dl_list_add(prev, &bss->list_id);
|
||||||
|
}
|
||||||
|
dl_list_add_tail(&wpa_s->bss, &bss->list);
|
||||||
|
|
||||||
|
return bss;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_update_start - Start a BSS table update from scan results
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
*
|
||||||
|
* This function is called at the start of each BSS table update round for new
|
||||||
|
* scan results. The actual scan result entries are indicated with calls to
|
||||||
|
* wpa_bss_update_scan_res() and the update round is finished with a call to
|
||||||
|
* wpa_bss_update_end().
|
||||||
|
*/
|
||||||
|
void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpa_s->bss_update_idx++;
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
|
||||||
|
wpa_s->bss_update_idx);
|
||||||
|
wpa_s->last_scan_res_used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @res: Scan result
|
||||||
|
* @fetch_time: Time when the result was fetched from the driver
|
||||||
|
*
|
||||||
|
* This function updates a BSS table entry (or adds one) based on a scan result.
|
||||||
|
* This is called separately for each scan result between the calls to
|
||||||
|
* wpa_bss_update_start() and wpa_bss_update_end().
|
||||||
|
*/
|
||||||
|
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_scan_res *res,
|
||||||
|
struct os_reltime *fetch_time)
|
||||||
|
{
|
||||||
|
const u8 *ssid;
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
|
ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
|
||||||
|
if (ssid == NULL) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
|
||||||
|
MACSTR, MAC2STR(res->bssid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ssid[1] > SSID_MAX_LEN) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
|
||||||
|
MACSTR, MAC2STR(res->bssid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: add option for ignoring BSSes we are not interested in
|
||||||
|
* (to save memory) */
|
||||||
|
|
||||||
|
bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
|
||||||
|
if (bss == NULL)
|
||||||
|
bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
|
||||||
|
else {
|
||||||
|
bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
|
||||||
|
if (wpa_s->last_scan_res) {
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
|
||||||
|
if (bss == wpa_s->last_scan_res[i]) {
|
||||||
|
/* Already in the list */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bss == NULL)
|
||||||
|
return;
|
||||||
|
if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
|
||||||
|
struct wpa_bss **n;
|
||||||
|
unsigned int siz;
|
||||||
|
if (wpa_s->last_scan_res_size == 0)
|
||||||
|
siz = 32;
|
||||||
|
else
|
||||||
|
siz = wpa_s->last_scan_res_size * 2;
|
||||||
|
n = os_realloc_array(wpa_s->last_scan_res, siz,
|
||||||
|
sizeof(struct wpa_bss *));
|
||||||
|
if (n == NULL)
|
||||||
|
return;
|
||||||
|
wpa_s->last_scan_res = n;
|
||||||
|
wpa_s->last_scan_res_size = siz;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s->last_scan_res)
|
||||||
|
wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_update_end - End a BSS table update from scan results
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @info: Information about scan parameters
|
||||||
|
* @new_scan: Whether this update round was based on a new scan
|
||||||
|
*
|
||||||
|
* This function is called at the end of each BSS table update round for new
|
||||||
|
* scan results. The start of the update was indicated with a call to
|
||||||
|
* wpa_bss_update_start().
|
||||||
|
*/
|
||||||
|
void wpa_bss_update_end(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
os_get_reltime(&wpa_s->last_scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_init - Initialize BSS table
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This prepares BSS table lists and timer for periodic updates. The BSS table
|
||||||
|
* is deinitialized with wpa_bss_deinit() once not needed anymore.
|
||||||
|
*/
|
||||||
|
int wpa_bss_init(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
dl_list_init(&wpa_s->bss);
|
||||||
|
dl_list_init(&wpa_s->bss_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_flush - Flush all unused BSS entries
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
*/
|
||||||
|
void wpa_bss_flush(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss, *n;
|
||||||
|
|
||||||
|
if (wpa_s->bss.next == NULL)
|
||||||
|
return; /* BSS table not yet initialized */
|
||||||
|
|
||||||
|
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (wpa_bss_in_use(wpa_s, bss))
|
||||||
|
continue;
|
||||||
|
wpa_bss_remove(wpa_s, bss, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_deinit - Deinitialize BSS table
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
*/
|
||||||
|
void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpa_bss_flush(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @bssid: BSSID
|
||||||
|
* Returns: Pointer to the BSS entry or %NULL if not found
|
||||||
|
*/
|
||||||
|
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *bssid)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
|
||||||
|
return bss;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_get_next_bss - Fetch a next BSS table entry from the list
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @bss: BSS
|
||||||
|
* Returns: Pointer to the BSS entry or %NULL if not found
|
||||||
|
*/
|
||||||
|
struct wpa_bss * wpa_bss_get_next_bss(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *prev_bss)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
|
if (!prev_bss)
|
||||||
|
return dl_list_first(&wpa_s->bss, struct wpa_bss, list);
|
||||||
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
if (os_memcmp(bss->bssid, prev_bss->bssid, ETH_ALEN) == 0)
|
||||||
|
return dl_list_entry(bss->list.next, struct wpa_bss, list);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_bss_get_ie - Fetch a specified information element from a BSS entry
|
||||||
|
* @bss: BSS table entry
|
||||||
|
* @ie: Information element identitifier (WLAN_EID_*)
|
||||||
|
* Returns: Pointer to the information element (id field) or %NULL if not found
|
||||||
|
*
|
||||||
|
* This function returns the first matching information element in the BSS
|
||||||
|
* entry.
|
||||||
|
*/
|
||||||
|
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
|
||||||
|
{
|
||||||
|
return get_ie((const u8 *) (bss + 1), bss->ie_len, ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
|
||||||
|
{
|
||||||
|
return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
|
||||||
|
capab);
|
||||||
|
}
|
86
components/wpa_supplicant/src/common/bss.h
Executable file
86
components/wpa_supplicant/src/common/bss.h
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* BSS table
|
||||||
|
* Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BSS_H
|
||||||
|
#define BSS_H
|
||||||
|
|
||||||
|
struct wpa_scan_res;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_bss - BSS table
|
||||||
|
*
|
||||||
|
* This structure is used to store information about neighboring BSSes in
|
||||||
|
* generic format. It is mainly updated based on scan results from the driver.
|
||||||
|
*/
|
||||||
|
struct wpa_bss {
|
||||||
|
/** List entry for struct wpa_supplicant::bss */
|
||||||
|
struct dl_list list;
|
||||||
|
/** List entry for struct wpa_supplicant::bss_id */
|
||||||
|
struct dl_list list_id;
|
||||||
|
/** Unique identifier for this BSS entry */
|
||||||
|
unsigned int id;
|
||||||
|
/** Index of the last scan update */
|
||||||
|
unsigned int last_update_idx;
|
||||||
|
/** Information flags about the BSS/IBSS (WPA_BSS_*) */
|
||||||
|
unsigned int flags;
|
||||||
|
/** BSSID */
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
/** SSID */
|
||||||
|
u8 ssid[SSID_MAX_LEN];
|
||||||
|
/** Length of SSID */
|
||||||
|
size_t ssid_len;
|
||||||
|
/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
|
||||||
|
int channel;
|
||||||
|
/** Beacon interval in TUs (host byte order) */
|
||||||
|
u16 beacon_int;
|
||||||
|
/** Capability information field in host byte order */
|
||||||
|
u16 caps;
|
||||||
|
/** Signal quality */
|
||||||
|
int qual;
|
||||||
|
/** Noise level */
|
||||||
|
int noise;
|
||||||
|
/** Signal level */
|
||||||
|
int level;
|
||||||
|
/** Timestamp of last Beacon/Probe Response frame */
|
||||||
|
u64 tsf;
|
||||||
|
/** Timestamp of parent aganist which it was taken */
|
||||||
|
u64 parent_tsf;
|
||||||
|
/** Time of the last update (i.e., Beacon or Probe Response RX) */
|
||||||
|
struct os_reltime last_update;
|
||||||
|
/** Length of the following IE field in octets (from Probe Response) */
|
||||||
|
size_t ie_len;
|
||||||
|
/** Length of the following Beacon IE field in octets */
|
||||||
|
size_t beacon_ie_len;
|
||||||
|
/* followed by ie_len octets of IEs */
|
||||||
|
/* followed by beacon_ie_len octets of IEs */
|
||||||
|
};
|
||||||
|
|
||||||
|
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
|
||||||
|
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_scan_res *res,
|
||||||
|
struct os_reltime *fetch_time);
|
||||||
|
void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||||
|
const char *reason);
|
||||||
|
void wpa_bss_update_end(struct wpa_supplicant *wpa_s);
|
||||||
|
int wpa_bss_init(struct wpa_supplicant *wpa_s);
|
||||||
|
void wpa_bss_deinit(struct wpa_supplicant *wpa_s);
|
||||||
|
void wpa_bss_flush(struct wpa_supplicant *wpa_s);
|
||||||
|
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
|
const u8 *ssid, size_t ssid_len);
|
||||||
|
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *bssid);
|
||||||
|
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
|
||||||
|
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
|
||||||
|
struct wpa_bss * wpa_bss_get_next_bss(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *prev_bss);
|
||||||
|
|
||||||
|
void calculate_update_time(const struct os_reltime *fetch_time,
|
||||||
|
unsigned int age_ms,
|
||||||
|
struct os_reltime *update_time);
|
||||||
|
|
||||||
|
#endif /* BSS_H */
|
198
components/wpa_supplicant/src/common/ieee802_11_common.c
Executable file
198
components/wpa_supplicant/src/common/ieee802_11_common.c
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* IEEE 802.11 Common routines
|
||||||
|
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "ieee802_11_defs.h"
|
||||||
|
#include "ieee802_11_common.h"
|
||||||
|
#include "common/wpa_supplicant_i.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_ie - Fetch a specified information element from IEs buffer
|
||||||
|
* @ies: Information elements buffer
|
||||||
|
* @len: Information elements buffer length
|
||||||
|
* @eid: Information element identifier (WLAN_EID_*)
|
||||||
|
* Returns: Pointer to the information element (id field) or %NULL if not found
|
||||||
|
*
|
||||||
|
* This function returns the first matching information element in the IEs
|
||||||
|
* buffer or %NULL in case the element is not found.
|
||||||
|
*/
|
||||||
|
const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
|
||||||
|
{
|
||||||
|
const struct element *elem;
|
||||||
|
|
||||||
|
if (!ies)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for_each_element_id(elem, eid, ies, len)
|
||||||
|
return &elem->id;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
||||||
|
size_t nei_rep_len)
|
||||||
|
{
|
||||||
|
u8 *nei_pos = nei_rep;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BSS Transition Candidate List Entries - Neighbor Report elements
|
||||||
|
* neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
|
||||||
|
* <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
|
||||||
|
*/
|
||||||
|
while (pos) {
|
||||||
|
u8 *nei_start;
|
||||||
|
long int val;
|
||||||
|
char *endptr, *tmp;
|
||||||
|
|
||||||
|
pos = os_strstr(pos, " neighbor=");
|
||||||
|
if (!pos)
|
||||||
|
break;
|
||||||
|
if (nei_pos + 15 > nei_rep + nei_rep_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Not enough room for additional neighbor");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += 10;
|
||||||
|
|
||||||
|
nei_start = nei_pos;
|
||||||
|
*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
|
||||||
|
nei_pos++; /* length to be filled in */
|
||||||
|
|
||||||
|
if (hwaddr_aton2(pos, nei_pos) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Invalid BSSID");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nei_pos += ETH_ALEN;
|
||||||
|
pos += 17;
|
||||||
|
if (*pos != ',') {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing BSSID Information");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
val = strtol(pos, &endptr, 0);
|
||||||
|
WPA_PUT_LE32(nei_pos, val);
|
||||||
|
nei_pos += 4;
|
||||||
|
if (*endptr != ',') {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing Operating Class");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos = endptr + 1;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* Operating Class */
|
||||||
|
pos = os_strchr(pos, ',');
|
||||||
|
if (pos == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing Channel Number");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* Channel Number */
|
||||||
|
pos = os_strchr(pos, ',');
|
||||||
|
if (pos == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing PHY Type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* PHY Type */
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
tmp = os_strchr(pos, ',');
|
||||||
|
if (tmp && (!end || tmp < end)) {
|
||||||
|
/* Optional Subelements (hexdump) */
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
pos = tmp + 1;
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
if (end)
|
||||||
|
len = end - pos;
|
||||||
|
else
|
||||||
|
len = os_strlen(pos);
|
||||||
|
if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Not enough room for neighbor subelements");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len & 0x01 ||
|
||||||
|
hexstr2bin(pos, nei_pos, len / 2) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Invalid neighbor subelement info");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nei_pos += len / 2;
|
||||||
|
pos = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
nei_start[1] = nei_pos - nei_start - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nei_pos - nei_rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee802_11_parse_elems - Parse information elements in management frames
|
||||||
|
* @start: Pointer to the start of IEs
|
||||||
|
* @len: Length of IE buffer in octets
|
||||||
|
* @elems: Data structure for parsed elements
|
||||||
|
* @show_errors: Whether to show parsing errors in debug log
|
||||||
|
* Returns: Parsing result
|
||||||
|
*/
|
||||||
|
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len)
|
||||||
|
{
|
||||||
|
const struct element *elem;
|
||||||
|
|
||||||
|
if (!start)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for_each_element(elem, start, len) {
|
||||||
|
u8 id = elem->id;
|
||||||
|
const u8 *pos = elem->data;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case WLAN_EID_RRM_ENABLED_CAPABILITIES:
|
||||||
|
os_memcpy(wpa_s->rrm_ie, pos, 5);
|
||||||
|
wpa_s->rrm.rrm_used = true;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_CAPAB:
|
||||||
|
/* extended caps can go beyond 8 octacts but we aren't using them now */
|
||||||
|
os_memcpy(wpa_s->extend_caps, pos, 5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
|
||||||
|
{
|
||||||
|
if (!ie || ie[1] <= capab / 8)
|
||||||
|
return 0;
|
||||||
|
return !!(ie[2 + capab / 8] & BIT(capab % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_operating_class(u8 chan, int sec_channel)
|
||||||
|
{
|
||||||
|
u8 op_class;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return op_class;
|
||||||
|
}
|
42
components/wpa_supplicant/src/common/ieee802_11_common.h
Executable file
42
components/wpa_supplicant/src/common/ieee802_11_common.h
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* IEEE 802.11 Common routines
|
||||||
|
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IEEE802_11_COMMON_H
|
||||||
|
#define IEEE802_11_COMMON_H
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "ieee802_11_defs.h"
|
||||||
|
|
||||||
|
struct element {
|
||||||
|
u8 id;
|
||||||
|
u8 datalen;
|
||||||
|
u8 data[];
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* element iteration helpers */
|
||||||
|
#define for_each_element(_elem, _data, _datalen) \
|
||||||
|
for (_elem = (const struct element *) (_data); \
|
||||||
|
(const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \
|
||||||
|
(int) sizeof(*_elem) && \
|
||||||
|
(const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \
|
||||||
|
(int) sizeof(*_elem) + _elem->datalen; \
|
||||||
|
_elem = (const struct element *) (_elem->data + _elem->datalen))
|
||||||
|
|
||||||
|
#define for_each_element_id(element, _id, data, datalen) \
|
||||||
|
for_each_element(element, data, datalen) \
|
||||||
|
if (element->id == (_id))
|
||||||
|
|
||||||
|
struct wpa_supplicant;
|
||||||
|
|
||||||
|
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
||||||
|
size_t nei_rep_len);
|
||||||
|
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
|
||||||
|
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len);
|
||||||
|
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
|
||||||
|
u8 get_operating_class(u8 chan, int sec_channel);
|
||||||
|
#endif /* IEEE802_11_COMMON_H */
|
@ -1,21 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* IEEE 802.11 Frame type definitions
|
* IEEE 802.11 Frame type definitions
|
||||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||||
* Copyright (c) 2007-2008 Intel Corporation
|
* Copyright (c) 2007-2008 Intel Corporation
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* See README for more details.
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* Alternatively, this software may be distributed under the terms of BSD
|
|
||||||
* license.
|
|
||||||
*
|
|
||||||
* See README and COPYING for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IEEE802_11_DEFS_H
|
#ifndef IEEE802_11_DEFS_H
|
||||||
#define IEEE802_11_DEFS_H
|
#define IEEE802_11_DEFS_H
|
||||||
|
|
||||||
|
#include <utils/common.h>
|
||||||
|
|
||||||
/* IEEE 802.11 defines */
|
/* IEEE 802.11 defines */
|
||||||
|
|
||||||
#define WLAN_FC_PVER 0x0003
|
#define WLAN_FC_PVER 0x0003
|
||||||
@ -89,10 +85,15 @@
|
|||||||
#define WLAN_CAPABILITY_PBCC BIT(6)
|
#define WLAN_CAPABILITY_PBCC BIT(6)
|
||||||
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
||||||
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
||||||
|
#define WLAN_CAPABILITY_QOS BIT(9)
|
||||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
||||||
|
#define WLAN_CAPABILITY_APSD BIT(11)
|
||||||
|
#define WLAN_CAPABILITY_RADIO_MEASUREMENT BIT(12)
|
||||||
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
||||||
|
#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
|
||||||
|
#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
|
||||||
|
|
||||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
/* Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */
|
||||||
#define WLAN_STATUS_SUCCESS 0
|
#define WLAN_STATUS_SUCCESS 0
|
||||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||||
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
||||||
@ -104,26 +105,23 @@
|
|||||||
#define WLAN_STATUS_AUTH_TIMEOUT 16
|
#define WLAN_STATUS_AUTH_TIMEOUT 16
|
||||||
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_RATES 18
|
#define WLAN_STATUS_ASSOC_DENIED_RATES 18
|
||||||
/* IEEE 802.11b */
|
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
|
#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
|
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
|
|
||||||
/* IEEE 802.11h */
|
|
||||||
#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
|
#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
|
||||||
#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
|
#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
|
||||||
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
||||||
/* IEEE 802.11g */
|
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
|
||||||
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||||
/* IEEE 802.11w */
|
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
|
||||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||||
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
|
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
|
||||||
|
#define WLAN_STATUS_DENIED_INSUFFICIENT_BANDWIDTH 33
|
||||||
|
#define WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS 34
|
||||||
|
#define WLAN_STATUS_DENIED_QOS_NOT_SUPPORTED 35
|
||||||
#define WLAN_STATUS_REQUEST_DECLINED 37
|
#define WLAN_STATUS_REQUEST_DECLINED 37
|
||||||
#define WLAN_STATUS_INVALID_PARAMETERS 38
|
#define WLAN_STATUS_INVALID_PARAMETERS 38
|
||||||
/* IEEE 802.11i */
|
#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39
|
||||||
#define WLAN_STATUS_INVALID_IE 40
|
#define WLAN_STATUS_INVALID_IE 40
|
||||||
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
||||||
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
|
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
|
||||||
@ -136,7 +134,6 @@
|
|||||||
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
|
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
|
||||||
#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
|
#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
|
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
|
||||||
/* IEEE 802.11r */
|
|
||||||
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
|
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
|
||||||
#define WLAN_STATUS_INVALID_PMKID 53
|
#define WLAN_STATUS_INVALID_PMKID 53
|
||||||
#define WLAN_STATUS_INVALID_MDIE 54
|
#define WLAN_STATUS_INVALID_MDIE 54
|
||||||
@ -161,7 +158,7 @@
|
|||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
|
#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
|
||||||
#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
|
#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
|
||||||
|
|
||||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
|
||||||
#define WLAN_REASON_UNSPECIFIED 1
|
#define WLAN_REASON_UNSPECIFIED 1
|
||||||
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
|
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
|
||||||
#define WLAN_REASON_DEAUTH_LEAVING 3
|
#define WLAN_REASON_DEAUTH_LEAVING 3
|
||||||
@ -171,10 +168,9 @@
|
|||||||
#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
|
#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
|
||||||
#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
|
#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
|
||||||
#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
|
#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
|
||||||
/* IEEE 802.11h */
|
|
||||||
#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
|
#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
|
||||||
#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
|
#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
|
||||||
/* IEEE 802.11i */
|
#define WLAN_REASON_BSS_TRANSITION_DISASSOC 12
|
||||||
#define WLAN_REASON_INVALID_IE 13
|
#define WLAN_REASON_INVALID_IE 13
|
||||||
#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
|
#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
|
||||||
#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
|
#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
|
||||||
@ -188,18 +184,15 @@
|
|||||||
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||||
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
||||||
|
|
||||||
|
/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */
|
||||||
/* Information Element IDs */
|
|
||||||
#define WLAN_EID_SSID 0
|
#define WLAN_EID_SSID 0
|
||||||
#define WLAN_EID_SUPP_RATES 1
|
#define WLAN_EID_SUPP_RATES 1
|
||||||
#define WLAN_EID_FH_PARAMS 2
|
|
||||||
#define WLAN_EID_DS_PARAMS 3
|
#define WLAN_EID_DS_PARAMS 3
|
||||||
#define WLAN_EID_CF_PARAMS 4
|
#define WLAN_EID_CF_PARAMS 4
|
||||||
#define WLAN_EID_TIM 5
|
#define WLAN_EID_TIM 5
|
||||||
#define WLAN_EID_IBSS_PARAMS 6
|
#define WLAN_EID_IBSS_PARAMS 6
|
||||||
#define WLAN_EID_COUNTRY 7
|
#define WLAN_EID_COUNTRY 7
|
||||||
#define WLAN_EID_CHALLENGE 16
|
#define WLAN_EID_CHALLENGE 16
|
||||||
/* EIDs defined by IEEE 802.11h - START */
|
|
||||||
#define WLAN_EID_PWR_CONSTRAINT 32
|
#define WLAN_EID_PWR_CONSTRAINT 32
|
||||||
#define WLAN_EID_PWR_CAPABILITY 33
|
#define WLAN_EID_PWR_CAPABILITY 33
|
||||||
#define WLAN_EID_TPC_REQUEST 34
|
#define WLAN_EID_TPC_REQUEST 34
|
||||||
@ -208,23 +201,25 @@
|
|||||||
#define WLAN_EID_CHANNEL_SWITCH 37
|
#define WLAN_EID_CHANNEL_SWITCH 37
|
||||||
#define WLAN_EID_MEASURE_REQUEST 38
|
#define WLAN_EID_MEASURE_REQUEST 38
|
||||||
#define WLAN_EID_MEASURE_REPORT 39
|
#define WLAN_EID_MEASURE_REPORT 39
|
||||||
#define WLAN_EID_QUITE 40
|
#define WLAN_EID_QUIET 40
|
||||||
#define WLAN_EID_IBSS_DFS 41
|
#define WLAN_EID_IBSS_DFS 41
|
||||||
/* EIDs defined by IEEE 802.11h - END */
|
|
||||||
#define WLAN_EID_ERP_INFO 42
|
#define WLAN_EID_ERP_INFO 42
|
||||||
#define WLAN_EID_HT_CAP 45
|
#define WLAN_EID_HT_CAP 45
|
||||||
#define WLAN_EID_RSN 48
|
#define WLAN_EID_RSN 48
|
||||||
#define WLAN_EID_EXT_SUPP_RATES 50
|
#define WLAN_EID_EXT_SUPP_RATES 50
|
||||||
|
#define WLAN_EID_NEIGHBOR_REPORT 52
|
||||||
#define WLAN_EID_MOBILITY_DOMAIN 54
|
#define WLAN_EID_MOBILITY_DOMAIN 54
|
||||||
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
||||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||||
#define WLAN_EID_RIC_DATA 57
|
#define WLAN_EID_RIC_DATA 57
|
||||||
#define WLAN_EID_HT_OPERATION 61
|
#define WLAN_EID_HT_OPERATION 61
|
||||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||||
|
#define WLAN_EID_RRM_ENABLED_CAPABILITIES 70
|
||||||
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
|
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
|
||||||
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
||||||
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
||||||
#define WLAN_EID_MMIE 76
|
#define WLAN_EID_MMIE 76
|
||||||
|
#define WLAN_EID_EXT_CAPAB 127
|
||||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||||
#define WLAN_EID_CAG_NUMBER 237
|
#define WLAN_EID_CAG_NUMBER 237
|
||||||
#define WLAN_EID_AP_CSN 239
|
#define WLAN_EID_AP_CSN 239
|
||||||
@ -241,7 +236,7 @@
|
|||||||
#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5
|
#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5
|
||||||
#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6
|
#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6
|
||||||
#define WLAN_EID_EXT_KEY_DELIVERY 7
|
#define WLAN_EID_EXT_KEY_DELIVERY 7
|
||||||
#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8
|
#define WLAN_EID_EXT_WRAPPED_DATA 8
|
||||||
#define WLAN_EID_EXT_FTM_SYNC_INFO 9
|
#define WLAN_EID_EXT_FTM_SYNC_INFO 9
|
||||||
#define WLAN_EID_EXT_EXTENDED_REQUEST 10
|
#define WLAN_EID_EXT_EXTENDED_REQUEST 10
|
||||||
#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
|
#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
|
||||||
@ -253,8 +248,7 @@
|
|||||||
#define WLAN_EID_EXT_HE_CAPABILITIES 35
|
#define WLAN_EID_EXT_HE_CAPABILITIES 35
|
||||||
#define WLAN_EID_EXT_HE_OPERATION 36
|
#define WLAN_EID_EXT_HE_OPERATION 36
|
||||||
|
|
||||||
|
/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
|
||||||
/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
|
|
||||||
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
||||||
#define WLAN_ACTION_QOS 1
|
#define WLAN_ACTION_QOS 1
|
||||||
#define WLAN_ACTION_DLS 2
|
#define WLAN_ACTION_DLS 2
|
||||||
@ -264,6 +258,8 @@
|
|||||||
#define WLAN_ACTION_FT 6
|
#define WLAN_ACTION_FT 6
|
||||||
#define WLAN_ACTION_HT 7
|
#define WLAN_ACTION_HT 7
|
||||||
#define WLAN_ACTION_SA_QUERY 8
|
#define WLAN_ACTION_SA_QUERY 8
|
||||||
|
#define WLAN_ACTION_WNM 10
|
||||||
|
#define WLAN_ACTION_UNPROTECTED_WNM 11
|
||||||
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
||||||
|
|
||||||
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
||||||
@ -300,6 +296,51 @@ struct ieee80211_hdr {
|
|||||||
#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
|
#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
|
||||||
|
|
||||||
#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
|
#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
|
||||||
|
/* Radio Measurement Action codes */
|
||||||
|
#define WLAN_RRM_RADIO_MEASUREMENT_REQUEST 0
|
||||||
|
#define WLAN_RRM_RADIO_MEASUREMENT_REPORT 1
|
||||||
|
#define WLAN_RRM_LINK_MEASUREMENT_REQUEST 2
|
||||||
|
#define WLAN_RRM_LINK_MEASUREMENT_REPORT 3
|
||||||
|
#define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4
|
||||||
|
#define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5
|
||||||
|
|
||||||
|
/* Radio Measurement capabilities (from RM Enabled Capabilities element)
|
||||||
|
* IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */
|
||||||
|
/* byte 1 (out of 5) */
|
||||||
|
#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
|
||||||
|
#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
|
||||||
|
#define WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE BIT(4)
|
||||||
|
#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5)
|
||||||
|
#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
|
||||||
|
* measurement requests
|
||||||
|
*/
|
||||||
|
enum measure_type {
|
||||||
|
MEASURE_TYPE_RPI_HIST = 2,
|
||||||
|
MEASURE_TYPE_BEACON = 5,
|
||||||
|
MEASURE_TYPE_LCI = 8,
|
||||||
|
MEASURE_TYPE_LOCATION_CIVIC = 11,
|
||||||
|
MEASURE_TYPE_MEASURE_PAUSE = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2012 Table 8-71 - Location subject definition */
|
||||||
|
enum location_subject {
|
||||||
|
LOCATION_SUBJECT_LOCAL = 0,
|
||||||
|
LOCATION_SUBJECT_REMOTE = 1,
|
||||||
|
LOCATION_SUBJECT_3RD_PARTY = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE P802.11-REVmc/D5.0 Table 9-94 - Optional subelement IDs for LCI request
|
||||||
|
*/
|
||||||
|
enum lci_req_subelem {
|
||||||
|
LCI_REQ_SUBELEM_AZIMUTH_REQ = 1,
|
||||||
|
LCI_REQ_SUBELEM_ORIGINATOR_MAC_ADDR = 2,
|
||||||
|
LCI_REQ_SUBELEM_TARGET_MAC_ADDR = 3,
|
||||||
|
LCI_REQ_SUBELEM_MAX_AGE = 4,
|
||||||
|
};
|
||||||
|
|
||||||
struct ieee80211_mgmt {
|
struct ieee80211_mgmt {
|
||||||
le16 frame_control;
|
le16 frame_control;
|
||||||
@ -406,6 +447,7 @@ struct ieee80211_mgmt {
|
|||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
|
||||||
|
#define IEEE80211_MAX_MMPDU_SIZE 2304
|
||||||
struct ieee80211_ht_capabilities {
|
struct ieee80211_ht_capabilities {
|
||||||
le16 ht_capabilities_info;
|
le16 ht_capabilities_info;
|
||||||
u8 a_mpdu_params;
|
u8 a_mpdu_params;
|
||||||
@ -416,12 +458,14 @@ struct ieee80211_ht_capabilities {
|
|||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
|
||||||
|
/* HT Operation element */
|
||||||
struct ieee80211_ht_operation {
|
struct ieee80211_ht_operation {
|
||||||
u8 control_chan;
|
u8 primary_chan;
|
||||||
u8 ht_param;
|
/* Five octets of HT Operation Information */
|
||||||
le16 operation_mode;
|
u8 ht_param; /* B0..B7 */
|
||||||
le16 stbc_param;
|
le16 operation_mode; /* B8..B23 */
|
||||||
u8 basic_set[16];
|
le16 param; /* B24..B39 */
|
||||||
|
u8 basic_mcs_set[16];
|
||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -432,7 +476,9 @@ struct ieee80211_ht_operation {
|
|||||||
#define ERP_INFO_USE_PROTECTION BIT(1)
|
#define ERP_INFO_USE_PROTECTION BIT(1)
|
||||||
#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
|
#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
|
||||||
|
|
||||||
|
#define OVERLAPPING_BSS_TRANS_DELAY_FACTOR 5
|
||||||
|
|
||||||
|
/* HT Capabilities Info field within HT Capabilities element */
|
||||||
#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
||||||
#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
||||||
#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
||||||
@ -450,79 +496,86 @@ struct ieee80211_ht_operation {
|
|||||||
#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
||||||
#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
||||||
#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
||||||
#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
|
/* B13 - Reserved (was PSMP support during P802.11n development) */
|
||||||
#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
||||||
#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
||||||
|
|
||||||
|
/* HT Extended Capabilities field within HT Capabilities element */
|
||||||
#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0))
|
#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0))
|
||||||
|
#define EXT_HT_CAP_INFO_PCO_TRANS_TIME_MASK ((u16) (BIT(1) | BIT(2)))
|
||||||
#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1
|
#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1
|
||||||
|
/* B3..B7 - Reserved */
|
||||||
|
#define EXT_HT_CAP_INFO_MCS_FEEDBACK_MASK ((u16) (BIT(8) | BIT(9)))
|
||||||
#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8
|
#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8
|
||||||
#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10))
|
#define EXT_HT_CAP_INFO_HTC_SUPPORT ((u16) BIT(10))
|
||||||
#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11))
|
#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11))
|
||||||
|
/* B12..B15 - Reserved */
|
||||||
|
|
||||||
|
/* Transmit Beanforming Capabilities within HT Capabilities element */
|
||||||
|
#define TX_BF_CAP_IMPLICIT_TXBF_RX_CAP ((u32) BIT(0))
|
||||||
|
#define TX_BF_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
|
||||||
|
#define TX_BF_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
|
||||||
|
#define TX_BF_CAP_RX_NDP_CAP ((u32) BIT(3))
|
||||||
|
#define TX_BF_CAP_TX_NDP_CAP ((u32) BIT(4))
|
||||||
|
#define TX_BF_CAP_IMPLICIT_TX_BF_CAP ((u32) BIT(5))
|
||||||
|
#define TX_BF_CAP_CALIBRATION_MASK ((u32) (BIT(6) | BIT(7))
|
||||||
|
#define TX_BF_CAP_CALIB_OFFSET 6
|
||||||
|
#define TX_BF_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
|
||||||
|
#define TX_BF_CAP_EXPLICIT_NONCOMPR_STEERING_CAP ((u32) BIT(9))
|
||||||
|
#define TX_BF_CAP_EXPLICIT_COMPR_STEERING_CAP ((u32) BIT(10))
|
||||||
|
#define TX_BF_CAP_EXPLICIT_TX_BF_CSI_FEEDBACK_MASK ((u32) (BIT(10) | BIT(11)))
|
||||||
|
#define TX_BF_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
|
||||||
|
#define TX_BF_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
|
||||||
|
#define TX_BF_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
|
||||||
|
#define TX_BF_CAP_MINIMAL_GROUPING_OFFSET 17
|
||||||
|
#define TX_BF_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
|
||||||
|
#define TX_BF_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
|
||||||
|
#define TX_BF_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
|
||||||
|
#define TX_BF_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
|
||||||
|
#define TX_BF_CAP_CHANNEL_ESTIMATION_CAP_MASK ((u32) (BIT(27) | BIT(28)))
|
||||||
|
#define TX_BF_CAP_CHANNEL_ESTIMATION_CAP_OFFSET 27
|
||||||
|
/* B29..B31 - Reserved */
|
||||||
|
|
||||||
#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))
|
/* ASEL Capability field within HT Capabilities element */
|
||||||
#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
|
#define ASEL_CAP_ASEL_CAPABLE ((u8) BIT(0))
|
||||||
#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
|
#define ASEL_CAP_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
|
||||||
#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))
|
#define ASEL_CAP_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
|
||||||
#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))
|
#define ASEL_CAP_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
|
||||||
#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))
|
#define ASEL_CAP_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
|
||||||
#define TX_BEAMFORM_CAP_CALIB_OFFSET 6
|
#define ASEL_CAP_RX_AS_CAP ((u8) BIT(5))
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
|
#define ASEL_CAP_TX_SOUNDING_PPDUS_CAP ((u8) BIT(6))
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))
|
/* B7 - Reserved */
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))
|
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
|
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
|
|
||||||
#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
|
|
||||||
#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17
|
|
||||||
#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
|
|
||||||
#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
|
|
||||||
#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
|
|
||||||
#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
|
|
||||||
|
|
||||||
|
|
||||||
#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))
|
|
||||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
|
|
||||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
|
|
||||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
|
|
||||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
|
|
||||||
#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
|
|
||||||
#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
|
|
||||||
|
|
||||||
|
/* First octet of HT Operation Information within HT Operation element */
|
||||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
|
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
|
||||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
|
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
|
||||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
|
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
|
||||||
#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
|
#define HT_INFO_HT_PARAM_STA_CHNL_WIDTH ((u8) BIT(2))
|
||||||
#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
|
#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
|
||||||
#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
|
/* B4..B7 - Reserved */
|
||||||
#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
|
|
||||||
|
|
||||||
|
/* HT Protection (B8..B9 of HT Operation Information) */
|
||||||
|
#define HT_PROT_NO_PROTECTION 0
|
||||||
|
#define HT_PROT_NONMEMBER_PROTECTION 1
|
||||||
|
#define HT_PROT_20MHZ_PROTECTION 2
|
||||||
|
#define HT_PROT_NON_HT_MIXED 3
|
||||||
|
/* Bits within ieee80211_ht_operation::operation_mode (BIT(0) maps to B8 in
|
||||||
|
* HT Operation Information) */
|
||||||
|
#define HT_OPER_OP_MODE_HT_PROT_MASK ((u16) (BIT(0) | BIT(1))) /* B8..B9 */
|
||||||
|
#define HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT ((u16) BIT(2)) /* B10 */
|
||||||
|
/* BIT(3), i.e., B11 in HT Operation Information field - Reserved */
|
||||||
|
#define HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT ((u16) BIT(4)) /* B12 */
|
||||||
|
/* BIT(5)..BIT(15), i.e., B13..B23 - Reserved */
|
||||||
|
|
||||||
#define OP_MODE_PURE 0
|
/* Last two octets of HT Operation Information (BIT(0) = B24) */
|
||||||
#define OP_MODE_MAY_BE_LEGACY_STAS 1
|
/* B24..B29 - Reserved */
|
||||||
#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
|
#define HT_OPER_PARAM_DUAL_BEACON ((u16) BIT(6))
|
||||||
#define OP_MODE_MIXED 3
|
#define HT_OPER_PARAM_DUAL_CTS_PROTECTION ((u16) BIT(7))
|
||||||
|
#define HT_OPER_PARAM_STBC_BEACON ((u16) BIT(8))
|
||||||
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
|
#define HT_OPER_PARAM_LSIG_TXOP_PROT_FULL_SUPP ((u16) BIT(9))
|
||||||
((le16) (0x0001 | 0x0002))
|
#define HT_OPER_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
||||||
#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
|
#define HT_OPER_PARAM_PCO_PHASE ((u16) BIT(11))
|
||||||
#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
|
/* B36..B39 - Reserved */
|
||||||
#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
|
|
||||||
#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
|
|
||||||
|
|
||||||
#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
|
|
||||||
#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
|
|
||||||
#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8))
|
|
||||||
#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
|
|
||||||
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
|
||||||
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
|
|
||||||
|
|
||||||
|
|
||||||
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
|
||||||
* 00:50:F2 */
|
|
||||||
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
|
||||||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
|
||||||
|
|
||||||
#define WMM_OUI_TYPE 2
|
#define WMM_OUI_TYPE 2
|
||||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||||
@ -589,7 +642,7 @@ struct wmm_parameter_element {
|
|||||||
u8 oui_type; /* 2 */
|
u8 oui_type; /* 2 */
|
||||||
u8 oui_subtype; /* 1 */
|
u8 oui_subtype; /* 1 */
|
||||||
u8 version; /* 1 for WMM version 1.0 */
|
u8 version; /* 1 for WMM version 1.0 */
|
||||||
u8 qos_info; /* AP/STA specif QoS info */
|
u8 qos_info; /* AP/STA specific QoS info */
|
||||||
u8 reserved; /* 0 */
|
u8 reserved; /* 0 */
|
||||||
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||||
|
|
||||||
@ -624,29 +677,260 @@ struct wmm_tspec_element {
|
|||||||
|
|
||||||
|
|
||||||
/* Access Categories / ACI to AC coding */
|
/* Access Categories / ACI to AC coding */
|
||||||
enum {
|
enum wmm_ac {
|
||||||
WMM_AC_BE = 0 /* Best Effort */,
|
WMM_AC_BE = 0 /* Best Effort */,
|
||||||
WMM_AC_BK = 1 /* Background */,
|
WMM_AC_BK = 1 /* Background */,
|
||||||
WMM_AC_VI = 2 /* Video */,
|
WMM_AC_VI = 2 /* Video */,
|
||||||
WMM_AC_VO = 3 /* Voice */
|
WMM_AC_VO = 3 /* Voice */,
|
||||||
|
WMM_AC_NUM = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* MBO v0.0_r19, 4.2.7: Transition Rejection Reason Code Attribute */
|
||||||
|
/* Table 4-21: Transition Rejection Reason Code Field Values */
|
||||||
|
enum mbo_transition_reject_reason {
|
||||||
|
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED = 0,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_FRAME_LOSS = 1,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_DELAY = 2,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_QOS_CAPACITY = 3,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_RSSI = 4,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_INTERFERENCE = 5,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_SERVICES = 6,
|
||||||
|
};
|
||||||
|
|
||||||
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
/* IEEE 802.11v - WNM Action field values */
|
||||||
|
enum wnm_action {
|
||||||
|
WNM_EVENT_REQ = 0,
|
||||||
|
WNM_EVENT_REPORT = 1,
|
||||||
|
WNM_DIAGNOSTIC_REQ = 2,
|
||||||
|
WNM_DIAGNOSTIC_REPORT = 3,
|
||||||
|
WNM_LOCATION_CFG_REQ = 4,
|
||||||
|
WNM_LOCATION_CFG_RESP = 5,
|
||||||
|
WNM_BSS_TRANS_MGMT_QUERY = 6,
|
||||||
|
WNM_BSS_TRANS_MGMT_REQ = 7,
|
||||||
|
WNM_BSS_TRANS_MGMT_RESP = 8,
|
||||||
|
WNM_FMS_REQ = 9,
|
||||||
|
WNM_FMS_RESP = 10,
|
||||||
|
WNM_COLLOCATED_INTERFERENCE_REQ = 11,
|
||||||
|
WNM_COLLOCATED_INTERFERENCE_REPORT = 12,
|
||||||
|
WNM_TFS_REQ = 13,
|
||||||
|
WNM_TFS_RESP = 14,
|
||||||
|
WNM_TFS_NOTIFY = 15,
|
||||||
|
WNM_SLEEP_MODE_REQ = 16,
|
||||||
|
WNM_SLEEP_MODE_RESP = 17,
|
||||||
|
WNM_TIM_BROADCAST_REQ = 18,
|
||||||
|
WNM_TIM_BROADCAST_RESP = 19,
|
||||||
|
WNM_QOS_TRAFFIC_CAPAB_UPDATE = 20,
|
||||||
|
WNM_CHANNEL_USAGE_REQ = 21,
|
||||||
|
WNM_CHANNEL_USAGE_RESP = 22,
|
||||||
|
WNM_DMS_REQ = 23,
|
||||||
|
WNM_DMS_RESP = 24,
|
||||||
|
WNM_TIMING_MEASUREMENT_REQ = 25,
|
||||||
|
WNM_NOTIFICATION_REQ = 26,
|
||||||
|
WNM_NOTIFICATION_RESP = 27
|
||||||
|
};
|
||||||
|
|
||||||
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
|
/* IEEE 802.11v - BSS Transition Management Request - Request Mode */
|
||||||
|
#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0)
|
||||||
|
#define WNM_BSS_TM_REQ_ABRIDGED BIT(1)
|
||||||
|
#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2)
|
||||||
|
#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3)
|
||||||
|
#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4)
|
||||||
|
|
||||||
/* cipher suite selectors */
|
/* IEEE Std 802.11-2012 - Table 8-253 */
|
||||||
#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
|
enum bss_trans_mgmt_status_code {
|
||||||
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
|
WNM_BSS_TM_ACCEPT = 0,
|
||||||
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
|
WNM_BSS_TM_REJECT_UNSPECIFIED = 1,
|
||||||
/* reserved: 0x000FAC03 */
|
WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON = 2,
|
||||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY = 3,
|
||||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
WNM_BSS_TM_REJECT_UNDESIRED = 4,
|
||||||
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
WNM_BSS_TM_REJECT_DELAY_REQUEST = 5,
|
||||||
|
WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
|
||||||
|
WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES = 7,
|
||||||
|
WNM_BSS_TM_REJECT_LEAVING_ESS = 8
|
||||||
|
};
|
||||||
|
|
||||||
/* AKM suite selectors */
|
/*
|
||||||
#define WLAN_AKM_SUITE_8021X 0x000FAC01
|
* IEEE P802.11-REVmc/D5.0 Table 9-150 - Optional subelement IDs for
|
||||||
#define WLAN_AKM_SUITE_PSK 0x000FAC02
|
* neighbor report
|
||||||
|
*/
|
||||||
|
#define WNM_NEIGHBOR_TSF 1
|
||||||
|
#define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING 2
|
||||||
|
#define WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE 3
|
||||||
|
#define WNM_NEIGHBOR_BSS_TERMINATION_DURATION 4
|
||||||
|
#define WNM_NEIGHBOR_BEARING 5
|
||||||
|
#define WNM_NEIGHBOR_MEASUREMENT_REPORT 39
|
||||||
|
#define WNM_NEIGHBOR_MEASUREMENT_PILOT 66
|
||||||
|
#define WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES 70
|
||||||
|
#define WNM_NEIGHBOR_MULTIPLE_BSSID 71
|
||||||
|
|
||||||
|
struct tpc_report {
|
||||||
|
u8 eid;
|
||||||
|
u8 len;
|
||||||
|
u8 tx_power;
|
||||||
|
u8 link_margin;
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
#define RRM_CAPABILITIES_IE_LEN 5
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
|
||||||
|
struct rrm_link_measurement_request {
|
||||||
|
u8 dialog_token;
|
||||||
|
s8 tx_power;
|
||||||
|
s8 max_tp;
|
||||||
|
u8 variable[0];
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */
|
||||||
|
struct rrm_link_measurement_report {
|
||||||
|
u8 dialog_token;
|
||||||
|
struct tpc_report tpc;
|
||||||
|
u8 rx_ant_id;
|
||||||
|
u8 tx_ant_id;
|
||||||
|
u8 rcpi;
|
||||||
|
u8 rsni;
|
||||||
|
u8 variable[0];
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, 9.4.2.21 - Measurement Request element */
|
||||||
|
struct rrm_measurement_request_element {
|
||||||
|
u8 eid; /* Element ID */
|
||||||
|
u8 len; /* Length */
|
||||||
|
u8 token; /* Measurement Token */
|
||||||
|
u8 mode; /* Measurement Request Mode */
|
||||||
|
u8 type; /* Measurement Type */
|
||||||
|
u8 variable[0]; /* Measurement Request */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, Figure 9-148 - Measurement Request Mode field */
|
||||||
|
#define MEASUREMENT_REQUEST_MODE_PARALLEL BIT(0)
|
||||||
|
#define MEASUREMENT_REQUEST_MODE_ENABLE BIT(1)
|
||||||
|
#define MEASUREMENT_REQUEST_MODE_REQUEST BIT(2)
|
||||||
|
#define MEASUREMENT_REQUEST_MODE_REPORT BIT(3)
|
||||||
|
#define MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY BIT(4)
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, 9.4.2.21.7 - Beacon request */
|
||||||
|
struct rrm_measurement_beacon_request {
|
||||||
|
u8 oper_class; /* Operating Class */
|
||||||
|
u8 channel; /* Channel Number */
|
||||||
|
le16 rand_interval; /* Randomization Interval (in TUs) */
|
||||||
|
le16 duration; /* Measurement Duration (in TUs) */
|
||||||
|
u8 mode; /* Measurement Mode */
|
||||||
|
u8 bssid[ETH_ALEN]; /* BSSID */
|
||||||
|
u8 variable[0]; /* Optional Subelements */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon
|
||||||
|
* request
|
||||||
|
*/
|
||||||
|
enum beacon_report_mode {
|
||||||
|
BEACON_REPORT_MODE_PASSIVE = 0,
|
||||||
|
BEACON_REPORT_MODE_ACTIVE = 1,
|
||||||
|
BEACON_REPORT_MODE_TABLE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs */
|
||||||
|
/* IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for
|
||||||
|
* Beacon request */
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_SSID 0
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_INFO 1 /* Beacon Reporting */
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_DETAIL 2 /* Reporting Detail */
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_REQUEST 10
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL 51 /* AP Channel Report */
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION 164
|
||||||
|
#define WLAN_BEACON_REQUEST_SUBELEM_VENDOR 221
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values
|
||||||
|
*/
|
||||||
|
enum beacon_report_detail {
|
||||||
|
/* No fixed-length fields or elements */
|
||||||
|
BEACON_REPORT_DETAIL_NONE = 0,
|
||||||
|
/* All fixed-length fields and any requested elements in the Request
|
||||||
|
* element if present */
|
||||||
|
BEACON_REPORT_DETAIL_REQUESTED_ONLY = 1,
|
||||||
|
/* All fixed-length fields and elements (default, used when Reporting
|
||||||
|
* Detail subelement is not included in a Beacon request) */
|
||||||
|
BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, 9.4.2.22 - Measurement Report element */
|
||||||
|
struct rrm_measurement_report_element {
|
||||||
|
u8 eid; /* Element ID */
|
||||||
|
u8 len; /* Length */
|
||||||
|
u8 token; /* Measurement Token */
|
||||||
|
u8 mode; /* Measurement Report Mode */
|
||||||
|
u8 type; /* Measurement Type */
|
||||||
|
u8 variable[0]; /* Measurement Report */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */
|
||||||
|
#define MEASUREMENT_REPORT_MODE_ACCEPT 0
|
||||||
|
#define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0)
|
||||||
|
#define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1)
|
||||||
|
#define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2)
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, 9.4.2.22.7 - Beacon report */
|
||||||
|
struct rrm_measurement_beacon_report {
|
||||||
|
u8 op_class; /* Operating Class */
|
||||||
|
u8 channel; /* Channel Number */
|
||||||
|
le64 start_time; /* Actual Measurement Start Time
|
||||||
|
* (in TSF of the BSS requesting the measurement) */
|
||||||
|
le16 duration; /* in TUs */
|
||||||
|
u8 report_info; /* Reported Frame Information */
|
||||||
|
u8 rcpi; /* RCPI */
|
||||||
|
u8 rsni; /* RSNI */
|
||||||
|
u8 bssid[ETH_ALEN]; /* BSSID */
|
||||||
|
u8 antenna_id; /* Antenna ID */
|
||||||
|
le32 parent_tsf; /* Parent TSF */
|
||||||
|
u8 variable[0]; /* Optional Subelements */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */
|
||||||
|
/* IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for
|
||||||
|
* Beacon report */
|
||||||
|
#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY 1
|
||||||
|
#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID 2
|
||||||
|
#define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION 164
|
||||||
|
|
||||||
|
/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the
|
||||||
|
* Reported Frame Body Fragment ID subelement */
|
||||||
|
#define REPORTED_FRAME_BODY_SUBELEM_LEN 4
|
||||||
|
#define REPORTED_FRAME_BODY_MORE_FRAGMENTS BIT(7)
|
||||||
|
|
||||||
|
/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report */
|
||||||
|
#define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN 3
|
||||||
|
|
||||||
|
/* IEEE Std 802.11ac-2013, Annex C - dot11PHYType */
|
||||||
|
enum phy_type {
|
||||||
|
PHY_TYPE_UNSPECIFIED = 0,
|
||||||
|
PHY_TYPE_FHSS = 1,
|
||||||
|
PHY_TYPE_DSSS = 2,
|
||||||
|
PHY_TYPE_IRBASEBAND = 3,
|
||||||
|
PHY_TYPE_OFDM = 4,
|
||||||
|
PHY_TYPE_HRDSSS = 5,
|
||||||
|
PHY_TYPE_ERP = 6,
|
||||||
|
PHY_TYPE_HT = 7,
|
||||||
|
PHY_TYPE_DMG = 8,
|
||||||
|
PHY_TYPE_VHT = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */
|
||||||
|
/* BSSID Information Field */
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
|
||||||
|
#define NEI_REP_BSSID_INFO_AP_REACHABLE (BIT(0) | BIT(1))
|
||||||
|
#define NEI_REP_BSSID_INFO_SECURITY BIT(2)
|
||||||
|
#define NEI_REP_BSSID_INFO_KEY_SCOPE BIT(3)
|
||||||
|
#define NEI_REP_BSSID_INFO_SPECTRUM_MGMT BIT(4)
|
||||||
|
#define NEI_REP_BSSID_INFO_QOS BIT(5)
|
||||||
|
#define NEI_REP_BSSID_INFO_APSD BIT(6)
|
||||||
|
#define NEI_REP_BSSID_INFO_RM BIT(7)
|
||||||
|
#define NEI_REP_BSSID_INFO_DELAYED_BA BIT(8)
|
||||||
|
#define NEI_REP_BSSID_INFO_IMM_BA BIT(9)
|
||||||
|
#define NEI_REP_BSSID_INFO_MOBILITY_DOMAIN BIT(10)
|
||||||
|
#define NEI_REP_BSSID_INFO_HT BIT(11)
|
||||||
|
#define NEI_REP_BSSID_INFO_VHT BIT(12)
|
||||||
|
#define NEI_REP_BSSID_INFO_FTM BIT(13)
|
||||||
|
|
||||||
#endif /* IEEE802_11_DEFS_H */
|
#endif /* IEEE802_11_DEFS_H */
|
||||||
|
1162
components/wpa_supplicant/src/common/rrm.c
Executable file
1162
components/wpa_supplicant/src/common/rrm.c
Executable file
File diff suppressed because it is too large
Load Diff
30
components/wpa_supplicant/src/common/rrm.h
Executable file
30
components/wpa_supplicant/src/common/rrm.h
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
#ifndef RRM_H
|
||||||
|
#define RRM_H
|
||||||
|
|
||||||
|
#include "common/defs.h"
|
||||||
|
#include "utils/list.h"
|
||||||
|
#include "esp_wifi_types.h"
|
||||||
|
#define RRM_NEIGHBOR_REPORT_TIMEOUT 1 /* 1 second for AP to send a report */
|
||||||
|
|
||||||
|
void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
|
||||||
|
void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *report, size_t report_len);
|
||||||
|
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct wpa_ssid_value *ssid,
|
||||||
|
int lci, int civic,
|
||||||
|
void (*cb)(void *ctx,
|
||||||
|
const u8 *neighbor_rep, size_t len),
|
||||||
|
void *cb_ctx);
|
||||||
|
void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *src, const u8 *dst,
|
||||||
|
const u8 *frame, size_t len);
|
||||||
|
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *src,
|
||||||
|
const u8 *frame, size_t len,
|
||||||
|
int rssi);
|
||||||
|
int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
|
||||||
|
u64 scan_start_tsf);
|
||||||
|
void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
#endif
|
95
components/wpa_supplicant/src/common/scan.c
Executable file
95
components/wpa_supplicant/src/common/scan.c
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* WPA Supplicant - Scanning
|
||||||
|
* Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "wpa_supplicant_i.h"
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "common/ieee802_11_common.h"
|
||||||
|
#include "bss.h"
|
||||||
|
#include "scan.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_supplicant_req_scan - Schedule a scan for neighboring access points
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @sec: Number of seconds after which to scan
|
||||||
|
* @usec: Number of microseconds after which to scan
|
||||||
|
*
|
||||||
|
* This function is used to schedule a scan for neighboring access points after
|
||||||
|
* the specified time.
|
||||||
|
*/
|
||||||
|
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct wpa_driver_scan_params *params;
|
||||||
|
|
||||||
|
os_sleep(sec, usec);
|
||||||
|
|
||||||
|
if (wpa_s->scanning) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Return");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params = os_zalloc(sizeof(*params));
|
||||||
|
|
||||||
|
if (wpa_s->wnm_mode) {
|
||||||
|
/* Use the same memory */
|
||||||
|
params->ssids[0].ssid = wpa_s->current_bss->ssid;
|
||||||
|
params->ssids[0].ssid_len = wpa_s->current_bss->ssid_len;
|
||||||
|
params->num_ssids = 1;
|
||||||
|
}
|
||||||
|
if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
|
||||||
|
/* Use the same memory */
|
||||||
|
params->bssid = wpa_s->next_scan_bssid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s->next_scan_chan)
|
||||||
|
params->channel = wpa_s->next_scan_chan;
|
||||||
|
|
||||||
|
wpa_s->scan_reason = REASON_WNM_BSS_TRANS_REQ;
|
||||||
|
ret = wpa_supplicant_trigger_scan(wpa_s, params);
|
||||||
|
|
||||||
|
os_free(params);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "Failed to issue scan - Return");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_scan_get_ie - Fetch a specified information element from a scan result
|
||||||
|
* @res: Scan result entry
|
||||||
|
* @ie: Information element identitifier (WLAN_EID_*)
|
||||||
|
* Returns: Pointer to the information element (id field) or %NULL if not found
|
||||||
|
*
|
||||||
|
* This function returns the first matching information element in the scan
|
||||||
|
* result.
|
||||||
|
*/
|
||||||
|
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
|
||||||
|
{
|
||||||
|
size_t ie_len = res->ie_len;
|
||||||
|
|
||||||
|
/* Use the Beacon frame IEs if res->ie_len is not available */
|
||||||
|
if (!ie_len)
|
||||||
|
ie_len = res->beacon_ie_len;
|
||||||
|
|
||||||
|
return get_ie((const u8 *) (res + 1), ie_len, ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpa_scan_free_params(struct wpa_driver_scan_params *params)
|
||||||
|
{
|
||||||
|
if (params == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
os_free((u8 *) params->bssid);
|
||||||
|
|
||||||
|
os_free(params);
|
||||||
|
}
|
25
components/wpa_supplicant/src/common/scan.h
Executable file
25
components/wpa_supplicant/src/common/scan.h
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* WPA Supplicant - Scanning
|
||||||
|
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCAN_H
|
||||||
|
#define SCAN_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Noise floor values to use when we have signal strength
|
||||||
|
* measurements, but no noise floor measurements. These values were
|
||||||
|
* measured in an office environment with many APs.
|
||||||
|
*/
|
||||||
|
#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
|
||||||
|
|
||||||
|
struct wpa_driver_scan_params;
|
||||||
|
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
|
||||||
|
int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_driver_scan_params *params);
|
||||||
|
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie);
|
||||||
|
void wpa_scan_free_params(struct wpa_driver_scan_params *params);
|
||||||
|
#endif /* SCAN_H */
|
966
components/wpa_supplicant/src/common/wnm_sta.c
Executable file
966
components/wpa_supplicant/src/common/wnm_sta.c
Executable file
@ -0,0 +1,966 @@
|
|||||||
|
/*
|
||||||
|
* wpa_supplicant - WNM
|
||||||
|
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "common/ieee802_11_common.h"
|
||||||
|
#include "rsn_supp/wpa.h"
|
||||||
|
#include "wpa_supplicant_i.h"
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "scan.h"
|
||||||
|
#include "bss.h"
|
||||||
|
#include "wnm_sta.h"
|
||||||
|
|
||||||
|
#define MAX_TFS_IE_LEN 1024
|
||||||
|
#define WNM_MAX_NEIGHBOR_REPORT 10
|
||||||
|
|
||||||
|
#define WNM_SCAN_RESULT_AGE 2 /* 2 seconds */
|
||||||
|
|
||||||
|
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
|
os_free(wpa_s->wnm_neighbor_report_elements[i].meas_pilot);
|
||||||
|
os_free(wpa_s->wnm_neighbor_report_elements[i].mul_bssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_s->wnm_num_neighbor_report = 0;
|
||||||
|
os_free(wpa_s->wnm_neighbor_report_elements);
|
||||||
|
wpa_s->wnm_neighbor_report_elements = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
|
||||||
|
u8 id, u8 elen, const u8 *pos)
|
||||||
|
{
|
||||||
|
switch (id) {
|
||||||
|
case WNM_NEIGHBOR_TSF:
|
||||||
|
if (elen < 2 + 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short TSF");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rep->tsf_offset = WPA_GET_LE16(pos);
|
||||||
|
rep->beacon_int = WPA_GET_LE16(pos + 2);
|
||||||
|
rep->tsf_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING:
|
||||||
|
if (elen < 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short condensed "
|
||||||
|
"country string");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os_memcpy(rep->country, pos, 2);
|
||||||
|
rep->country_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE:
|
||||||
|
if (elen < 1) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short BSS transition "
|
||||||
|
"candidate");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rep->preference = pos[0];
|
||||||
|
rep->preference_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_BSS_TERMINATION_DURATION:
|
||||||
|
if (elen < 10) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Too short BSS termination duration");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rep->bss_term_tsf = WPA_GET_LE64(pos);
|
||||||
|
rep->bss_term_dur = WPA_GET_LE16(pos + 8);
|
||||||
|
rep->bss_term_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_BEARING:
|
||||||
|
if (elen < 8) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short neighbor "
|
||||||
|
"bearing");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rep->bearing = WPA_GET_LE16(pos);
|
||||||
|
rep->distance = WPA_GET_LE32(pos + 2);
|
||||||
|
rep->rel_height = WPA_GET_LE16(pos + 2 + 4);
|
||||||
|
rep->bearing_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_MEASUREMENT_PILOT:
|
||||||
|
if (elen < 1) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short measurement "
|
||||||
|
"pilot");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os_free(rep->meas_pilot);
|
||||||
|
rep->meas_pilot = os_zalloc(sizeof(struct measurement_pilot));
|
||||||
|
if (rep->meas_pilot == NULL)
|
||||||
|
break;
|
||||||
|
rep->meas_pilot->measurement_pilot = pos[0];
|
||||||
|
rep->meas_pilot->subelem_len = elen - 1;
|
||||||
|
os_memcpy(rep->meas_pilot->subelems, pos + 1, elen - 1);
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES:
|
||||||
|
if (elen < 5) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short RRM enabled "
|
||||||
|
"capabilities");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os_memcpy(rep->rm_capab, pos, 5);
|
||||||
|
rep->rm_capab_present = 1;
|
||||||
|
break;
|
||||||
|
case WNM_NEIGHBOR_MULTIPLE_BSSID:
|
||||||
|
if (elen < 1) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short multiple BSSID");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os_free(rep->mul_bssid);
|
||||||
|
rep->mul_bssid = os_zalloc(sizeof(struct multiple_bssid));
|
||||||
|
if (rep->mul_bssid == NULL)
|
||||||
|
break;
|
||||||
|
rep->mul_bssid->max_bssid_indicator = pos[0];
|
||||||
|
rep->mul_bssid->subelem_len = elen - 1;
|
||||||
|
os_memcpy(rep->mul_bssid->subelems, pos + 1, elen - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *pos, u8 len,
|
||||||
|
struct neighbor_report *rep)
|
||||||
|
{
|
||||||
|
u8 left = len;
|
||||||
|
|
||||||
|
if (left < 13) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short neighbor report");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memcpy(rep->bssid, pos, ETH_ALEN);
|
||||||
|
rep->bssid_info = WPA_GET_LE32(pos + ETH_ALEN);
|
||||||
|
rep->regulatory_class = *(pos + 10);
|
||||||
|
rep->channel_number = *(pos + 11);
|
||||||
|
rep->phy_type = *(pos + 12);
|
||||||
|
|
||||||
|
pos += 13;
|
||||||
|
left -= 13;
|
||||||
|
|
||||||
|
while (left >= 2) {
|
||||||
|
u8 id, elen;
|
||||||
|
|
||||||
|
id = *pos++;
|
||||||
|
elen = *pos++;
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Subelement id=%u len=%u", id, elen);
|
||||||
|
left -= 2;
|
||||||
|
if (elen > left) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Truncated neighbor report subelement");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wnm_parse_neighbor_report_elem(rep, id, elen, pos);
|
||||||
|
left -= elen;
|
||||||
|
pos += elen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wnm_clear_acceptable(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++)
|
||||||
|
wpa_s->wnm_neighbor_report_elements[i].acceptable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpa_bss * get_first_acceptable(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct neighbor_report *nei;
|
||||||
|
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
|
nei = &wpa_s->wnm_neighbor_report_elements[i];
|
||||||
|
if (nei->acceptable)
|
||||||
|
return wpa_bss_get_bssid(wpa_s, nei->bssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* basic function to match candidate profile with current bss */
|
||||||
|
bool wpa_scan_res_match(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *current_bss,
|
||||||
|
struct wpa_bss *target_bss)
|
||||||
|
{
|
||||||
|
if (current_bss->ssid_len != target_bss->ssid_len) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: ssid didn't match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (os_memcmp(current_bss->ssid, target_bss->ssid, current_bss->ssid_len) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: ssid didn't match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO security Match */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpa_bss *
|
||||||
|
compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs,
|
||||||
|
enum mbo_transition_reject_reason *reason)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
struct wpa_bss *bss = wpa_s->current_bss;
|
||||||
|
struct wpa_bss *target;
|
||||||
|
|
||||||
|
if (!bss)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wnm_clear_acceptable(wpa_s);
|
||||||
|
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
|
struct neighbor_report *nei;
|
||||||
|
|
||||||
|
nei = &wpa_s->wnm_neighbor_report_elements[i];
|
||||||
|
if (nei->preference_present && nei->preference == 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR,
|
||||||
|
MAC2STR(nei->bssid));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = wpa_bss_get_bssid(wpa_s, nei->bssid);
|
||||||
|
if (!target) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
|
" (pref %d) not found in scan results",
|
||||||
|
MAC2STR(nei->bssid),
|
||||||
|
nei->preference_present ? nei->preference :
|
||||||
|
-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (age_secs) {
|
||||||
|
struct os_reltime now;
|
||||||
|
|
||||||
|
if (os_get_reltime(&now) == 0 &&
|
||||||
|
os_time_expired(&now, &target->last_update,
|
||||||
|
age_secs)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Candidate BSS is more than %ld seconds old",
|
||||||
|
age_secs);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bss->ssid_len != target->ssid_len ||
|
||||||
|
os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) {
|
||||||
|
/*
|
||||||
|
* TODO: Could consider allowing transition to another
|
||||||
|
* ESS if PMF was enabled for the association.
|
||||||
|
*/
|
||||||
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
|
" (pref %d) in different ESS",
|
||||||
|
MAC2STR(nei->bssid),
|
||||||
|
nei->preference_present ? nei->preference :
|
||||||
|
-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s->current_bss &&
|
||||||
|
!wpa_scan_res_match(wpa_s, wpa_s->current_bss, target)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
|
" (pref %d) does not match the current network profile",
|
||||||
|
MAC2STR(nei->bssid),
|
||||||
|
nei->preference_present ? nei->preference :
|
||||||
|
-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->level < bss->level && target->level < -80) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
|
" (pref %d) does not have sufficient signal level (%d)",
|
||||||
|
MAC2STR(nei->bssid),
|
||||||
|
nei->preference_present ? nei->preference :
|
||||||
|
-1,
|
||||||
|
target->level);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nei->acceptable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = get_first_acceptable(wpa_s);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Found an acceptable preferred transition candidate BSS "
|
||||||
|
MACSTR " (RSSI %d)",
|
||||||
|
MAC2STR(target->bssid), target->level);
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_bss_ies_eq(struct wpa_bss *a, struct wpa_bss *b, u8 eid)
|
||||||
|
{
|
||||||
|
const u8 *ie_a, *ie_b;
|
||||||
|
|
||||||
|
if (!a || !b)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ie_a = wpa_bss_get_ie(a, eid);
|
||||||
|
ie_b = wpa_bss_get_ie(b, eid);
|
||||||
|
|
||||||
|
if (!ie_a || !ie_b || ie_a[1] != ie_b[1])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return os_memcmp(ie_a, ie_b, ie_a[1]) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u32 wnm_get_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
|
||||||
|
{
|
||||||
|
u32 info = 0;
|
||||||
|
|
||||||
|
info |= NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Leave the security and key scope bits unset to indicate that the
|
||||||
|
* security information is not available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_SPECTRUM_MGMT)
|
||||||
|
info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_QOS)
|
||||||
|
info |= NEI_REP_BSSID_INFO_QOS;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_APSD)
|
||||||
|
info |= NEI_REP_BSSID_INFO_APSD;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_RADIO_MEASUREMENT)
|
||||||
|
info |= NEI_REP_BSSID_INFO_RM;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_DELAYED_BLOCK_ACK)
|
||||||
|
info |= NEI_REP_BSSID_INFO_DELAYED_BA;
|
||||||
|
if (bss->caps & WLAN_CAPABILITY_IMM_BLOCK_ACK)
|
||||||
|
info |= NEI_REP_BSSID_INFO_IMM_BA;
|
||||||
|
if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_MOBILITY_DOMAIN))
|
||||||
|
info |= NEI_REP_BSSID_INFO_MOBILITY_DOMAIN;
|
||||||
|
if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_HT_CAP))
|
||||||
|
info |= NEI_REP_BSSID_INFO_HT;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wnm_add_nei_rep(struct wpabuf **buf, const u8 *bssid,
|
||||||
|
u32 bss_info, u8 op_class, u8 chan, u8 phy_type,
|
||||||
|
u8 pref)
|
||||||
|
{
|
||||||
|
if (wpabuf_len(*buf) + 18 >
|
||||||
|
IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: No room in frame for Neighbor Report element");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpabuf_resize(buf, 18) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Failed to allocate memory for Neighbor Report element");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_put_u8(*buf, WLAN_EID_NEIGHBOR_REPORT);
|
||||||
|
/* length: 13 for basic neighbor report + 3 for preference subelement */
|
||||||
|
wpabuf_put_u8(*buf, 16);
|
||||||
|
wpabuf_put_data(*buf, bssid, ETH_ALEN);
|
||||||
|
wpabuf_put_le32(*buf, bss_info);
|
||||||
|
wpabuf_put_u8(*buf, op_class);
|
||||||
|
wpabuf_put_u8(*buf, chan);
|
||||||
|
wpabuf_put_u8(*buf, phy_type);
|
||||||
|
wpabuf_put_u8(*buf, WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE);
|
||||||
|
wpabuf_put_u8(*buf, 1);
|
||||||
|
wpabuf_put_u8(*buf, pref);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wnm_nei_rep_add_bss(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, struct wpabuf **buf,
|
||||||
|
u8 pref)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
u8 op_class;
|
||||||
|
int sec_chan = 0;
|
||||||
|
enum phy_type phy_type;
|
||||||
|
u32 info;
|
||||||
|
struct ieee80211_ht_operation *ht_oper = NULL;
|
||||||
|
|
||||||
|
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
|
||||||
|
if (ie && ie[1] >= 2) {
|
||||||
|
ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
|
||||||
|
|
||||||
|
if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||||
|
sec_chan = 1;
|
||||||
|
else if (ht_oper->ht_param &
|
||||||
|
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||||
|
sec_chan = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
op_class = get_operating_class(bss->channel, sec_chan);
|
||||||
|
|
||||||
|
phy_type = (sec_chan != 0) ? PHY_TYPE_HT : PHY_TYPE_ERP;
|
||||||
|
|
||||||
|
info = wnm_get_bss_info(wpa_s, bss);
|
||||||
|
|
||||||
|
return wnm_add_nei_rep(buf, bss->bssid, info, op_class, bss->channel, phy_type,
|
||||||
|
pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wnm_add_cand_list(struct wpa_supplicant *wpa_s, struct wpabuf **buf)
|
||||||
|
{
|
||||||
|
unsigned int i, pref = 255;
|
||||||
|
struct os_reltime now;
|
||||||
|
|
||||||
|
if (!wpa_s->current_bss)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Define when scan results are no longer valid for the candidate
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
os_get_reltime(&now);
|
||||||
|
if (os_time_expired(&now, &wpa_s->last_scan, 10))
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Add candidate list to BSS Transition Management Response frame");
|
||||||
|
for (i = 0; i < wpa_s->last_scan_res_used && pref; i++) {
|
||||||
|
struct wpa_bss *bss = wpa_s->last_scan_res[i];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (wpa_scan_res_match(wpa_s, wpa_s->current_bss, bss)) {
|
||||||
|
res = wnm_nei_rep_add_bss(wpa_s, bss, buf, pref--);
|
||||||
|
if (res == -2)
|
||||||
|
continue; /* could not build entry for BSS */
|
||||||
|
if (res < 0)
|
||||||
|
break; /* no more room for candidates */
|
||||||
|
if (pref == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
|
"WNM: BSS Transition Management Response candidate list",
|
||||||
|
*buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define BTM_RESP_MIN_SIZE 5 + ETH_ALEN
|
||||||
|
|
||||||
|
static void wnm_send_bss_transition_mgmt_resp(
|
||||||
|
struct wpa_supplicant *wpa_s, u8 dialog_token,
|
||||||
|
enum bss_trans_mgmt_status_code status,
|
||||||
|
enum mbo_transition_reject_reason reason,
|
||||||
|
u8 delay, const u8 *target_bssid)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Send BSS Transition Management Response to " MACSTR
|
||||||
|
" dialog_token=%u status=%u reason=%u delay=%d",
|
||||||
|
MAC2STR(wpa_s->current_bss->bssid), dialog_token, status, reason, delay);
|
||||||
|
if (!wpa_s->current_bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Current BSS not known - drop response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(BTM_RESP_MIN_SIZE);
|
||||||
|
if (!buf) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Failed to allocate memory for BTM response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
|
||||||
|
wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_RESP);
|
||||||
|
wpabuf_put_u8(buf, dialog_token);
|
||||||
|
wpabuf_put_u8(buf, status);
|
||||||
|
wpabuf_put_u8(buf, delay);
|
||||||
|
if (target_bssid) {
|
||||||
|
wpabuf_put_data(buf, target_bssid, ETH_ALEN);
|
||||||
|
} else if (status == WNM_BSS_TM_ACCEPT) {
|
||||||
|
/*
|
||||||
|
* P802.11-REVmc clarifies that the Target BSSID field is always
|
||||||
|
* present when status code is zero, so use a fake value here if
|
||||||
|
* no BSSID is yet known.
|
||||||
|
*/
|
||||||
|
wpabuf_put_data(buf, "\0\0\0\0\0\0", ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == WNM_BSS_TM_ACCEPT)
|
||||||
|
wnm_add_cand_list(wpa_s, &buf);
|
||||||
|
|
||||||
|
res = wpa_drv_send_action(wpa_s, 0, 0,
|
||||||
|
wpabuf_head_u8(buf), wpabuf_len(buf), 0);
|
||||||
|
if (res < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Failed to send BSS Transition Management Response");
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, char *ssid,
|
||||||
|
int after_new_scan)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Transition to BSS " MACSTR
|
||||||
|
" based on BSS Transition Management Request after_new_scan=%d)",
|
||||||
|
MAC2STR(bss->bssid), after_new_scan);
|
||||||
|
|
||||||
|
/* Send the BSS Management Response - Accept */
|
||||||
|
if (wpa_s->wnm_reply) {
|
||||||
|
wpa_s->wnm_reply = 0;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Sending successful BSS Transition Management Response");
|
||||||
|
wnm_send_bss_transition_mgmt_resp(
|
||||||
|
wpa_s, wpa_s->wnm_dialog_token, WNM_BSS_TM_ACCEPT,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
|
||||||
|
bss->bssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bss == wpa_s->current_bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Already associated with the preferred candidate");
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Issuing connect");
|
||||||
|
|
||||||
|
wpa_supplicant_connect(wpa_s, bss, ssid);
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;
|
||||||
|
enum mbo_transition_reject_reason reason =
|
||||||
|
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
|
||||||
|
|
||||||
|
if (!wpa_s->wnm_neighbor_report_elements)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"WNM: Process scan results for BSS Transition Management");
|
||||||
|
if (os_reltime_before(&wpa_s->wnm_cand_valid_until,
|
||||||
|
&wpa_s->scan_trigger_time)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Previously stored BSS transition candidate list is not valid anymore - drop it");
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the Neighbor Report and scan results */
|
||||||
|
bss = compare_scan_neighbor_results(wpa_s, 0, &reason);
|
||||||
|
if (!bss) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
|
||||||
|
status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
|
||||||
|
goto send_bss_resp_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Associate to the network */
|
||||||
|
wnm_bss_tm_connect(wpa_s, bss, NULL, 1);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
send_bss_resp_fail:
|
||||||
|
if (!reply_on_fail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Send reject response for all the failures */
|
||||||
|
|
||||||
|
if (wpa_s->wnm_reply) {
|
||||||
|
wpa_s->wnm_reply = 0;
|
||||||
|
wnm_send_bss_transition_mgmt_resp(wpa_s,
|
||||||
|
wpa_s->wnm_dialog_token,
|
||||||
|
status, reason, 0, NULL);
|
||||||
|
}
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cand_pref_compar(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct neighbor_report *aa = a;
|
||||||
|
const struct neighbor_report *bb = b;
|
||||||
|
|
||||||
|
if (!aa->preference_present && !bb->preference_present)
|
||||||
|
return 0;
|
||||||
|
if (!aa->preference_present)
|
||||||
|
return 1;
|
||||||
|
if (!bb->preference_present)
|
||||||
|
return -1;
|
||||||
|
if (bb->preference > aa->preference)
|
||||||
|
return 1;
|
||||||
|
if (bb->preference < aa->preference)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wnm_sort_cand_list(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (!wpa_s->wnm_neighbor_report_elements)
|
||||||
|
return;
|
||||||
|
qsort(wpa_s->wnm_neighbor_report_elements,
|
||||||
|
wpa_s->wnm_num_neighbor_report, sizeof(struct neighbor_report),
|
||||||
|
cand_pref_compar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wnm_dump_cand_list(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_PRINT
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Candidate List");
|
||||||
|
if (!wpa_s->wnm_neighbor_report_elements)
|
||||||
|
return;
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
|
struct neighbor_report *nei;
|
||||||
|
|
||||||
|
nei = &wpa_s->wnm_neighbor_report_elements[i];
|
||||||
|
wpa_printf(MSG_DEBUG, "%u: " MACSTR
|
||||||
|
" info=0x%x op_class=%u chan=%u phy=%u pref=%d",
|
||||||
|
i, MAC2STR(nei->bssid), nei->bssid_info,
|
||||||
|
nei->regulatory_class,
|
||||||
|
nei->channel_number, nei->phy_type,
|
||||||
|
nei->preference_present ? nei->preference : -1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wnm_set_scan_freqs(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int num_chan;
|
||||||
|
u8 chan = 0;
|
||||||
|
|
||||||
|
wpa_s->next_scan_chan = 0;
|
||||||
|
if (!wpa_s->wnm_neighbor_report_elements)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
|
struct neighbor_report *nei;
|
||||||
|
|
||||||
|
nei = &wpa_s->wnm_neighbor_report_elements[i];
|
||||||
|
if (nei->channel_number <= 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Unknown neighbor operating channel_number for "
|
||||||
|
MACSTR " - scan all channels",
|
||||||
|
MAC2STR(nei->bssid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nei->channel_number != chan)
|
||||||
|
num_chan++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_chan == 1) {
|
||||||
|
wpa_s->next_scan_chan = chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
/* ESP doesn't support this */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *pos, const u8 *end,
|
||||||
|
int reply)
|
||||||
|
{
|
||||||
|
unsigned int beacon_int;
|
||||||
|
u8 valid_int;
|
||||||
|
|
||||||
|
if (wpa_s->disable_btm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (end - pos < 5)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MBO
|
||||||
|
wpa_s->wnm_mbo_trans_reason_present = 0;
|
||||||
|
wpa_s->wnm_mbo_transition_reason = 0;
|
||||||
|
#endif /* CONFIG_MBO */
|
||||||
|
|
||||||
|
if (wpa_s->current_bss)
|
||||||
|
beacon_int = wpa_s->current_bss->beacon_int;
|
||||||
|
else
|
||||||
|
beacon_int = 100; /* best guess */
|
||||||
|
|
||||||
|
wpa_s->wnm_dialog_token = pos[0];
|
||||||
|
wpa_s->wnm_mode = pos[1];
|
||||||
|
wpa_s->wnm_dissoc_timer = WPA_GET_LE16(pos + 2);
|
||||||
|
valid_int = pos[4];
|
||||||
|
wpa_s->wnm_reply = reply;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Request: "
|
||||||
|
"dialog_token=%u request_mode=0x%x "
|
||||||
|
"disassoc_timer=%u validity_interval=%u",
|
||||||
|
wpa_s->wnm_dialog_token, wpa_s->wnm_mode,
|
||||||
|
wpa_s->wnm_dissoc_timer, valid_int);
|
||||||
|
|
||||||
|
pos += 5;
|
||||||
|
|
||||||
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
|
||||||
|
if (end - pos < 12) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Too short BSS TM Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
os_memcpy(wpa_s->wnm_bss_termination_duration, pos, 12);
|
||||||
|
pos += 12; /* BSS Termination Duration */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
|
||||||
|
char url[256];
|
||||||
|
|
||||||
|
if (end - pos < 1 || 1 + pos[0] > end - pos) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Invalid BSS Transition "
|
||||||
|
"Management Request (URL)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
os_memcpy(url, pos + 1, pos[0]);
|
||||||
|
url[pos[0]] = '\0';
|
||||||
|
pos += 1 + pos[0];
|
||||||
|
|
||||||
|
wpa_msg(wpa_s, MSG_DEBUG, "ESS_DISASSOC_IMMINENT %u %s",
|
||||||
|
wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
|
||||||
|
wpa_msg(wpa_s, MSG_DEBUG, "WNM: Disassociation Imminent - "
|
||||||
|
"Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
|
||||||
|
if (wpa_s->wnm_dissoc_timer) {
|
||||||
|
/* TODO: mark current BSS less preferred for
|
||||||
|
* selection */
|
||||||
|
wpa_printf(MSG_DEBUG, "Trying to find another BSS");
|
||||||
|
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MBO
|
||||||
|
vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
|
||||||
|
if (vendor)
|
||||||
|
wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
|
||||||
|
#endif /* CONFIG_MBO */
|
||||||
|
|
||||||
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
|
||||||
|
unsigned int valid_ms;
|
||||||
|
|
||||||
|
wpa_msg(wpa_s, MSG_DEBUG, "WNM: Preferred List Available");
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
wpa_s->wnm_neighbor_report_elements = os_calloc(
|
||||||
|
WNM_MAX_NEIGHBOR_REPORT,
|
||||||
|
sizeof(struct neighbor_report));
|
||||||
|
if (wpa_s->wnm_neighbor_report_elements == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (end - pos >= 2 &&
|
||||||
|
wpa_s->wnm_num_neighbor_report < WNM_MAX_NEIGHBOR_REPORT)
|
||||||
|
{
|
||||||
|
u8 tag = *pos++;
|
||||||
|
u8 len = *pos++;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Neighbor report tag %u",
|
||||||
|
tag);
|
||||||
|
if (len > end - pos) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Truncated request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tag == WLAN_EID_NEIGHBOR_REPORT) {
|
||||||
|
struct neighbor_report *rep;
|
||||||
|
rep = &wpa_s->wnm_neighbor_report_elements[
|
||||||
|
wpa_s->wnm_num_neighbor_report];
|
||||||
|
wnm_parse_neighbor_report(wpa_s, pos, len, rep);
|
||||||
|
wpa_s->wnm_num_neighbor_report++;
|
||||||
|
#ifdef CONFIG_MBO
|
||||||
|
if (wpa_s->wnm_mbo_trans_reason_present &&
|
||||||
|
wpa_s->wnm_num_neighbor_report == 1) {
|
||||||
|
rep->is_first = 1;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: First transition candidate is "
|
||||||
|
MACSTR, MAC2STR(rep->bssid));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBO */
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wpa_s->wnm_num_neighbor_report) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Candidate list included bit is set, but no candidates found");
|
||||||
|
wnm_send_bss_transition_mgmt_resp(
|
||||||
|
wpa_s, wpa_s->wnm_dialog_token,
|
||||||
|
WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0,
|
||||||
|
NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wnm_sort_cand_list(wpa_s);
|
||||||
|
wnm_dump_cand_list(wpa_s);
|
||||||
|
valid_ms = valid_int * beacon_int * 128 / 125;
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Candidate list valid for %u ms",
|
||||||
|
valid_ms);
|
||||||
|
os_get_reltime(&wpa_s->wnm_cand_valid_until);
|
||||||
|
wpa_s->wnm_cand_valid_until.sec += valid_ms / 1000;
|
||||||
|
wpa_s->wnm_cand_valid_until.usec += (valid_ms % 1000) * 1000;
|
||||||
|
wpa_s->wnm_cand_valid_until.sec +=
|
||||||
|
wpa_s->wnm_cand_valid_until.usec / 1000000;
|
||||||
|
wpa_s->wnm_cand_valid_until.usec %= 1000000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch the latest scan results from the kernel and check for
|
||||||
|
* candidates based on those results first. This can help in
|
||||||
|
* finding more up-to-date information should the driver has
|
||||||
|
* done some internal scanning operations after the last scan
|
||||||
|
* result update in wpa_supplicant.
|
||||||
|
*/
|
||||||
|
if (wnm_fetch_scan_results(wpa_s) > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to use previously received scan results, if they are
|
||||||
|
* recent enough to use for a connection.
|
||||||
|
*/
|
||||||
|
if (wpa_s->last_scan_res_used > 0) {
|
||||||
|
struct os_reltime now;
|
||||||
|
|
||||||
|
os_get_reltime(&now);
|
||||||
|
if (!os_time_expired(&now, &wpa_s->last_scan, 10)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Try to use recent scan results");
|
||||||
|
if (wnm_scan_process(wpa_s, 0) > 0)
|
||||||
|
return;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: No match in previous scan results - try a new scan");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wnm_set_scan_freqs(wpa_s);
|
||||||
|
if (wpa_s->wnm_num_neighbor_report == 1) {
|
||||||
|
os_memcpy(wpa_s->next_scan_bssid,
|
||||||
|
wpa_s->wnm_neighbor_report_elements[0].bssid,
|
||||||
|
ETH_ALEN);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Scan only for a specific BSSID since there is only a single candidate "
|
||||||
|
MACSTR, MAC2STR(wpa_s->next_scan_bssid));
|
||||||
|
}
|
||||||
|
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||||
|
} else if (reply) {
|
||||||
|
enum bss_trans_mgmt_status_code status;
|
||||||
|
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT)
|
||||||
|
status = WNM_BSS_TM_ACCEPT;
|
||||||
|
else {
|
||||||
|
wpa_msg(wpa_s, MSG_DEBUG, "WNM: BSS Transition Management Request did not include candidates");
|
||||||
|
status = WNM_BSS_TM_REJECT_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
wpa_s->wnm_reply = 0;
|
||||||
|
wnm_send_bss_transition_mgmt_resp(
|
||||||
|
wpa_s, wpa_s->wnm_dialog_token, status,
|
||||||
|
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define BTM_QUERY_MIN_SIZE 4
|
||||||
|
|
||||||
|
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 query_reason,
|
||||||
|
const char *btm_candidates,
|
||||||
|
int cand_list)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Query to "
|
||||||
|
MACSTR " query_reason=%u%s",
|
||||||
|
MAC2STR(wpa_s->current_bss->bssid), query_reason,
|
||||||
|
cand_list ? " candidate list" : "");
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(BTM_QUERY_MIN_SIZE);
|
||||||
|
if (!buf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
|
||||||
|
wpabuf_put_u8(buf, WNM_BSS_TRANS_MGMT_QUERY);
|
||||||
|
wpabuf_put_u8(buf, 1);
|
||||||
|
wpabuf_put_u8(buf, query_reason);
|
||||||
|
|
||||||
|
if (cand_list)
|
||||||
|
wnm_add_cand_list(wpa_s, &buf);
|
||||||
|
|
||||||
|
if (btm_candidates) {
|
||||||
|
const size_t max_len = 1000;
|
||||||
|
|
||||||
|
ret = wpabuf_resize(&buf, max_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ieee802_11_parse_candidate_list(btm_candidates,
|
||||||
|
wpabuf_put(buf, 0),
|
||||||
|
max_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_put(buf, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wpa_drv_send_action(wpa_s, 0, 0,
|
||||||
|
wpabuf_head_u8(buf), wpabuf_len(buf), 0);
|
||||||
|
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 *sender, u8 *payload, size_t len)
|
||||||
|
{
|
||||||
|
const u8 *pos, *end;
|
||||||
|
u8 act;
|
||||||
|
|
||||||
|
if (len < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos = payload;
|
||||||
|
act = *pos++;
|
||||||
|
end = payload + len;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
|
||||||
|
act, MAC2STR(sender));
|
||||||
|
|
||||||
|
switch (act) {
|
||||||
|
case WNM_BSS_TRANS_MGMT_REQ:
|
||||||
|
ieee802_11_rx_bss_trans_mgmt_req(wpa_s, pos, end,
|
||||||
|
!(sender[0] & 0x01));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wpa_printf(MSG_ERROR, "WNM: Unknown request");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
70
components/wpa_supplicant/src/common/wnm_sta.h
Executable file
70
components/wpa_supplicant/src/common/wnm_sta.h
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* IEEE 802.11v WNM related functions and structures
|
||||||
|
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WNM_STA_H
|
||||||
|
#define WNM_STA_H
|
||||||
|
|
||||||
|
struct measurement_pilot {
|
||||||
|
u8 measurement_pilot;
|
||||||
|
u8 subelem_len;
|
||||||
|
u8 subelems[255];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiple_bssid {
|
||||||
|
u8 max_bssid_indicator;
|
||||||
|
u8 subelem_len;
|
||||||
|
u8 subelems[255];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct neighbor_report {
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u32 bssid_info;
|
||||||
|
u8 regulatory_class;
|
||||||
|
u8 channel_number;
|
||||||
|
u8 phy_type;
|
||||||
|
u8 preference; /* valid if preference_present=1 */
|
||||||
|
u16 tsf_offset; /* valid if tsf_present=1 */
|
||||||
|
u16 beacon_int; /* valid if tsf_present=1 */
|
||||||
|
char country[2]; /* valid if country_present=1 */
|
||||||
|
u8 rm_capab[5]; /* valid if rm_capab_present=1 */
|
||||||
|
u16 bearing; /* valid if bearing_present=1 */
|
||||||
|
u16 rel_height; /* valid if bearing_present=1 */
|
||||||
|
u32 distance; /* valid if bearing_present=1 */
|
||||||
|
u64 bss_term_tsf; /* valid if bss_term_present=1 */
|
||||||
|
u16 bss_term_dur; /* valid if bss_term_present=1 */
|
||||||
|
unsigned int preference_present:1;
|
||||||
|
unsigned int tsf_present:1;
|
||||||
|
unsigned int country_present:1;
|
||||||
|
unsigned int rm_capab_present:1;
|
||||||
|
unsigned int bearing_present:1;
|
||||||
|
unsigned int bss_term_present:1;
|
||||||
|
unsigned int acceptable:1;
|
||||||
|
struct measurement_pilot *meas_pilot;
|
||||||
|
struct multiple_bssid *mul_bssid;
|
||||||
|
int freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 action, u16 intval, struct wpabuf *tfs_req);
|
||||||
|
|
||||||
|
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 *sender, u8 *payload, size_t len);
|
||||||
|
|
||||||
|
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 query_reason,
|
||||||
|
const char *btm_candidates,
|
||||||
|
int cand_list);
|
||||||
|
|
||||||
|
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
|
||||||
|
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
|
||||||
|
void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, char *ssid,
|
||||||
|
int after_new_scan);
|
||||||
|
|
||||||
|
#endif /* WNM_STA_H */
|
110
components/wpa_supplicant/src/common/wpa_supplicant_i.h
Executable file
110
components/wpa_supplicant/src/common/wpa_supplicant_i.h
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* wpa_supplicant - Internal definitions
|
||||||
|
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WPA_SUPPLICANT_I_H
|
||||||
|
#define WPA_SUPPLICANT_I_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
/*
|
||||||
|
* struct rrm_data - Data used for managing RRM features
|
||||||
|
*/
|
||||||
|
struct rrm_data {
|
||||||
|
/* rrm_used - indication regarding the current connection */
|
||||||
|
unsigned int rrm_used:1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* notify_neighbor_rep - Callback for notifying report requester
|
||||||
|
*/
|
||||||
|
void (*notify_neighbor_rep)(void *ctx, const u8 *neighbor_rep, size_t len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* neighbor_rep_cb_ctx - Callback context
|
||||||
|
* Received in the callback registration, and sent to the callback
|
||||||
|
* function as a parameter.
|
||||||
|
*/
|
||||||
|
void *neighbor_rep_cb_ctx;
|
||||||
|
|
||||||
|
/* next_neighbor_rep_token - Next request's dialog token */
|
||||||
|
u8 next_neighbor_rep_token;
|
||||||
|
|
||||||
|
/* token - Dialog token of the current radio measurement */
|
||||||
|
u8 token;
|
||||||
|
|
||||||
|
/* destination address of the current radio measurement request */
|
||||||
|
u8 dst_addr[ETH_ALEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SSID_MAX_LEN 32
|
||||||
|
struct beacon_rep_data {
|
||||||
|
u8 token;
|
||||||
|
u8 last_indication;
|
||||||
|
struct wpa_driver_scan_params scan_params;
|
||||||
|
u8 ssid[SSID_MAX_LEN];
|
||||||
|
size_t ssid_len;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
enum beacon_report_detail report_detail;
|
||||||
|
struct bitfield *eids;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum scan_trigger_reason {
|
||||||
|
REASON_INVALID,
|
||||||
|
REASON_RRM_BEACON_REPORT,
|
||||||
|
REASON_WNM_BSS_TRANS_REQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wpa_supplicant {
|
||||||
|
int disable_btm;
|
||||||
|
/* rrm ie */
|
||||||
|
uint8_t rrm_ie[5];
|
||||||
|
u8 extend_caps[8];
|
||||||
|
|
||||||
|
int scanning;
|
||||||
|
enum scan_trigger_reason scan_reason;
|
||||||
|
u64 scan_start_tsf;
|
||||||
|
u8 tsf_bssid[ETH_ALEN];
|
||||||
|
struct wpa_bss *current_bss;
|
||||||
|
|
||||||
|
struct dl_list bss; /* struct wpa_bss::list */
|
||||||
|
struct dl_list bss_id; /* struct wpa_bss::list_id */
|
||||||
|
size_t num_bss;
|
||||||
|
unsigned int bss_update_idx;
|
||||||
|
unsigned int bss_next_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointers to BSS entries in the order they were in the last scan
|
||||||
|
* results.
|
||||||
|
*/
|
||||||
|
struct wpa_bss **last_scan_res;
|
||||||
|
unsigned int last_scan_res_used;
|
||||||
|
unsigned int last_scan_res_size;
|
||||||
|
struct os_reltime last_scan;
|
||||||
|
|
||||||
|
struct os_reltime scan_trigger_time, scan_start_time;
|
||||||
|
|
||||||
|
u8 next_scan_bssid[ETH_ALEN];
|
||||||
|
/* type and subtype of frames for which supplicant has registered */
|
||||||
|
uint32_t type, subtype;
|
||||||
|
u8 next_scan_chan;
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
u8 wnm_dialog_token;
|
||||||
|
u8 wnm_reply;
|
||||||
|
u8 wnm_num_neighbor_report;
|
||||||
|
u8 wnm_mode;
|
||||||
|
u16 wnm_dissoc_timer;
|
||||||
|
u8 wnm_bss_termination_duration[12];
|
||||||
|
struct neighbor_report *wnm_neighbor_report_elements;
|
||||||
|
struct os_reltime wnm_cand_valid_until;
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
struct rrm_data rrm;
|
||||||
|
struct beacon_rep_data beacon_rep_data;
|
||||||
|
struct os_reltime beacon_rep_scan;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
187
components/wpa_supplicant/src/drivers/driver.h
Executable file
187
components/wpa_supplicant/src/drivers/driver.h
Executable file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* Driver interface definition
|
||||||
|
* Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*
|
||||||
|
* This file defines a driver interface used by both %wpa_supplicant and
|
||||||
|
* hostapd. The first part of the file defines data structures used in various
|
||||||
|
* driver operations. This is followed by the struct wpa_driver_ops that each
|
||||||
|
* driver wrapper will beed to define with callback functions for requesting
|
||||||
|
* driver operations. After this, there are definitions for driver event
|
||||||
|
* reporting with wpa_supplicant_event() and some convenience helper functions
|
||||||
|
* that can be used to report events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRIVER_H
|
||||||
|
#define DRIVER_H
|
||||||
|
|
||||||
|
#define WPA_SUPPLICANT_DRIVER_VERSION 4
|
||||||
|
|
||||||
|
#include "common/defs.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "common/wpa_common.h"
|
||||||
|
#include "utils/list.h"
|
||||||
|
struct wpa_bss;
|
||||||
|
struct wpa_supplicant;
|
||||||
|
/**
|
||||||
|
* struct wpa_scan_res - Scan result for an BSS/IBSS
|
||||||
|
* @flags: information flags about the BSS/IBSS (WPA_SCAN_*)
|
||||||
|
* @bssid: BSSID
|
||||||
|
* @freq: frequency of the channel in MHz (e.g., 2412 = channel 1)
|
||||||
|
* @beacon_int: beacon interval in TUs (host byte order)
|
||||||
|
* @caps: capability information field in host byte order
|
||||||
|
* @qual: signal quality
|
||||||
|
* @noise: noise level
|
||||||
|
* @level: signal level
|
||||||
|
* @tsf: Timestamp
|
||||||
|
* @age: Age of the information in milliseconds (i.e., how many milliseconds
|
||||||
|
* ago the last Beacon or Probe Response frame was received)
|
||||||
|
* @snr: Signal-to-noise ratio in dB (calculated during scan result processing)
|
||||||
|
* @parent_tsf: Time when the Beacon/Probe Response frame was received in terms
|
||||||
|
* of TSF of the BSS specified by %tsf_bssid.
|
||||||
|
* @tsf_bssid: The BSS that %parent_tsf TSF time refers to.
|
||||||
|
* @ie_len: length of the following IE field in octets
|
||||||
|
* @beacon_ie_len: length of the following Beacon IE field in octets
|
||||||
|
*
|
||||||
|
* This structure is used as a generic format for scan results from the
|
||||||
|
* driver. Each driver interface implementation is responsible for converting
|
||||||
|
* the driver or OS specific scan results into this format.
|
||||||
|
*
|
||||||
|
* If the driver does not support reporting all IEs, the IE data structure is
|
||||||
|
* constructed of the IEs that are available. This field will also need to
|
||||||
|
* include SSID in IE format. All drivers are encouraged to be extended to
|
||||||
|
* report all IEs to make it easier to support future additions.
|
||||||
|
*
|
||||||
|
* This structure data is followed by ie_len octets of IEs from Probe Response
|
||||||
|
* frame (or if the driver does not indicate source of IEs, these may also be
|
||||||
|
* from Beacon frame). After the first set of IEs, another set of IEs may follow
|
||||||
|
* (with beacon_ie_len octets of data) if the driver provides both IE sets.
|
||||||
|
*/
|
||||||
|
struct wpa_scan_res {
|
||||||
|
unsigned int flags;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
int chan;
|
||||||
|
u16 beacon_int;
|
||||||
|
u16 caps;
|
||||||
|
int noise;
|
||||||
|
int level;
|
||||||
|
u64 tsf;
|
||||||
|
unsigned int age;
|
||||||
|
u64 parent_tsf;
|
||||||
|
u8 tsf_bssid[ETH_ALEN];
|
||||||
|
size_t ie_len;
|
||||||
|
size_t beacon_ie_len;
|
||||||
|
/* Followed by ie_len + beacon_ie_len octets of IE data */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_scan_results - Scan results
|
||||||
|
* @res: Array of pointers to allocated variable length scan result entries
|
||||||
|
* @num: Number of entries in the scan result array
|
||||||
|
* @fetch_time: Time when the results were fetched from the driver
|
||||||
|
*/
|
||||||
|
struct wpa_scan_results {
|
||||||
|
struct wpa_scan_res **res;
|
||||||
|
size_t num;
|
||||||
|
struct os_reltime fetch_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WPAS_MAX_SCAN_SSIDS 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_driver_scan_ssid - SSIDs to scan for
|
||||||
|
* @ssid - specific SSID to scan for (ProbeReq)
|
||||||
|
* %NULL or zero-length SSID is used to indicate active scan
|
||||||
|
* with wildcard SSID.
|
||||||
|
* @ssid_len - Length of the SSID in octets
|
||||||
|
*/
|
||||||
|
struct wpa_driver_scan_ssid {
|
||||||
|
const u8 *ssid;
|
||||||
|
size_t ssid_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_driver_scan_params - Scan parameters
|
||||||
|
* Data for struct wpa_driver_ops::scan2().
|
||||||
|
*/
|
||||||
|
struct wpa_driver_scan_params {
|
||||||
|
/**
|
||||||
|
* ssids - SSIDs to scan for
|
||||||
|
*/
|
||||||
|
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* num_ssids - Number of entries in ssids array
|
||||||
|
* Zero indicates a request for a passive scan.
|
||||||
|
*/
|
||||||
|
size_t num_ssids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* freqs - Array of frequencies to scan or %NULL for all frequencies
|
||||||
|
*
|
||||||
|
* The frequency is set in MHz. The array is zero-terminated.
|
||||||
|
*/
|
||||||
|
int channel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bssid - Specific BSSID to scan for
|
||||||
|
*
|
||||||
|
* This optional parameter can be used to replace the default wildcard
|
||||||
|
* BSSID with a specific BSSID to scan for if results are needed from
|
||||||
|
* only a single BSS.
|
||||||
|
*/
|
||||||
|
const u8 *bssid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* duration - Dwell time on each channel
|
||||||
|
*
|
||||||
|
* This optional parameter can be used to set the dwell time on each
|
||||||
|
* channel. In TUs.
|
||||||
|
*/
|
||||||
|
u16 duration;
|
||||||
|
|
||||||
|
unsigned int duration_mandatory;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct scan_info - Optional data for EVENT_SCAN_RESULTS events
|
||||||
|
* @aborted: Whether the scan was aborted
|
||||||
|
* @freqs: Scanned frequencies in MHz (%NULL = all channels scanned)
|
||||||
|
* @num_freqs: Number of entries in freqs array
|
||||||
|
* @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard
|
||||||
|
* SSID)
|
||||||
|
* @num_ssids: Number of entries in ssids array
|
||||||
|
* @external_scan: Whether the scan info is for an external scan
|
||||||
|
* @nl_scan_event: 1 if the source of this scan event is a normal scan,
|
||||||
|
* 0 if the source of the scan event is a vendor scan
|
||||||
|
* @scan_start_tsf: Time when the scan started in terms of TSF of the
|
||||||
|
* BSS that the interface that requested the scan is connected to
|
||||||
|
* (if available).
|
||||||
|
* @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf
|
||||||
|
* is set.
|
||||||
|
*/
|
||||||
|
struct scan_info {
|
||||||
|
int aborted;
|
||||||
|
const int *freqs;
|
||||||
|
size_t num_freqs;
|
||||||
|
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
|
||||||
|
size_t num_ssids;
|
||||||
|
int external_scan;
|
||||||
|
int nl_scan_event;
|
||||||
|
u64 scan_start_tsf;
|
||||||
|
u8 scan_start_tsf_bssid[ETH_ALEN];
|
||||||
|
} scan_info;
|
||||||
|
|
||||||
|
|
||||||
|
/* driver_common.c */
|
||||||
|
void wpa_scan_results_free(struct wpa_scan_results *res);
|
||||||
|
|
||||||
|
int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
|
||||||
|
unsigned int chan, unsigned int wait,
|
||||||
|
const u8 *data, size_t data_len, int no_cck);
|
||||||
|
|
||||||
|
void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, char *ssid);
|
||||||
|
#endif /* DRIVER_H */
|
17
components/wpa_supplicant/src/eap_peer/chap.h
Executable file
17
components/wpa_supplicant/src/eap_peer/chap.h
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* CHAP-MD5 (RFC 1994)
|
||||||
|
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CHAP_H
|
||||||
|
#define CHAP_H
|
||||||
|
|
||||||
|
#define CHAP_MD5_LEN 16
|
||||||
|
|
||||||
|
int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
|
||||||
|
size_t challenge_len, u8 *response);
|
||||||
|
|
||||||
|
#endif /* CHAP_H */
|
403
components/wpa_supplicant/src/esp_supplicant/esp_common.c
Executable file
403
components/wpa_supplicant/src/esp_supplicant/esp_common.c
Executable file
@ -0,0 +1,403 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_wifi_types.h"
|
||||||
|
#include "esp_wifi_driver.h"
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "common/bss.h"
|
||||||
|
#include "common/rrm.h"
|
||||||
|
#include "common/wnm_sta.h"
|
||||||
|
#include "common/wpa_supplicant_i.h"
|
||||||
|
#include "esp_supplicant/esp_scan_i.h"
|
||||||
|
#include "esp_supplicant/esp_common_i.h"
|
||||||
|
#include "common/ieee802_11_common.h"
|
||||||
|
#include "esp_rrm.h"
|
||||||
|
#include "esp_wnm.h"
|
||||||
|
|
||||||
|
struct wpa_supplicant g_wpa_supp;
|
||||||
|
|
||||||
|
static void *s_supplicant_task_hdl = NULL;
|
||||||
|
static void *s_supplicant_evt_queue = NULL;
|
||||||
|
static void *s_supplicant_api_lock = NULL;
|
||||||
|
|
||||||
|
static int esp_handle_action_frm(u8 *frame, size_t len,
|
||||||
|
u8 *sender, u32 rssi, u8 channel)
|
||||||
|
{
|
||||||
|
struct ieee_mgmt_frame *frm = os_malloc(sizeof(struct ieee_mgmt_frame) + len);
|
||||||
|
|
||||||
|
if (!frm) {
|
||||||
|
wpa_printf(MSG_ERROR, "memory allocation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memcpy(frm->sender, sender, ETH_ALEN);
|
||||||
|
frm->len = len;
|
||||||
|
frm->channel = channel;
|
||||||
|
frm->rssi = rssi;
|
||||||
|
|
||||||
|
os_memcpy(frm->payload, frame, len);
|
||||||
|
if (esp_supplicant_post_evt(SIG_SUPPLICANT_RX_ACTION, (u32)frm) != 0) {
|
||||||
|
os_free(frm);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
|
||||||
|
u8 *payload, size_t len, u32 rssi)
|
||||||
|
{
|
||||||
|
if (payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) {
|
||||||
|
/* neighbor report parsing */
|
||||||
|
wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, len - 1);
|
||||||
|
} else if (payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
|
||||||
|
/* Beacon measurement */
|
||||||
|
wpas_rrm_handle_radio_measurement_request(wpa_s, NULL,
|
||||||
|
sender, payload + 1, len - 1);
|
||||||
|
} else if (payload[0] == WLAN_RRM_LINK_MEASUREMENT_REQUEST) {
|
||||||
|
/* Link measurement */
|
||||||
|
wpas_rrm_handle_link_measurement_request(wpa_s, NULL,
|
||||||
|
payload + 1, len - 1, rssi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int esp_mgmt_rx_action(u8 *sender, u8 *payload, size_t len, u8 channel, u32 rssi)
|
||||||
|
{
|
||||||
|
u8 category;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
int ret = esp_wifi_get_assoc_bssid_internal(bssid);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_INFO, "STA not associated");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
category = *payload++;
|
||||||
|
len--;
|
||||||
|
if (category == WLAN_ACTION_WNM) {
|
||||||
|
ieee802_11_rx_wnm_action(wpa_s, sender, payload, len);
|
||||||
|
} else if (category == WLAN_ACTION_RADIO_MEASUREMENT) {
|
||||||
|
esp_handle_rrm_frame(wpa_s, sender, payload, len, rssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_supplicant_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
supplicant_event_t *evt;
|
||||||
|
bool task_del = false;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
if (xQueueReceive(s_supplicant_evt_queue, &evt, portMAX_DELAY) != pdTRUE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* event validation failed */
|
||||||
|
if (evt->id >= SIG_SUPPLICANT_MAX) {
|
||||||
|
os_free(evt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get lock */
|
||||||
|
SUPPLICANT_API_LOCK();
|
||||||
|
|
||||||
|
switch (evt->id) {
|
||||||
|
case SIG_SUPPLICANT_RX_ACTION:
|
||||||
|
{
|
||||||
|
struct ieee_mgmt_frame *frm = (struct ieee_mgmt_frame *)evt->data;
|
||||||
|
esp_mgmt_rx_action(frm->sender, frm->payload, frm->len, frm->channel, frm->rssi);
|
||||||
|
os_free(frm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SIG_SUPPLICANT_SCAN_DONE:
|
||||||
|
esp_supplicant_handle_scan_done_evt();
|
||||||
|
break;
|
||||||
|
case SIG_SUPPLICANT_DEL_TASK:
|
||||||
|
task_del = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_free(evt);
|
||||||
|
SUPPLICANT_API_UNLOCK();
|
||||||
|
|
||||||
|
if (task_del)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vQueueDelete(s_supplicant_evt_queue);
|
||||||
|
s_supplicant_evt_queue = NULL;
|
||||||
|
|
||||||
|
if (s_supplicant_api_lock) {
|
||||||
|
vSemaphoreDelete(s_supplicant_api_lock);
|
||||||
|
s_supplicant_api_lock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, we completed */
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_clear_bssid_flag(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wifi_config_t *config;
|
||||||
|
|
||||||
|
/* Reset only if btm is enabled */
|
||||||
|
if (esp_wifi_is_btm_enabled_internal(ESP_IF_WIFI_STA) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
config = os_zalloc(sizeof(wifi_config_t));
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_wifi_get_config(ESP_IF_WIFI_STA, config);
|
||||||
|
config->sta.bssid_set = 0;
|
||||||
|
esp_wifi_set_config(ESP_IF_WIFI_STA, config);
|
||||||
|
os_free(config);
|
||||||
|
wpa_printf(MSG_DEBUG, "cleared bssid flag");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_regsiter_action_frame(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpa_s->type &= ~WLAN_FC_STYPE_ACTION;
|
||||||
|
/* subtype is defined only for action frame */
|
||||||
|
wpa_s->subtype = 0;
|
||||||
|
|
||||||
|
/* current supported features in supplicant: rrm and btm */
|
||||||
|
if (esp_wifi_is_rm_enabled_internal(ESP_IF_WIFI_STA))
|
||||||
|
wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT;
|
||||||
|
if (esp_wifi_is_btm_enabled_internal(ESP_IF_WIFI_STA))
|
||||||
|
wpa_s->subtype |= 1 << WLAN_ACTION_WNM;
|
||||||
|
|
||||||
|
if (wpa_s->subtype)
|
||||||
|
wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION;
|
||||||
|
|
||||||
|
esp_wifi_register_frame_internal(wpa_s->type, wpa_s->subtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_supplicant_sta_conn_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int event_id, void* event_data)
|
||||||
|
{
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u8 *ie;
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
int ret = esp_wifi_get_assoc_bssid_internal(bssid);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not able to get connected bssid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid);
|
||||||
|
if (!bss) {
|
||||||
|
wpa_printf(MSG_INFO, "connected bss entry not present in scan cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_s->current_bss = bss;
|
||||||
|
ie = (u8 *)bss;
|
||||||
|
ie += sizeof(struct wpa_bss);
|
||||||
|
ieee802_11_parse_elems(wpa_s, ie, bss->ie_len);
|
||||||
|
wpa_bss_flush(wpa_s);
|
||||||
|
/* Register for action frames */
|
||||||
|
esp_regsiter_action_frame(wpa_s);
|
||||||
|
/* clear set bssid flag */
|
||||||
|
esp_clear_bssid_flag(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_supplicant_sta_disconn_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int event_id, void* event_data)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
wpas_rrm_reset(wpa_s);
|
||||||
|
if (wpa_s->current_bss) {
|
||||||
|
wpa_s->current_bss = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
|
||||||
|
s_supplicant_evt_queue = xQueueCreate(3, sizeof(supplicant_event_t));
|
||||||
|
xTaskCreate(esp_supplicant_task, "supplicantT", SUPPLICANT_TASK_STACK_SIZE, NULL, 2, s_supplicant_task_hdl);
|
||||||
|
|
||||||
|
s_supplicant_api_lock = xSemaphoreCreateRecursiveMutex();
|
||||||
|
if (!s_supplicant_api_lock) {
|
||||||
|
wpa_printf(MSG_ERROR, "esp_supplicant_common_init: failed to create Supplicant API lock");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_scan_init(wpa_s);
|
||||||
|
wpas_rrm_reset(wpa_s);
|
||||||
|
wpas_clear_beacon_rep_data(wpa_s);
|
||||||
|
|
||||||
|
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
|
||||||
|
&esp_supplicant_sta_conn_handler, NULL);
|
||||||
|
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
|
||||||
|
&esp_supplicant_sta_disconn_handler, NULL);
|
||||||
|
|
||||||
|
wpa_s->type = 0;
|
||||||
|
wpa_s->subtype = 0;
|
||||||
|
wpa_cb->esp_sta_rx_mgmt = esp_ieee80211_handle_rx_frm;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
|
||||||
|
void *cb_ctx)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
struct wpa_ssid_value wpa_ssid = {0};
|
||||||
|
struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
|
||||||
|
os_memcpy(wpa_ssid.ssid, ssid->ssid, ssid->len);
|
||||||
|
wpa_ssid.ssid_len = ssid->len;
|
||||||
|
wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
|
||||||
|
const char *btm_candidates,
|
||||||
|
int cand_list)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, btm_candidates, cand_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss, char *ssid)
|
||||||
|
{
|
||||||
|
wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_wifi_get_config(ESP_IF_WIFI_STA, config);
|
||||||
|
esp_wifi_disconnect();
|
||||||
|
/* We only support roaming in same ESS, therefore only bssid setting is needed */
|
||||||
|
os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN);
|
||||||
|
config->sta.bssid_set = 1;
|
||||||
|
esp_wifi_set_config(ESP_IF_WIFI_STA, config);
|
||||||
|
os_free(config);
|
||||||
|
esp_wifi_connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_set_rm_enabled_ie(void)
|
||||||
|
{
|
||||||
|
uint8_t rmm_ie[5] = {0};
|
||||||
|
uint8_t rrm_ie_len = 5;
|
||||||
|
uint8_t *pos = rmm_ie;
|
||||||
|
|
||||||
|
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
|
||||||
|
|
||||||
|
*pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
|
||||||
|
#ifdef SCAN_CACHE_SUPPORTED
|
||||||
|
WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
|
||||||
|
#endif
|
||||||
|
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
|
||||||
|
|
||||||
|
/* set rm enabled IE if enabled in driver */
|
||||||
|
if (esp_wifi_is_rm_enabled_internal(ESP_IF_WIFI_STA)) {
|
||||||
|
esp_wifi_set_appie_internal(WIFI_APPIE_RM_ENABLED_CAPS, rmm_ie, rrm_ie_len, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_get_tx_power(uint8_t *tx_power)
|
||||||
|
{
|
||||||
|
#define DEFAULT_MAX_TX_POWER 19 /* max tx power is 19.5 dbm */
|
||||||
|
s8 power;
|
||||||
|
/* esp sends management frames at max tx power configured */
|
||||||
|
int ret = esp_wifi_get_max_tx_power(&power);
|
||||||
|
if (ret != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to get tx power");
|
||||||
|
*tx_power = DEFAULT_MAX_TX_POWER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*tx_power = power/4;
|
||||||
|
#undef DEFAULT_MAX_TX_POWER
|
||||||
|
}
|
||||||
|
|
||||||
|
int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
|
||||||
|
unsigned int channel,
|
||||||
|
unsigned int wait,
|
||||||
|
const u8 *data, size_t data_len,
|
||||||
|
int no_cck)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + data_len);;
|
||||||
|
if (!req)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!wpa_s->current_bss) {
|
||||||
|
wpa_printf(MSG_ERROR, "STA not associated, return");
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->ifx = ESP_IF_WIFI_STA;
|
||||||
|
req->subtype = WLAN_FC_STYPE_ACTION;
|
||||||
|
req->data_len = data_len;
|
||||||
|
os_memcpy(req->data, data, req->data_len);
|
||||||
|
|
||||||
|
if (esp_wifi_send_mgmt_frm_internal(req) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "action frame sending failed");
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_INFO, "action frame sent");
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
os_free(req);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
|
||||||
|
{
|
||||||
|
supplicant_event_t *evt = os_zalloc(sizeof(supplicant_event_t));
|
||||||
|
if (evt == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
evt->id = evt_id;
|
||||||
|
evt->data = data;
|
||||||
|
|
||||||
|
SUPPLICANT_API_LOCK();
|
||||||
|
if (xQueueSend(s_supplicant_evt_queue, &evt, 10 / portTICK_PERIOD_MS ) != pdPASS) {
|
||||||
|
SUPPLICANT_API_UNLOCK();
|
||||||
|
os_free(evt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SUPPLICANT_API_UNLOCK();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
|
||||||
|
u32 rssi, u8 channel, u64 current_tsf)
|
||||||
|
{
|
||||||
|
if (type == WLAN_FC_STYPE_BEACON || type == WLAN_FC_STYPE_PROBE_RESP) {
|
||||||
|
return esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf);
|
||||||
|
} else if (type == WLAN_FC_STYPE_ACTION) {
|
||||||
|
return esp_handle_action_frm(frame, len, sender, rssi, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
80
components/wpa_supplicant/src/esp_supplicant/esp_common_i.h
Executable file
80
components/wpa_supplicant/src/esp_supplicant/esp_common_i.h
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ESP_COMMON_I_H
|
||||||
|
#define ESP_COMMON_I_H
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
struct wpa_funcs;
|
||||||
|
|
||||||
|
#ifdef ROAMING_SUPPORT
|
||||||
|
struct ieee_mgmt_frame {
|
||||||
|
u8 sender[ETH_ALEN];
|
||||||
|
u8 channel;
|
||||||
|
u32 rssi;
|
||||||
|
size_t len;
|
||||||
|
u8 payload[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t data;
|
||||||
|
} supplicant_event_t;
|
||||||
|
|
||||||
|
#define SUPPLICANT_API_LOCK() xSemaphoreTakeRecursive(s_supplicant_api_lock, portMAX_DELAY)
|
||||||
|
#define SUPPLICANT_API_UNLOCK() xSemaphoreGiveRecursive(s_supplicant_api_lock)
|
||||||
|
|
||||||
|
#define SUPPLICANT_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD)
|
||||||
|
enum SIG_SUPPLICANT {
|
||||||
|
SIG_SUPPLICANT_RX_ACTION,
|
||||||
|
SIG_SUPPLICANT_SCAN_DONE,
|
||||||
|
SIG_SUPPLICANT_DEL_TASK,
|
||||||
|
SIG_SUPPLICANT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data);
|
||||||
|
int esp_ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
|
||||||
|
u32 rssi, u8 channel, u64 current_tsf);
|
||||||
|
void esp_set_rm_enabled_ie(void);
|
||||||
|
void esp_get_tx_power(uint8_t *tx_power);
|
||||||
|
void esp_supplicant_common_init(struct wpa_funcs *wpa_cb);
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "esp_rrm.h"
|
||||||
|
#include "esp_wnm.h"
|
||||||
|
|
||||||
|
static inline void esp_set_rm_enabled_ie(void) {}
|
||||||
|
static inline int esp_ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
|
||||||
|
u32 rssi, u8 channel, u64 current_tsf)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
|
||||||
|
void *cb_ctx)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
|
||||||
|
const char *btm_candidates,
|
||||||
|
int cand_list)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
270
components/wpa_supplicant/src/esp_supplicant/esp_scan.c
Executable file
270
components/wpa_supplicant/src/esp_supplicant/esp_scan.c
Executable file
@ -0,0 +1,270 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "common/wpa_supplicant_i.h"
|
||||||
|
#include "utils/wpa_debug.h"
|
||||||
|
#include "esp_wifi_driver.h"
|
||||||
|
#include "esp_wifi_types.h"
|
||||||
|
#include "drivers/driver.h"
|
||||||
|
#include "common/scan.h"
|
||||||
|
#include "common/bss.h"
|
||||||
|
#include "common/rrm.h"
|
||||||
|
#include "common/ieee802_11_common.h"
|
||||||
|
#include "esp_supplicant/esp_common_i.h"
|
||||||
|
#include "common/wnm_sta.h"
|
||||||
|
|
||||||
|
extern struct wpa_supplicant g_wpa_supp;
|
||||||
|
|
||||||
|
static void esp_scan_done_event_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int event_id, void* event_data)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
if (!wpa_s->scanning) {
|
||||||
|
/* update last scan time */
|
||||||
|
wpa_s->scan_start_tsf = esp_wifi_get_tsf_time(ESP_IF_WIFI_STA);
|
||||||
|
wpa_printf(MSG_DEBUG, "scan not triggered by supplicant, ignore");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_s->type &= ~(1 << WLAN_FC_STYPE_BEACON) & ~(1 << WLAN_FC_STYPE_PROBE_RESP);
|
||||||
|
esp_wifi_register_frame_internal(wpa_s->type, wpa_s->subtype);
|
||||||
|
esp_supplicant_post_evt(SIG_SUPPLICANT_SCAN_DONE, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_supp_handle_wnm_scan_done(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss);
|
||||||
|
|
||||||
|
if (wpa_s->wnm_neighbor_report_elements) {
|
||||||
|
wnm_scan_process(wpa_s, 1);
|
||||||
|
} else if (wpa_s->wnm_dissoc_timer) {
|
||||||
|
if (wpa_s->num_bss == 1) {
|
||||||
|
wpa_printf(MSG_INFO, "not able to find another candidate, do nothing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* this is a already matched bss */
|
||||||
|
if (bss)
|
||||||
|
wnm_bss_tm_connect(wpa_s, bss, NULL, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esp_supp_scan_done_cleanup(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
uint16_t number = 1;
|
||||||
|
wifi_ap_record_t ap_records;
|
||||||
|
|
||||||
|
wpa_s->scanning = 0;
|
||||||
|
wpa_s->scan_reason = 0;
|
||||||
|
/* clean scan list from net80211 */
|
||||||
|
esp_wifi_scan_get_ap_records(&number, &ap_records);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_supplicant_handle_scan_done_evt(void)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
|
||||||
|
wpa_printf(MSG_INFO, "scan done received");
|
||||||
|
/* Check which module started this, call the respective function */
|
||||||
|
if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) {
|
||||||
|
wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf);
|
||||||
|
} else if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) {
|
||||||
|
esp_supp_handle_wnm_scan_done(wpa_s);
|
||||||
|
}
|
||||||
|
esp_supp_scan_done_cleanup(wpa_s);
|
||||||
|
wpa_bss_update_end(wpa_s);
|
||||||
|
#ifndef SCAN_CACHE_SUPPORTED
|
||||||
|
wpa_bss_flush(wpa_s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_scan_init(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpa_s->scanning = 0;
|
||||||
|
wpa_bss_init(wpa_s);
|
||||||
|
wpa_s->last_scan_res = NULL;
|
||||||
|
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE,
|
||||||
|
&esp_scan_done_event_handler, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_scan_deinit(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpa_bss_deinit(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_handle_beacon_probe(u8 type, u8 *frame, size_t len, u8 *sender,
|
||||||
|
u32 rssi, u8 channel, u64 current_tsf)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = &g_wpa_supp;
|
||||||
|
struct os_reltime now;
|
||||||
|
struct wpa_scan_res *res;
|
||||||
|
u8 *ptr;
|
||||||
|
|
||||||
|
if (len < 12) {
|
||||||
|
wpa_printf(MSG_ERROR, "beacon/probe is having short len=%d\n", len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_zalloc(sizeof(struct wpa_scan_res) + len - 12);
|
||||||
|
if (!res) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = (u8 *)res;
|
||||||
|
os_get_time(&now);
|
||||||
|
os_memcpy(res->bssid, sender, ETH_ALEN);
|
||||||
|
res->tsf = WPA_GET_LE64(frame);
|
||||||
|
frame += 8;
|
||||||
|
len -= 8;
|
||||||
|
|
||||||
|
if ((wpa_s->scan_start_tsf == 0) &&
|
||||||
|
wpa_s->current_bss &&
|
||||||
|
(os_memcmp(wpa_s->current_bss, sender, ETH_ALEN) == 0)) {
|
||||||
|
wpa_s->scan_start_tsf = res->tsf;
|
||||||
|
os_memcpy(wpa_s->tsf_bssid, sender, ETH_ALEN);
|
||||||
|
}
|
||||||
|
res->beacon_int = WPA_GET_LE16(frame);
|
||||||
|
|
||||||
|
frame += 2;
|
||||||
|
len -= 2;
|
||||||
|
res->caps = WPA_GET_LE16(frame);
|
||||||
|
frame += 2;
|
||||||
|
len -= 2;
|
||||||
|
|
||||||
|
res->chan = channel;
|
||||||
|
res->noise = 0;
|
||||||
|
res->level = rssi;
|
||||||
|
os_memcpy(res->tsf_bssid, wpa_s->tsf_bssid, ETH_ALEN);
|
||||||
|
res->parent_tsf = current_tsf - wpa_s->scan_start_tsf;
|
||||||
|
if (type == WLAN_FC_STYPE_PROBE_RESP)
|
||||||
|
res->ie_len = len;
|
||||||
|
else if (type == WLAN_FC_STYPE_BEACON)
|
||||||
|
res->beacon_ie_len = len;
|
||||||
|
|
||||||
|
ptr += sizeof(struct wpa_scan_res);
|
||||||
|
|
||||||
|
/* update rest of the frame */
|
||||||
|
os_memcpy(ptr, frame, len);
|
||||||
|
wpa_bss_update_scan_res(wpa_s, res, &now);
|
||||||
|
os_free(res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int esp_issue_scan(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_driver_scan_params *scan_params)
|
||||||
|
{
|
||||||
|
wifi_scan_config_t *params = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
u64 scan_start_tsf = esp_wifi_get_tsf_time(ESP_IF_WIFI_STA);
|
||||||
|
|
||||||
|
/* TODO: Directly try to connect if scan results are recent */
|
||||||
|
if ((scan_start_tsf - wpa_s->scan_start_tsf) > 100000) {
|
||||||
|
wpa_printf(MSG_DEBUG, "flushing old scan cache %llu",
|
||||||
|
(scan_start_tsf - wpa_s->scan_start_tsf));
|
||||||
|
wpa_bss_flush(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_wifi_get_macaddr_internal(ESP_IF_WIFI_STA, wpa_s->tsf_bssid);
|
||||||
|
|
||||||
|
if (scan_params) {
|
||||||
|
params = os_zalloc(sizeof(wifi_scan_config_t));
|
||||||
|
if (!params) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (scan_params->num_ssids) {
|
||||||
|
params->ssid = os_zalloc(scan_params->ssids[0].ssid_len + 1);
|
||||||
|
if (!params->ssid) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os_memcpy(params->ssid, scan_params->ssids[0].ssid, scan_params->ssids[0].ssid_len);
|
||||||
|
params->scan_type = WIFI_SCAN_TYPE_ACTIVE;
|
||||||
|
} else
|
||||||
|
params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
|
||||||
|
|
||||||
|
if (scan_params->bssid) {
|
||||||
|
params->bssid = os_zalloc(ETH_ALEN);
|
||||||
|
if (!params->bssid) {
|
||||||
|
wpa_printf(MSG_ERROR, "failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os_memcpy(params->bssid, scan_params->bssid, ETH_ALEN);
|
||||||
|
}
|
||||||
|
if (scan_params->channel) {
|
||||||
|
params->channel = scan_params->channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scan_params->duration) {
|
||||||
|
params->scan_time.passive = scan_params->duration;
|
||||||
|
params->scan_time.active.min = scan_params->duration;
|
||||||
|
params->scan_time.active.max = scan_params->duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_s->scan_start_tsf = scan_start_tsf;
|
||||||
|
/* Register frames to come to supplicant when we park on channel */
|
||||||
|
wpa_s->type |= (1 << WLAN_FC_STYPE_BEACON) | (1 << WLAN_FC_STYPE_PROBE_RESP);
|
||||||
|
esp_wifi_register_frame_internal(wpa_s->type, wpa_s->subtype);
|
||||||
|
|
||||||
|
/* issue scan */
|
||||||
|
if (esp_wifi_scan_start(params, false) < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
wpa_s->scanning = 1;
|
||||||
|
wpa_bss_update_start(wpa_s);
|
||||||
|
wpa_printf(MSG_INFO, "scan issued at time=%llu", wpa_s->scan_start_tsf);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (params->ssid)
|
||||||
|
os_free(params->ssid);
|
||||||
|
if (params->bssid)
|
||||||
|
os_free(params->bssid);
|
||||||
|
os_free(params);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_supplicant_trigger_scan - Request driver to start a scan
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
* @params: Scan parameters
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_driver_scan_params *params)
|
||||||
|
{
|
||||||
|
return esp_issue_scan(wpa_s, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpa_scan_results_free(struct wpa_scan_results *res)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (res == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < res->num; i++)
|
||||||
|
os_free(res->res[i]);
|
||||||
|
os_free(res->res);
|
||||||
|
os_free(res);
|
||||||
|
}
|
25
components/wpa_supplicant/src/esp_supplicant/esp_scan_i.h
Executable file
25
components/wpa_supplicant/src/esp_supplicant/esp_scan_i.h
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ESP_SCAN_I_H
|
||||||
|
#define ESP_SCAN_I_H
|
||||||
|
void esp_scan_init(struct wpa_supplicant *wpa_s);
|
||||||
|
void esp_scan_deinit(struct wpa_supplicant *wpa_s);
|
||||||
|
int esp_handle_beacon_probe(u8 type, u8 *frame, size_t len, u8 *sender,
|
||||||
|
u32 rssi, u8 channel, u64 current_tsf);
|
||||||
|
|
||||||
|
void esp_supplicant_handle_scan_done_evt(void);
|
||||||
|
#endif
|
14
components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h
Normal file → Executable file
14
components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h
Normal file → Executable file
@ -39,6 +39,7 @@ enum {
|
|||||||
WIFI_APPIE_FREQ_ERROR,
|
WIFI_APPIE_FREQ_ERROR,
|
||||||
WIFI_APPIE_ESP_MANUFACTOR,
|
WIFI_APPIE_ESP_MANUFACTOR,
|
||||||
WIFI_APPIE_COUNTRY,
|
WIFI_APPIE_COUNTRY,
|
||||||
|
WIFI_APPIE_RM_ENABLED_CAPS,
|
||||||
WIFI_APPIE_MAX,
|
WIFI_APPIE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,6 +108,7 @@ struct wpa_funcs {
|
|||||||
int (*wpa_michael_mic_failure)(u16 is_unicast);
|
int (*wpa_michael_mic_failure)(u16 is_unicast);
|
||||||
uint8_t *(*wpa3_build_sae_msg)(uint8_t *bssid, uint32_t type, size_t *len);
|
uint8_t *(*wpa3_build_sae_msg)(uint8_t *bssid, uint32_t type, size_t *len);
|
||||||
int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
|
int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
|
||||||
|
int (*esp_sta_rx_mgmt)(u8 type, u8 *frame, size_t len, u8 *sender, u32 rssi, u8 channel, u64 current_tsf);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wpa2_funcs {
|
struct wpa2_funcs {
|
||||||
@ -156,7 +158,13 @@ typedef struct {
|
|||||||
uint8_t igtk[WPA_IGTK_LEN];
|
uint8_t igtk[WPA_IGTK_LEN];
|
||||||
} wifi_wpa_igtk_t;
|
} wifi_wpa_igtk_t;
|
||||||
|
|
||||||
/*wpa_auth.c*/
|
typedef struct {
|
||||||
|
wifi_interface_t ifx;
|
||||||
|
uint8_t subtype;
|
||||||
|
uint32_t data_len;
|
||||||
|
uint8_t data[0];
|
||||||
|
} mgmt_frm_req_t;
|
||||||
|
|
||||||
uint8_t *esp_wifi_ap_get_prof_pmk_internal(void);
|
uint8_t *esp_wifi_ap_get_prof_pmk_internal(void);
|
||||||
struct wifi_ssid *esp_wifi_ap_get_prof_ap_ssid_internal(void);
|
struct wifi_ssid *esp_wifi_ap_get_prof_ap_ssid_internal(void);
|
||||||
uint8_t esp_wifi_ap_get_prof_authmode_internal(void);
|
uint8_t esp_wifi_ap_get_prof_authmode_internal(void);
|
||||||
@ -224,5 +232,9 @@ uint8_t esp_wifi_get_user_init_flag_internal(void);
|
|||||||
int esp_wifi_ipc_internal(wifi_ipc_config_t *cfg, bool sync);
|
int esp_wifi_ipc_internal(wifi_ipc_config_t *cfg, bool sync);
|
||||||
esp_err_t esp_wifi_internal_issue_disconnect(uint8_t reason_code);
|
esp_err_t esp_wifi_internal_issue_disconnect(uint8_t reason_code);
|
||||||
int esp_wifi_ap_deauth_internal(uint8_t *mac, uint32_t reason);
|
int esp_wifi_ap_deauth_internal(uint8_t *mac, uint32_t reason);
|
||||||
|
bool esp_wifi_is_rm_enabled_internal(uint8_t if_index);
|
||||||
|
bool esp_wifi_is_btm_enabled_internal(uint8_t if_index);
|
||||||
|
void esp_wifi_register_frame_internal(uint32_t type, uint32_t subtype);
|
||||||
|
esp_err_t esp_wifi_send_mgmt_frm_internal(const mgmt_frm_req_t *req);
|
||||||
|
|
||||||
#endif /* _ESP_WIFI_DRIVER_H_ */
|
#endif /* _ESP_WIFI_DRIVER_H_ */
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "esp_wifi_driver.h"
|
#include "esp_wifi_driver.h"
|
||||||
#include "esp_private/wifi.h"
|
#include "esp_private/wifi.h"
|
||||||
#include "esp_wpa3_i.h"
|
#include "esp_wpa3_i.h"
|
||||||
|
#include "esp_common_i.h"
|
||||||
|
|
||||||
void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
|
void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
|
||||||
u8 *seq, size_t seq_len, u8 *key, size_t key_len, int key_entry_valid)
|
u8 *seq, size_t seq_len, u8 *key, size_t key_len, int key_entry_valid)
|
||||||
@ -102,6 +103,7 @@ void wpa_config_assoc_ie(u8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len)
|
|||||||
} else {
|
} else {
|
||||||
esp_wifi_set_appie_internal(WIFI_APPIE_RSN, assoc_buf, assoc_wpa_ie_len, 1);
|
esp_wifi_set_appie_internal(WIFI_APPIE_RSN, assoc_buf, assoc_wpa_ie_len, 1);
|
||||||
}
|
}
|
||||||
|
esp_set_rm_enabled_ie();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wpa_neg_complete(void)
|
void wpa_neg_complete(void)
|
||||||
@ -154,6 +156,7 @@ bool wpa_deattach(void)
|
|||||||
|
|
||||||
void wpa_sta_connect(uint8_t *bssid)
|
void wpa_sta_connect(uint8_t *bssid)
|
||||||
{
|
{
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
wpa_config_profile();
|
wpa_config_profile();
|
||||||
ret = wpa_config_bss(bssid);
|
ret = wpa_config_bss(bssid);
|
||||||
@ -198,6 +201,13 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ROAMING_SUPPORT
|
||||||
|
static void esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
|
||||||
|
{
|
||||||
|
wpa_cb->esp_sta_rx_mgmt = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int esp_supplicant_init(void)
|
int esp_supplicant_init(void)
|
||||||
{
|
{
|
||||||
struct wpa_funcs *wpa_cb;
|
struct wpa_funcs *wpa_cb;
|
||||||
@ -226,6 +236,7 @@ int esp_supplicant_init(void)
|
|||||||
wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
|
wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
|
||||||
wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
|
wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
|
||||||
esp_wifi_register_wpa3_cb(wpa_cb);
|
esp_wifi_register_wpa3_cb(wpa_cb);
|
||||||
|
esp_supplicant_common_init(wpa_cb);
|
||||||
|
|
||||||
esp_wifi_register_wpa_cb_internal(wpa_cb);
|
esp_wifi_register_wpa_cb_internal(wpa_cb);
|
||||||
|
|
||||||
|
89
components/wpa_supplicant/src/utils/bitfield.c
Executable file
89
components/wpa_supplicant/src/utils/bitfield.c
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Bitfield
|
||||||
|
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "bitfield.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct bitfield {
|
||||||
|
u8 *bits;
|
||||||
|
size_t max_bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct bitfield * bitfield_alloc(size_t max_bits)
|
||||||
|
{
|
||||||
|
struct bitfield *bf;
|
||||||
|
|
||||||
|
bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
|
||||||
|
if (bf == NULL)
|
||||||
|
return NULL;
|
||||||
|
bf->bits = (u8 *) (bf + 1);
|
||||||
|
bf->max_bits = max_bits;
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bitfield_free(struct bitfield *bf)
|
||||||
|
{
|
||||||
|
os_free(bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bitfield_set(struct bitfield *bf, size_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= bf->max_bits)
|
||||||
|
return;
|
||||||
|
bf->bits[bit / 8] |= BIT(bit % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bitfield_clear(struct bitfield *bf, size_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= bf->max_bits)
|
||||||
|
return;
|
||||||
|
bf->bits[bit / 8] &= ~BIT(bit % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int bitfield_is_set(struct bitfield *bf, size_t bit)
|
||||||
|
{
|
||||||
|
if (bit >= bf->max_bits)
|
||||||
|
return 0;
|
||||||
|
return !!(bf->bits[bit / 8] & BIT(bit % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int first_zero(u8 val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (!(val & 0x01))
|
||||||
|
return i;
|
||||||
|
val >>= 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int bitfield_get_first_zero(struct bitfield *bf)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < (bf->max_bits + 7) / 8; i++) {
|
||||||
|
if (bf->bits[i] != 0xff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == (bf->max_bits + 7) / 8)
|
||||||
|
return -1;
|
||||||
|
i = i * 8 + first_zero(bf->bits[i]);
|
||||||
|
if (i >= bf->max_bits)
|
||||||
|
return -1;
|
||||||
|
return i;
|
||||||
|
}
|
21
components/wpa_supplicant/src/utils/bitfield.h
Executable file
21
components/wpa_supplicant/src/utils/bitfield.h
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Bitfield
|
||||||
|
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BITFIELD_H
|
||||||
|
#define BITFIELD_H
|
||||||
|
|
||||||
|
struct bitfield;
|
||||||
|
|
||||||
|
struct bitfield * bitfield_alloc(size_t max_bits);
|
||||||
|
void bitfield_free(struct bitfield *bf);
|
||||||
|
void bitfield_set(struct bitfield *bf, size_t bit);
|
||||||
|
void bitfield_clear(struct bitfield *bf, size_t bit);
|
||||||
|
int bitfield_is_set(struct bitfield *bf, size_t bit);
|
||||||
|
int bitfield_get_first_zero(struct bitfield *bf);
|
||||||
|
|
||||||
|
#endif /* BITFIELD_H */
|
@ -491,3 +491,59 @@ int hwaddr_aton2(const char *txt, u8 *addr)
|
|||||||
|
|
||||||
return pos - txt;
|
return pos - txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int os_reltime_expired(struct os_time *now,
|
||||||
|
struct os_time *ts,
|
||||||
|
os_time_t timeout_secs)
|
||||||
|
{
|
||||||
|
struct os_time age;
|
||||||
|
|
||||||
|
os_time_sub(now, ts, &age);
|
||||||
|
return (age.sec > timeout_secs) ||
|
||||||
|
(age.sec == timeout_secs && age.usec > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os_time_expired(struct os_time *now,
|
||||||
|
struct os_time *ts,
|
||||||
|
os_time_t timeout_secs)
|
||||||
|
{
|
||||||
|
return os_reltime_expired(now, ts, timeout_secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 rssi_to_rcpi(int rssi)
|
||||||
|
{
|
||||||
|
if (!rssi)
|
||||||
|
return 255; /* not available */
|
||||||
|
if (rssi < -110)
|
||||||
|
return 0;
|
||||||
|
if (rssi > 0)
|
||||||
|
return 220;
|
||||||
|
return (rssi + 110) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_ssid_txt - Convert SSID to a printable string
|
||||||
|
* @ssid: SSID (32-octet string)
|
||||||
|
* @ssid_len: Length of ssid in octets
|
||||||
|
* Returns: Pointer to a printable string
|
||||||
|
*
|
||||||
|
* This function can be used to convert SSIDs into printable form. In most
|
||||||
|
* cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
|
||||||
|
* does not limit the used character set, so anything could be used in an SSID.
|
||||||
|
*
|
||||||
|
* This function uses a static buffer, so only one call can be used at the
|
||||||
|
* time, i.e., this is not re-entrant and the returned buffer must be used
|
||||||
|
* before calling this again.
|
||||||
|
*/
|
||||||
|
const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
|
||||||
|
{
|
||||||
|
static char ssid_txt[SSID_MAX_LEN * 4 + 1];
|
||||||
|
|
||||||
|
if (ssid == NULL) {
|
||||||
|
ssid_txt[0] = '\0';
|
||||||
|
return ssid_txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
|
||||||
|
return ssid_txt;
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#endif /* ets */
|
#endif /* ets */
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "esp_bit_defs.h"
|
#include "esp_bit_defs.h"
|
||||||
|
#include "utils/list.h"
|
||||||
|
|
||||||
/* Define platform specific variable type macros */
|
/* Define platform specific variable type macros */
|
||||||
#if defined(ESP_PLATFORM)
|
#if defined(ESP_PLATFORM)
|
||||||
@ -117,6 +118,12 @@ static inline unsigned int wpa_swap_32(unsigned int v)
|
|||||||
#define WPA_BYTE_SWAP_DEFINED
|
#define WPA_BYTE_SWAP_DEFINED
|
||||||
#endif /* !WPA_BYTE_SWAP_DEFINED */
|
#endif /* !WPA_BYTE_SWAP_DEFINED */
|
||||||
|
|
||||||
|
#define SSID_MAX_LEN 32
|
||||||
|
|
||||||
|
struct wpa_ssid_value {
|
||||||
|
u8 ssid[SSID_MAX_LEN];
|
||||||
|
size_t ssid_len;
|
||||||
|
};
|
||||||
|
|
||||||
/* Macros for handling unaligned memory accesses */
|
/* Macros for handling unaligned memory accesses */
|
||||||
|
|
||||||
@ -381,6 +388,10 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
|
|||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
|
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
|
||||||
|
u8 rssi_to_rcpi(int rssi);
|
||||||
|
int os_time_expired(struct os_time *now,
|
||||||
|
struct os_time *ts,
|
||||||
|
os_time_t timeout_secs);
|
||||||
|
|
||||||
#ifdef CONFIG_NATIVE_WINDOWS
|
#ifdef CONFIG_NATIVE_WINDOWS
|
||||||
void wpa_unicode2ascii_inplace(TCHAR *str);
|
void wpa_unicode2ascii_inplace(TCHAR *str);
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
* See README and COPYING for more details.
|
* See README and COPYING for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIST_H
|
#ifndef WPA_LIST_H
|
||||||
#define LIST_H
|
#define WPA_LIST_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@ -100,4 +100,4 @@ static inline unsigned int dl_list_len(struct dl_list *list)
|
|||||||
#define DEFINE_DL_LIST(name) \
|
#define DEFINE_DL_LIST(name) \
|
||||||
struct dl_list name = { &(name), &(name) }
|
struct dl_list name = { &(name), &(name) }
|
||||||
|
|
||||||
#endif /* LIST_H */
|
#endif /* WPA_LIST_H */
|
||||||
|
@ -91,22 +91,22 @@ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
|
|||||||
size_t i;
|
size_t i;
|
||||||
char output[50];
|
char output[50];
|
||||||
|
|
||||||
if (level < MSG_MSGDUMP)
|
if (level < MSG_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s - hexdump(len=%lu):", title, (unsigned long) len);
|
wpa_printf(level, "%s - hexdump(len=%lu):", title, (unsigned long) len);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, " [NULL]");
|
wpa_printf(level, " [NULL]");
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < len / 16; i++) {
|
for (i = 0; i < len / 16; i++) {
|
||||||
_wpa_snprintf_hex(output, 50, buf + i * 16, 16, 0, 1);
|
_wpa_snprintf_hex(output, 50, buf + i * 16, 16, 0, 1);
|
||||||
wpa_printf(MSG_DEBUG, "%s", output);
|
wpa_printf(level, "%s", output);
|
||||||
}
|
}
|
||||||
if (len % 16) {
|
if (len % 16) {
|
||||||
int bytes_printed = (len / 16) * 16;
|
int bytes_printed = (len / 16) * 16;
|
||||||
_wpa_snprintf_hex(output, 50, buf + bytes_printed,
|
_wpa_snprintf_hex(output, 50, buf + bytes_printed,
|
||||||
len - bytes_printed, 0, 1);
|
len - bytes_printed, 0, 1);
|
||||||
wpa_printf(MSG_DEBUG, "%s", output);
|
wpa_printf(level, "%s", output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user