diff --git a/src/drivers/driver.h b/src/drivers/driver.h index a605f1265..8b63d54eb 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -73,6 +73,8 @@ struct hostapd_hw_modes { #define WPA_SCAN_NOISE_INVALID BIT(1) #define WPA_SCAN_LEVEL_INVALID BIT(2) #define WPA_SCAN_LEVEL_DBM BIT(3) +#define WPA_SCAN_AUTHENTICATED BIT(4) +#define WPA_SCAN_ASSOCIATED BIT(5) /** * struct wpa_scan_res - Scan result for an BSS/IBSS diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 77245eb95..c4db1a266 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -88,6 +88,7 @@ struct wpa_driver_nl80211_data { struct nl_cb *nl_cb; struct genl_family *nl80211; + u8 auth_bssid[ETH_ALEN]; u8 bssid[ETH_ALEN]; int associated; u8 ssid[32]; @@ -653,6 +654,7 @@ static void mlme_event_auth(struct wpa_driver_nl80211_data *drv, return; } + os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN); os_memset(&event, 0, sizeof(event)); os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN); event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg); @@ -1616,6 +1618,7 @@ static int bss_info_handler(struct nl_msg *msg, void *arg) [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, + [NL80211_BSS_STATUS] = { .type = NLA_U32 }, [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, }; struct wpa_scan_results *res = arg; @@ -1669,6 +1672,21 @@ static int bss_info_handler(struct nl_msg *msg, void *arg) if (ie) os_memcpy(r + 1, ie, ie_len); + if (bss[NL80211_BSS_STATUS]) { + enum nl80211_bss_status status; + status = nla_get_u32(bss[NL80211_BSS_STATUS]); + switch (status) { + case NL80211_BSS_STATUS_AUTHENTICATED: + r->flags |= WPA_SCAN_AUTHENTICATED; + break; + case NL80211_BSS_STATUS_ASSOCIATED: + r->flags |= WPA_SCAN_ASSOCIATED; + break; + default: + break; + } + } + tmp = os_realloc(res->res, (res->num + 1) * sizeof(struct wpa_scan_res *)); if (tmp == NULL) { @@ -1682,6 +1700,53 @@ static int bss_info_handler(struct nl_msg *msg, void *arg) } +static void wpa_driver_nl80211_check_bss_status( + struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res) +{ + size_t i; + + for (i = 0; i < res->num; i++) { + struct wpa_scan_res *r = res->res[i]; + if (r->flags & WPA_SCAN_AUTHENTICATED) { + wpa_printf(MSG_DEBUG, "nl80211: Scan results " + "indicates BSS status with " MACSTR + " as authenticated", + MAC2STR(r->bssid)); + if (drv->nlmode == NL80211_IFTYPE_STATION && + os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 && + os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) != + 0) { + wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID" + " in local state (auth=" MACSTR + " assoc=" MACSTR ")", + MAC2STR(drv->auth_bssid), + MAC2STR(drv->bssid)); + } + } + + if (r->flags & WPA_SCAN_ASSOCIATED) { + wpa_printf(MSG_DEBUG, "nl80211: Scan results " + "indicate BSS status with " MACSTR + " as associated", + MAC2STR(r->bssid)); + if (drv->nlmode == NL80211_IFTYPE_STATION && + !drv->associated) { + wpa_printf(MSG_DEBUG, "nl80211: Local state " + "(not associated) does not match " + "with BSS state"); + } else if (drv->nlmode == NL80211_IFTYPE_STATION && + os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != + 0) { + wpa_printf(MSG_DEBUG, "nl80211: Local state " + "(associated with " MACSTR ") does " + "not match with BSS state", + MAC2STR(r->bssid)); + } + } + } +} + + /** * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results * @priv: Pointer to private wext data from wpa_driver_nl80211_init() @@ -1711,6 +1776,7 @@ wpa_driver_nl80211_get_scan_results(void *priv) if (ret == 0) { wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)", (unsigned long) res->num); + wpa_driver_nl80211_check_bss_status(drv, res); return res; } wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " @@ -2018,6 +2084,7 @@ static int wpa_driver_nl80211_authenticate( int count = 0; drv->associated = 0; + os_memset(drv->auth_bssid, 0, ETH_ALEN); if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA) < 0) return -1;