fix(wifi) : Add scan only parser to show AP full compatibility

This commit is contained in:
tarun.kumar
2026-09-04 12:04:04 +08:00
committed by Jack
parent 04f2001014
commit 4c5df8be98
7 changed files with 187 additions and 23 deletions
@@ -163,6 +163,7 @@ struct wpa_funcs {
int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len);
void (*wpa_sta_clear_curr_pmksa)(void);
void (*wpa_config_reload)(void);
int (*wpa_parse_wpa_ie_scan_only)(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data);
};
struct wpa2_funcs {
@@ -277,12 +277,15 @@ void wpa_config_done(void)
esp_set_scan_ie();
}
int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
static int wpa_parse_wpa_ie_to_public(const u8 *wpa_ie, size_t wpa_ie_len,
wifi_wpa_ie_t *data,
int (*parse_fn)(const u8 *, size_t,
struct wpa_ie_data *))
{
struct wpa_ie_data ie;
int ret = 0;
struct wpa_ie_data ie = {0};
int ret;
ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie);
ret = parse_fn(wpa_ie, wpa_ie_len, &ie);
data->proto = ie.proto;
data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher);
data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher);
@@ -295,6 +298,18 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t
return ret;
}
int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
{
return wpa_parse_wpa_ie_to_public(wpa_ie, wpa_ie_len, data, wpa_parse_wpa_ie);
}
int wpa_parse_wpa_ie_scan_only_wrapper(const u8 *wpa_ie, size_t wpa_ie_len,
wifi_wpa_ie_t *data)
{
return wpa_parse_wpa_ie_to_public(wpa_ie, wpa_ie_len, data,
wpa_parse_wpa_ie_scan_only);
}
static void wpa_sta_connected_cb(uint8_t *bssid)
{
supplicant_sta_conn_handler(bssid);
@@ -539,6 +554,7 @@ int esp_supplicant_init(void)
wpa_cb->wpa_config_parse_string = wpa_config_parse_string;
wpa_cb->wpa_parse_wpa_ie = wpa_parse_wpa_ie_wrapper;
wpa_cb->wpa_parse_wpa_ie_scan_only = wpa_parse_wpa_ie_scan_only_wrapper;
wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
wpa_cb->wpa_config_done = wpa_config_done;
+124 -17
View File
@@ -373,6 +373,72 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
return 0;
}
static int rsn_selector_to_bitfield_scan_only(const u8 *s)
{
u32 sel = RSN_SELECTOR_GET(s);
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 0))
return WPA_CIPHER_NONE;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 1))
return WPA_CIPHER_WEP40;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 2))
return WPA_CIPHER_TKIP;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 4))
return WPA_CIPHER_CCMP;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 5))
return WPA_CIPHER_WEP104;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 6))
return WPA_CIPHER_AES_128_CMAC;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 7))
return WPA_CIPHER_GTK_NOT_USED;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 8))
return WPA_CIPHER_GCMP;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 9))
return WPA_CIPHER_GCMP_256;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 11))
return WPA_CIPHER_BIP_GMAC_128;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 12))
return WPA_CIPHER_BIP_GMAC_256;
return 0;
}
static int rsn_key_mgmt_to_bitfield_scan_only(const u8 *s)
{
u32 sel = RSN_SELECTOR_GET(s);
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 1))
return WPA_KEY_MGMT_IEEE8021X;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 2))
return WPA_KEY_MGMT_PSK;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 3))
return WPA_KEY_MGMT_FT_IEEE8021X;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 4))
return WPA_KEY_MGMT_FT_PSK;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 5))
return WPA_KEY_MGMT_IEEE8021X_SHA256;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 6))
return WPA_KEY_MGMT_PSK_SHA256;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 8))
return WPA_KEY_MGMT_SAE;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 9))
return WPA_KEY_MGMT_FT_SAE;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 11))
return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 12))
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 13))
return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 18))
return WPA_KEY_MGMT_OWE;
if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 24))
return WPA_KEY_MGMT_SAE_EXT_KEY;
if (sel == RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02))
return WPA_KEY_MGMT_DPP;
return 0;
}
static int wpa_selector_to_bitfield(const u8 *s)
{
if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
@@ -431,15 +497,31 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
return 0;
}
/**
* wpa_parse_wpa_ie_rsn - Parse RSN IE
* @rsn_ie: Buffer containing RSN IE
* @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
* @data: Pointer to structure that will be filled in with parsed data
* Returns: 0 on success, <0 on failure
*/
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
int wpa_parse_wpa_ie_rsnxe_scan_only(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
struct wpa_ie_data *data)
{
uint8_t rsnxe_capa = 0;
memset(data, 0, sizeof(*data));
if (rsnxe_ie_len < 3 || !rsnxe_ie) {
return -1;
}
if (rsnxe_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
rsnxe_ie[1] >= 1 + 4) {
rsnxe_capa = rsnxe_ie[2 + 4];
} else {
rsnxe_capa = rsnxe_ie[2];
}
data->rsnxe_capa = rsnxe_capa;
return 0;
}
static int wpa_parse_wpa_ie_rsn_common(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data,
int (*selector_to_bitfield)(const u8 *),
int (*key_mgmt_to_bitfield)(const u8 *),
bool validate_mgmt_group)
{
const u8 *pos;
int left;
@@ -468,9 +550,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
rsn_ie[1] == rsn_ie_len - 2 &&
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) &&
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
rsn_ie[1] == rsn_ie_len - 2 &&
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) &&
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
pos = rsn_ie + 2 + 4 + 2;
left = rsn_ie_len - 2 - 4 - 2;
} else {
@@ -491,7 +573,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
data->group_cipher = selector_to_bitfield(pos);
data->has_group = 1;
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
@@ -514,7 +596,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
if (count)
data->has_pairwise = 1;
for (i = 0; i < count; i++) {
data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
data->pairwise_cipher |= selector_to_bitfield(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
}
@@ -535,7 +617,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
return -6;
}
for (i = 0; i < count; i++) {
data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
data->key_mgmt |= key_mgmt_to_bitfield(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
}
@@ -570,8 +652,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
if (left >= 4) {
data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
data->mgmt_group_cipher = selector_to_bitfield(pos);
if (validate_mgmt_group &&
!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
wpa_printf(MSG_DEBUG,
"%s: Unsupported management group cipher 0x%x (%08x)",
__func__, data->mgmt_group_cipher,
@@ -590,6 +673,30 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
return 0;
}
/**
* wpa_parse_wpa_ie_rsn - Parse RSN IE
* @rsn_ie: Buffer containing RSN IE
* @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
* @data: Pointer to structure that will be filled in with parsed data
* Returns: 0 on success, <0 on failure
*/
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
return wpa_parse_wpa_ie_rsn_common(rsn_ie, rsn_ie_len, data,
rsn_selector_to_bitfield,
rsn_key_mgmt_to_bitfield, true);
}
int wpa_parse_wpa_ie_rsn_scan_only(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
return wpa_parse_wpa_ie_rsn_common(rsn_ie, rsn_ie_len, data,
rsn_selector_to_bitfield_scan_only,
rsn_key_mgmt_to_bitfield_scan_only,
false);
}
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data)
{
@@ -455,10 +455,16 @@ const char * wpa_cipher_txt(int cipher);
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_rsn_scan_only(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_rsnxe_scan_only(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
struct wpa_ie_data *data);
u32 wpa_akm_to_suite(int akm);
int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie1, size_t ie1len,
@@ -37,7 +37,7 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie_len >=1 && wpa_ie[0] == WLAN_EID_RSNX){
return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie[0] == WLAN_EID_WAPI) {
} else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_WAPI) {
return 0;
#ifdef CONFIG_WPA3_COMPAT
} else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
@@ -54,6 +54,38 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
/**
* wpa_parse_wpa_ie_scan_only - Parse WPA/RSN IE for scan result display
* @wpa_ie: Pointer to WPA or RSN IE
* @wpa_ie_len: Length of the WPA/RSN IE
* @data: Pointer to data area for parsing results
* Returns: 0 on success, -1 on failure
*
* Parse WPA/RSN IE without build-time feature restrictions so scan results
* can report all advertised ciphers and AKMs.
*/
int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data)
{
if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) {
return wpa_parse_wpa_ie_rsn_scan_only(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSNX) {
return wpa_parse_wpa_ie_rsnxe_scan_only(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_WAPI) {
return 0;
} else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
return wpa_parse_wpa_ie_rsn_scan_only(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
return wpa_parse_wpa_ie_rsnxe_scan_only(wpa_ie, wpa_ie_len, data);
}
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
int pairwise_cipher, int group_cipher,
@@ -19,5 +19,7 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len);
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len);
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
#endif /* WPA_IE_H */