From: Shivani Baranwal Date: Thu, 8 Sep 2022 14:44:11 +0000 (+0530) Subject: MLD STA: Fetch MLO connection info into core wpa_supplicant X-Git-Tag: hostap_2_11~1713 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7784964cbe885d10ae424206e8dac712db3fdb4e;p=thirdparty%2Fhostap.git MLD STA: Fetch MLO connection info into core wpa_supplicant Add support to fetch MLO connection info from the driver to the wpa_supplicant instance of corresponding MLD STA interface. In addition, return true for BSSs associated with MLO links from wpa_bss_in_use() to avoid getting them cleared from scan results. Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam Signed-off-by: Shivani Baranwal --- diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 42be1bc6f..0852e1082 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4803,6 +4803,17 @@ struct wpa_driver_ops { */ int (*send_pasn_resp)(void *priv, struct pasn_auth *params); + /** + * get_sta_mlo_info - Get the current multi-link association info + * @priv: Private driver interface data + * @mlo: Pointer to fill multi-link association info + * Returns: 0 on success, -1 on failure + * + * This callback is used to fetch multi-link of the current association. + */ + int (*get_sta_mlo_info)(void *priv, + struct driver_sta_mlo_info *mlo_info); + #ifdef CONFIG_TESTING_OPTIONS int (*register_frame)(void *priv, u16 type, const u8 *match, size_t match_len, diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index c5daef49e..4e216d839 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1020,6 +1020,20 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) } +static int nl80211_get_sta_mlo_info(void *priv, + struct driver_sta_mlo_info *mlo_info) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + if (!drv->associated) + return -1; + + os_memcpy(mlo_info, &drv->sta_mlo_info, sizeof(*mlo_info)); + return 0; +} + + static void wpa_driver_nl80211_event_newlink( struct nl80211_global *global, struct wpa_driver_nl80211_data *drv, int ifindex, const char *ifname) @@ -12777,6 +12791,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { #ifdef CONFIG_DPP .dpp_listen = nl80211_dpp_listen, #endif /* CONFIG_DPP */ + .get_sta_mlo_info = nl80211_get_sta_mlo_info, #ifdef CONFIG_TESTING_OPTIONS .register_frame = testing_nl80211_register_frame, .radio_disable = testing_nl80211_radio_disable, diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index eb97a618d..7dcdb9969 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -379,6 +379,8 @@ static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { + int i; + if (bss == wpa_s->current_bss) return 1; @@ -388,9 +390,23 @@ static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) bss->ssid_len) != 0)) return 0; /* SSID has changed */ - return !is_zero_ether_addr(bss->bssid) && - (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 || - os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0); + if (!is_zero_ether_addr(bss->bssid) && + (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 || + os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0)) + return 1; + + if (!wpa_s->valid_links) + return 0; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(wpa_s->valid_links & BIT(i))) + continue; + + if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0) + return 1; + } + + return 0; } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d20e06136..41d353f91 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -1152,4 +1152,14 @@ static inline int wpa_drv_set_secure_ranging_ctx(struct wpa_supplicant *wpa_s, return wpa_s->driver->set_secure_ranging_ctx(wpa_s->drv_priv, ¶ms); } +static inline int +wpas_drv_get_sta_mlo_info(struct wpa_supplicant *wpa_s, + struct driver_sta_mlo_info *mlo_info) +{ + if (!wpa_s->driver->get_sta_mlo_info) + return 0; + + return wpa_s->driver->get_sta_mlo_info(wpa_s->drv_priv, mlo_info); +} + #endif /* DRIVER_I_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b3b2c4932..a9447c59b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -167,6 +167,21 @@ wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid) } +static void wpa_supplicant_update_link_bss(struct wpa_supplicant *wpa_s, + u8 link_id, const u8 *bssid) +{ + struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + + if (!bss) { + wpa_supplicant_update_scan_results(wpa_s); + bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + } + + if (bss) + wpa_s->links[link_id].bss = bss; +} + + static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) { struct wpa_ssid *ssid, *old_ssid; @@ -285,6 +300,19 @@ void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx) } +static void wpas_reset_mlo_info(struct wpa_supplicant *wpa_s) +{ + int i; + + if (!wpa_s->valid_links) + return; + + wpa_s->valid_links = 0; + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) + wpa_s->links[i].bss = NULL; +} + + void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { int bssid_changed; @@ -352,6 +380,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0) wpa_s->enabled_4addr_mode = 0; + + wpas_reset_mlo_info(wpa_s); } @@ -3325,6 +3355,60 @@ static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s, } +static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s) +{ + struct driver_sta_mlo_info mlo; + int i; + + mlo.valid_links = 0; + if (wpas_drv_get_sta_mlo_info(wpa_s, &mlo)) { + wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO link info"); + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + return -1; + } + + if (wpa_s->valid_links == mlo.valid_links) { + bool match = true; + + if (!mlo.valid_links) + return 0; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(mlo.valid_links & BIT(i))) + continue; + + if (os_memcmp(wpa_s->links[i].addr, mlo.links[i].addr, + ETH_ALEN) != 0 || + os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid, + ETH_ALEN) != 0) { + match = false; + break; + } + } + + if (match && + os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr, + ETH_ALEN) == 0) + return 0; + } + + wpa_s->valid_links = mlo.valid_links; + os_memcpy(wpa_s->ap_mld_addr, mlo.ap_mld_addr, ETH_ALEN); + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(wpa_s->valid_links & BIT(i))) + continue; + + os_memcpy(wpa_s->links[i].addr, mlo.links[i].addr, ETH_ALEN); + os_memcpy(wpa_s->links[i].bssid, mlo.links[i].bssid, ETH_ALEN); + wpa_s->links[i].freq = mlo.links[i].freq; + wpa_supplicant_update_link_bss(wpa_s, i, mlo.links[i].bssid); + } + + return 0; +} + + static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { @@ -3360,6 +3444,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, return; } + if (wpa_drv_get_mlo_info(wpa_s) < 0) { + wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO connection info"); + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + return; + } + if (ft_completed && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION)) { wpa_msg(wpa_s, MSG_INFO, "Attempt to roam to " MACSTR, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 84a22a296..813e5ac1b 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -739,6 +739,14 @@ struct wpa_supplicant { struct wpa_bss *current_bss; int ap_ies_from_associnfo; unsigned int assoc_freq; + u8 ap_mld_addr[ETH_ALEN]; + u8 valid_links; /* bitmap of valid MLO link IDs */ + struct { + u8 addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + unsigned int freq; + struct wpa_bss *bss; + } links[MAX_NUM_MLD_LINKS]; u8 *last_con_fail_realm; size_t last_con_fail_realm_len;