]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MLD: Clear group keys for removed links
authorKavita Kavita <quic_kkavita@quicinc.com>
Fri, 9 May 2025 15:50:30 +0000 (21:20 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 2 Jun 2025 14:02:27 +0000 (17:02 +0300)
For AP link removal case, group keys (e.g., GTK, IGTK, BIGTK, etc.) were
not cleared for links that were removed in the NL80211_CMD_LINKS_REMOVED
event. Since the links are already removed, we should clear the keys
associated with these links for proper cleanup.

This functionality was missing in the current implementation, so address
this by clearing group keys for the removed links.

Signed-off-by: Kavita Kavita <quic_kkavita@quicinc.com>
src/drivers/driver_nl80211_event.c
src/rsn_supp/wpa.c

index 9bf9888ae6327bc61aac21f652ba84861580449a..60e5f589244ffb5e821ee4695fd995a1296a656f 100644 (file)
@@ -918,6 +918,47 @@ out:
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
 
+static void mlme_event_link_removal(struct wpa_driver_nl80211_data *drv,
+                                   struct nlattr *mlo_links)
+{
+       struct nlattr *link;
+       u16 removed_links = 0;
+       int rem_links, i;
+
+       if (!mlo_links)
+               return;
+       nla_for_each_nested(link, mlo_links, rem_links) {
+               struct nlattr *tb[NL80211_ATTR_MAX + 1];
+               int link_id;
+
+               nla_parse(tb, NL80211_ATTR_MAX, nla_data(link), nla_len(link),
+                         NULL);
+
+               if (!tb[NL80211_ATTR_MLO_LINK_ID])
+                       continue;
+
+               link_id = nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
+               if (link_id >= MAX_NUM_MLD_LINKS)
+                       continue;
+
+               removed_links |= BIT(link_id);
+       }
+
+       drv->sta_mlo_info.valid_links &= ~removed_links;
+       drv->sta_mlo_info.req_links &= ~removed_links;
+
+       for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+               if (!(removed_links & BIT(i)))
+                       continue;
+
+               os_memset(&drv->sta_mlo_info.links[i], 0,
+                         sizeof(drv->sta_mlo_info.links[i]));
+       }
+
+       wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
+}
+
+
 static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                               enum nl80211_commands cmd, bool qca_roam_auth,
                               struct nlattr *status,
@@ -4308,7 +4349,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
                break;
 #endif /* CONFIG_IEEE80211AX */
        case NL80211_CMD_LINKS_REMOVED:
-               wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
+               mlme_event_link_removal(drv, tb[NL80211_ATTR_MLO_LINKS]);
                break;
        case NL80211_CMD_ASSOC_MLO_RECONF:
                mlme_event_link_addition(drv, nla_data(frame), nla_len(frame));
index 9a046317042becd39a1348035890c4b958e6e5c8..f5319c606f0b7fda472d898eda09d0221f7cb4e7 100644 (file)
@@ -4729,14 +4729,36 @@ void wpa_sm_set_ssid(struct wpa_sm *sm, const u8 *ssid, size_t ssid_len)
 }
 
 
+static void wpa_sm_clear_mlo_group_keys(struct wpa_sm *sm, int link_id)
+{
+       if (!sm)
+               return;
+
+       os_memset(&sm->mlo.links[link_id].gtk, 0,
+                 sizeof(sm->mlo.links[link_id].gtk));
+       os_memset(&sm->mlo.links[link_id].gtk_wnm_sleep, 0,
+                 sizeof(sm->mlo.links[link_id].gtk_wnm_sleep));
+       os_memset(&sm->mlo.links[link_id].igtk, 0,
+                 sizeof(sm->mlo.links[link_id].igtk));
+       os_memset(&sm->mlo.links[link_id].igtk_wnm_sleep, 0,
+                 sizeof(sm->mlo.links[link_id].igtk_wnm_sleep));
+       os_memset(&sm->mlo.links[link_id].bigtk, 0,
+                 sizeof(sm->mlo.links[link_id].bigtk));
+       os_memset(&sm->mlo.links[link_id].bigtk_wnm_sleep, 0,
+                 sizeof(sm->mlo.links[link_id].bigtk_wnm_sleep));
+}
+
+
 int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
 {
        int i;
+       u16 removed_links;
 
        if (!sm)
                return -1;
 
        os_memcpy(sm->mlo.ap_mld_addr, mlo->ap_mld_addr, ETH_ALEN);
+       removed_links = ~mlo->valid_links & sm->mlo.valid_links;
        sm->mlo.assoc_link_id =  mlo->assoc_link_id;
        sm->mlo.valid_links = mlo->valid_links;
        sm->mlo.req_links = mlo->req_links;
@@ -4865,6 +4887,13 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
                        }
                        sm->mlo.links[i].ap_rsnxoe_len = len;
                }
+
+               if (removed_links & BIT(i)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "RSN: Clearing MLO group keys for link[%u]",
+                                  i);
+                       wpa_sm_clear_mlo_group_keys(sm, i);
+               }
        }
 
        return 0;