summaryrefslogtreecommitdiff
path: root/external/wpa_supplicant/src/drivers/driver_nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/wpa_supplicant/src/drivers/driver_nl80211.c')
-rw-r--r--external/wpa_supplicant/src/drivers/driver_nl80211.c70
1 files changed, 67 insertions, 3 deletions
diff --git a/external/wpa_supplicant/src/drivers/driver_nl80211.c b/external/wpa_supplicant/src/drivers/driver_nl80211.c
index 31e6df82..8397866d 100644
--- a/external/wpa_supplicant/src/drivers/driver_nl80211.c
+++ b/external/wpa_supplicant/src/drivers/driver_nl80211.c
@@ -3270,6 +3270,9 @@ static u32 sta_flags_nl80211(int flags)
if (flags & WPA_STA_AUTHENTICATED) {
f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
}
+ if (flags & WPA_STA_ASSOCIATED)
+ f |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+
return f;
}
@@ -3317,7 +3320,19 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct hostapd_sta_add_params
goto fail;
}
- if (!params->set || (params->flags & WPA_STA_TDLS_PEER)) {
+
+ /*
+ * Set the below properties only in one of the following cases:
+ * 1. New station is added, already associated.
+ * 2. Set WPA_STA_TDLS_PEER station.
+ * 3. Set an already added unassociated station, if driver supports
+ * full AP client state. (Set these properties after station became
+ * associated will be rejected by the driver).
+ */
+ if (!params->set || (params->flags & WPA_STA_TDLS_PEER) ||
+ (params->set && FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
+ (params->flags & WPA_STA_ASSOCIATED))) {
+
wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates, params->supp_rates_len);
wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability);
if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, params->supp_rates) || nla_put_u16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability)) {
@@ -3344,7 +3359,14 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct hostapd_sta_add_params
goto fail;
}
}
+ if (is_ap_interface(drv->nlmode) &&
+ nla_put_u8(msg, NL80211_ATTR_STA_SUPPORT_P2P_PS,
+ params->support_p2p_ps ?
+ NL80211_P2P_PS_SUPPORTED :
+ NL80211_P2P_PS_UNSUPPORTED))
+ goto fail;
}
+
if (!params->set) {
if (params->aid) {
wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
@@ -3355,9 +3377,13 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct hostapd_sta_add_params
/*
* cfg80211 validates that AID is non-zero, so we have
* to make this a non-zero value for the TDLS case where
- * a dummy STA entry is used for now.
+ * a dummy STA entry is used for now and for a station
+ * that is still not associated.
*/
- wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
+ wpa_printf(MSG_DEBUG, " * aid=1 (%s workaround)",
+ (params->flags & WPA_STA_TDLS_PEER) ?
+ "TDLS" : "UNASSOC_STA");
+
if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1)) {
goto fail;
}
@@ -3371,6 +3397,15 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct hostapd_sta_add_params
if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid)) {
goto fail;
}
+ } else if (FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
+ (params->flags & WPA_STA_ASSOCIATED)) {
+ wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
+ wpa_printf(MSG_DEBUG, " * listen_interval=%u",
+ params->listen_interval);
+ if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid) ||
+ nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
+ params->listen_interval))
+ goto fail;
}
if (params->vht_opmode_enabled) {
@@ -3397,6 +3432,35 @@ static int wpa_driver_nl80211_sta_add(void *priv, struct hostapd_sta_add_params
os_memset(&upd, 0, sizeof(upd));
upd.set = sta_flags_nl80211(params->flags);
upd.mask = upd.set | sta_flags_nl80211(params->flags_mask);
+ /*
+ * If the driver doesn't support full AP client state, ignore ASSOC/AUTH
+ * flags, as nl80211 driver moves a new station, by default, into
+ * associated state.
+ *
+ * On the other hand, if the driver supports that feature and the
+ * station is added in unauthenticated state, set the
+ * authenticated/associated bits in the mask to prevent moving this
+ * station to associated state before it is actually associated.
+ *
+ * This is irrelevant for mesh mode where the station is added to the
+ * driver as authenticated already, and ASSOCIATED isn't part of the
+ * nl80211 API.
+ */
+ if (!is_mesh_interface(drv->nlmode)) {
+ if (!FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore ASSOC/AUTH flags since driver doesn't support full AP client state");
+ upd.mask &= ~(BIT(NL80211_STA_FLAG_ASSOCIATED) |
+ BIT(NL80211_STA_FLAG_AUTHENTICATED));
+ } else if (!params->set &&
+ !(params->flags & WPA_STA_TDLS_PEER)) {
+ if (!(params->flags & WPA_STA_AUTHENTICATED))
+ upd.mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+ if (!(params->flags & WPA_STA_ASSOCIATED))
+ upd.mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+ }
+ }
+
wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x", upd.set, upd.mask);
if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) {
goto fail;