aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/driver.h2
-rw-r--r--src/drivers/driver_nl80211.c67
2 files changed, 69 insertions, 0 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a605f12..8b63d54 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 77245eb..c4db1a2 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;