AP: Handle re-association from a non-AP MLD
When processing a (Re)Association Request frame and no corresponding station is found, try to find the station using the station MLD MAC address from the Basic ML element, as it is possible that the station is trying to re-associate but with a different link address (in such a case the underlying driver would not perform address translations). When sending the (Re)Association Response frame, use the addresses from the (Re)Association Request frame and not the AP MLD MAC address, again, to avoid the address translation done in the driver. Signed-off-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
parent
a18f8ee0f5
commit
e996704201
3 changed files with 163 additions and 5 deletions
|
@ -85,6 +85,11 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||
int rssi, int from_queue);
|
||||
static int add_associated_sta(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int reassoc);
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
static struct sta_info *
|
||||
hostapd_ml_get_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
struct hostapd_data **assoc_hapd);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
|
||||
|
@ -4709,7 +4714,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||
static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 status_code, int reassoc,
|
||||
const u8 *ies, size_t ies_len, int rssi,
|
||||
int omit_rsnxe)
|
||||
int omit_rsnxe, bool allow_mld_addr_trans)
|
||||
{
|
||||
int send_len;
|
||||
u8 *buf;
|
||||
|
@ -4759,7 +4764,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
* Once a non-AP MLD is added to the driver, the addressing should use
|
||||
* MLD MAC address.
|
||||
*/
|
||||
if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta)
|
||||
if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta &&
|
||||
allow_mld_addr_trans)
|
||||
sa = hapd->mld_addr;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
@ -5125,7 +5131,8 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
|
||||
sta->fils_pending_assoc_is_reassoc,
|
||||
sta->fils_pending_assoc_req,
|
||||
sta->fils_pending_assoc_req_len, 0, 0);
|
||||
sta->fils_pending_assoc_req_len, 0, 0,
|
||||
true);
|
||||
os_free(sta->fils_pending_assoc_req);
|
||||
sta->fils_pending_assoc_req = NULL;
|
||||
sta->fils_pending_assoc_req_len = 0;
|
||||
|
@ -5160,6 +5167,48 @@ void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
|
|||
#endif /* CONFIG_FILS */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
static struct sta_info * handle_mlo_translate(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
size_t len, bool reassoc,
|
||||
struct hostapd_data **assoc_hapd)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee802_11_elems elems;
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
const u8 *pos;
|
||||
|
||||
if (!hapd->iconf->ieee80211be || hapd->conf->disable_11be)
|
||||
return NULL;
|
||||
|
||||
if (reassoc) {
|
||||
len -= IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req);
|
||||
pos = mgmt->u.reassoc_req.variable;
|
||||
} else {
|
||||
len -= IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req);
|
||||
pos = mgmt->u.assoc_req.variable;
|
||||
}
|
||||
|
||||
if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
|
||||
return NULL;
|
||||
|
||||
if (hostapd_process_ml_assoc_req_addr(hapd, elems.basic_mle,
|
||||
elems.basic_mle_len,
|
||||
mld_addr))
|
||||
return NULL;
|
||||
|
||||
sta = ap_get_sta(hapd, mld_addr);
|
||||
if (!sta)
|
||||
return NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "MLD: assoc: mld=" MACSTR ", link=" MACSTR,
|
||||
MAC2STR(mld_addr), MAC2STR(mgmt->sa));
|
||||
|
||||
return hostapd_ml_get_assoc_sta(hapd, sta, assoc_hapd);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
static void handle_assoc(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||
int reassoc, int rssi)
|
||||
|
@ -5176,6 +5225,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_FILS */
|
||||
int omit_rsnxe = 0;
|
||||
bool set_beacon = false;
|
||||
bool mld_addrs_not_translated = false;
|
||||
|
||||
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
||||
sizeof(mgmt->u.assoc_req))) {
|
||||
|
@ -5233,6 +5283,28 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
/*
|
||||
* It is possible that the association frame is from an associated
|
||||
* non-AP MLD station, that tries to re-associate using different link
|
||||
* addresses. In such a case, try to find the station based on the AP
|
||||
* MLD MAC address.
|
||||
*/
|
||||
if (!sta) {
|
||||
struct hostapd_data *assoc_hapd;
|
||||
|
||||
sta = handle_mlo_translate(hapd, mgmt, len, reassoc,
|
||||
&assoc_hapd);
|
||||
if (sta) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Switching to assoc hapd/station");
|
||||
hapd = assoc_hapd;
|
||||
mld_addrs_not_translated = true;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (sta && sta->auth_alg == WLAN_AUTH_FT &&
|
||||
(sta->flags & WLAN_STA_AUTH) == 0) {
|
||||
|
@ -5553,8 +5625,12 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_FILS */
|
||||
|
||||
if (resp >= 0)
|
||||
reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc,
|
||||
pos, left, rssi, omit_rsnxe);
|
||||
reply_res = send_assoc_resp(hapd,
|
||||
mld_addrs_not_translated ?
|
||||
NULL : sta,
|
||||
mgmt->sa, resp, reassoc,
|
||||
pos, left, rssi, omit_rsnxe,
|
||||
!mld_addrs_not_translated);
|
||||
os_free(tmp);
|
||||
|
||||
/*
|
||||
|
|
|
@ -104,6 +104,9 @@ const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd,
|
|||
u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
|
||||
struct ieee802_11_elems *elems,
|
||||
struct sta_info *sta);
|
||||
int hostapd_process_ml_assoc_req_addr(struct hostapd_data *hapd,
|
||||
const u8 *basic_mle, size_t basic_mle_len,
|
||||
u8 *mld_addr);
|
||||
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab);
|
||||
|
|
|
@ -1050,6 +1050,85 @@ static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
int hostapd_process_ml_assoc_req_addr(struct hostapd_data *hapd,
|
||||
const u8 *basic_mle, size_t basic_mle_len,
|
||||
u8 *mld_addr)
|
||||
{
|
||||
struct wpabuf *mlbuf = ieee802_11_defrag(basic_mle, basic_mle_len,
|
||||
true);
|
||||
struct ieee80211_eht_ml *ml;
|
||||
struct eht_ml_basic_common_info *common_info;
|
||||
size_t ml_len, common_info_len;
|
||||
int ret = -1;
|
||||
u16 ml_control;
|
||||
|
||||
if (!mlbuf)
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
|
||||
ml = (struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
|
||||
ml_len = wpabuf_len(mlbuf);
|
||||
|
||||
if (ml_len < sizeof(*ml))
|
||||
goto out;
|
||||
|
||||
ml_control = le_to_host16(ml->ml_control);
|
||||
if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) !=
|
||||
MULTI_LINK_CONTROL_TYPE_BASIC) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: Invalid ML type=%u",
|
||||
ml_control & MULTI_LINK_CONTROL_TYPE_MASK);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Common Info Length and MLD MAC Address must always be present */
|
||||
common_info_len = 1 + ETH_ALEN;
|
||||
|
||||
if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: Link ID Info not expected");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: BSS Parameters Change Count not expected");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Medium Synchronization Delay Information not expected");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA)
|
||||
common_info_len += 2;
|
||||
|
||||
if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA)
|
||||
common_info_len += 2;
|
||||
|
||||
if (sizeof(*ml) + common_info_len > ml_len) {
|
||||
wpa_printf(MSG_DEBUG, "MLD: Not enough bytes for common info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
common_info = (struct eht_ml_basic_common_info *) ml->variable;
|
||||
|
||||
/* Common information length includes the length octet */
|
||||
if (common_info->len != common_info_len) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MLD: Invalid common info len=%u", common_info->len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the MLD MAC Address */
|
||||
os_memcpy(mld_addr, common_info->mld_addr, ETH_ALEN);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
wpabuf_free(mlbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
|
||||
struct ieee802_11_elems *elems,
|
||||
struct sta_info *sta)
|
||||
|
|
Loading…
Reference in a new issue