nl80211: Add support for full station state operations

This provides means for determining whether the driver supports full AP
station state and setting the needed STA flags for using this
functionality.

Signed-off-by: Ayala Beker <ayala.beker@intel.com>
This commit is contained in:
Ayala Beker 2016-02-16 11:54:31 +02:00 committed by Jouni Malinen
parent bccd22f356
commit dc55b6b672
3 changed files with 75 additions and 7 deletions

View file

@ -3748,6 +3748,8 @@ static u32 sta_flags_nl80211(int flags)
f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
if (flags & WPA_STA_AUTHENTICATED)
f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
if (flags & WPA_STA_ASSOCIATED)
f |= BIT(NL80211_STA_FLAG_ASSOCIATED);
return f;
}
@ -3800,7 +3802,17 @@ static int wpa_driver_nl80211_sta_add(void *priv,
if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
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",
@ -3848,9 +3860,12 @@ static int wpa_driver_nl80211_sta_add(void *priv,
/*
* 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;
}
@ -3863,6 +3878,15 @@ static int wpa_driver_nl80211_sta_add(void *priv,
wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
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) {
@ -3893,6 +3917,36 @@ static int wpa_driver_nl80211_sta_add(void *priv,
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))