diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 3f3f2a633..fce0922cd 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1936,7 +1936,7 @@ static void hostapd_event_wds_sta_interface_status(struct hostapd_data *hapd, #ifdef CONFIG_OWE static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, const u8 *ie, - size_t ie_len) + size_t ie_len, const u8 *link_addr) { u16 status; struct sta_info *sta; @@ -1986,15 +1986,31 @@ static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, } sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); +#ifdef CONFIG_IEEE80211BE + if (link_addr) { + struct mld_info *info = &sta->mld_info; + u8 link_id = hapd->mld_link_id; + + info->mld_sta = true; + sta->mld_assoc_link_id = link_id;; + os_memcpy(info->common_info.mld_addr, peer, ETH_ALEN); + info->links[link_id].valid = true; + os_memcpy(info->links[link_id].local_addr, hapd->own_addr, + ETH_ALEN); + os_memcpy(info->links[link_id].peer_addr, link_addr, ETH_ALEN); + } +#endif /* CONFIG_IEEE80211BE */ + status = owe_process_rsn_ie(hapd, sta, elems.rsn_ie, elems.rsn_ie_len, elems.owe_dh, - elems.owe_dh_len); + elems.owe_dh_len, link_addr); if (status != WLAN_STATUS_SUCCESS) ap_free_sta(hapd, sta); return 0; err: - hostapd_drv_update_dh_ie(hapd, peer, status, NULL, 0); + hostapd_drv_update_dh_ie(hapd, link_addr ? link_addr : peer, status, + NULL, 0); return 0; } #endif /* CONFIG_OWE */ @@ -2113,9 +2129,22 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_UPDATE_DH: if (!data) return; +#ifdef CONFIG_IEEE80211BE + if (data->update_dh.assoc_link_id != -1) { + hapd = hostapd_mld_get_link_bss( + hapd, data->update_dh.assoc_link_id); + if (!hapd) { + wpa_printf(MSG_ERROR, + "MLD: Failed to get link BSS for EVENT_UPDATE_DH assoc_link_id=%d", + data->update_dh.assoc_link_id); + return; + } + } +#endif /* CONFIG_IEEE80211BE */ hostapd_notif_update_dh_ie(hapd, data->update_dh.peer, data->update_dh.ie, - data->update_dh.ie_len); + data->update_dh.ie_len, + data->update_dh.link_addr); break; #endif /* CONFIG_OWE */ case EVENT_DISASSOC: diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 087603810..d40a821fe 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3697,7 +3697,8 @@ u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer, u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta, const u8 *rsn_ie, size_t rsn_ie_len, - const u8 *owe_dh, size_t owe_dh_len) + const u8 *owe_dh, size_t owe_dh_len, + const u8 *link_addr) { u16 status; u8 *owe_buf, ie[256 * 2]; @@ -3719,6 +3720,11 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd, status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto end; } +#ifdef CONFIG_IEEE80211BE + if (sta->mld_info.mld_sta) + wpa_auth_set_ml_info(sta->wpa_sm, hapd->mld_addr, + sta->mld_assoc_link_id, &sta->mld_info); +#endif /* CONFIG_IEEE80211BE */ rsn_ie -= 2; rsn_ie_len += 2; res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, @@ -3763,8 +3769,9 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd, end: wpa_printf(MSG_DEBUG, "OWE: Update status %d, ie len %d for peer " MACSTR, status, (unsigned int) ie_len, - MAC2STR(sta->addr)); - hostapd_drv_update_dh_ie(hapd, sta->addr, status, + MAC2STR(link_addr ? link_addr : sta->addr)); + hostapd_drv_update_dh_ie(hapd, link_addr ? link_addr : sta->addr, + status, status == WLAN_STATUS_SUCCESS ? ie : NULL, ie_len); diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 71e0074c6..4e7d8fbe8 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -187,7 +187,8 @@ u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta, u8 *owe_buf, size_t owe_buf_len, u16 *status); u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta, const u8 *rsn_ie, size_t rsn_ie_len, - const u8 *owe_dh, size_t owe_dh_len); + const u8 *owe_dh, size_t owe_dh_len, + const u8 *link_addr); u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer, const u8 *rsn_ie, size_t rsn_ie_len, const u8 *owe_dh, size_t owe_dh_len); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 8e462c8b7..ece5f1259 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -6602,6 +6602,8 @@ union wpa_event_data { const u8 *peer; const u8 *ie; size_t ie_len; + int assoc_link_id; + const u8 *link_addr; } update_dh; /** diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index e7aff260d..b58eb80d5 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1905,6 +1905,8 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv, struct nlattr *tb[]) { union wpa_event_data data; + u8 *addr, *link_addr = NULL; + int assoc_link_id = -1; if (!is_ap_interface(drv->nlmode)) return; @@ -1912,9 +1914,37 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv, return; os_memset(&data, 0, sizeof(data)); - data.update_dh.peer = nla_data(tb[NL80211_ATTR_MAC]); + addr = nla_data(tb[NL80211_ATTR_MAC]); + + if (bss->links[0].link_id == NL80211_DRV_LINK_ID_NA && + (tb[NL80211_ATTR_MLO_LINK_ID] || + tb[NL80211_ATTR_MLD_ADDR])) { + wpa_printf(MSG_ERROR, + "nl80211: Link info not expected for DH event for non-MLD AP"); + return; + } + + if (tb[NL80211_ATTR_MLO_LINK_ID]) { + assoc_link_id = nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]); + wpa_printf(MSG_DEBUG, + "nl80211: STA assoc link ID %d in UPDATE_OWE_INFO event", + assoc_link_id); + + if (assoc_link_id != NL80211_DRV_LINK_ID_NA && + tb[NL80211_ATTR_MLD_ADDR]) { + link_addr = addr; + addr = nla_data(tb[NL80211_ATTR_MLD_ADDR]); + wpa_printf(MSG_DEBUG, + "nl80211: STA assoc link addr " MACSTR, + MAC2STR(link_addr)); + } + } + + data.update_dh.peer = addr; data.update_dh.ie = nla_data(tb[NL80211_ATTR_IE]); data.update_dh.ie_len = nla_len(tb[NL80211_ATTR_IE]); + data.update_dh.assoc_link_id = assoc_link_id; + data.update_dh.link_addr = link_addr; wpa_printf(MSG_DEBUG, "nl80211: DH event - peer " MACSTR, MAC2STR(data.update_dh.peer));