diff options
Diffstat (limited to 'external/wpa_supplicant/src/drivers/driver_nl80211.c')
-rw-r--r-- | external/wpa_supplicant/src/drivers/driver_nl80211.c | 70 |
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; |