From 50eb6cd3e5cb4ee8a2cd324f938effad54e75c97 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Fri, 21 Apr 2023 16:55:35 +0800
Subject: [PATCH 50/54] hostapd: mtk: handle two-link setup with link address

Switch to use link address during setup, and maintain a mapping of link
address to sta_info.

Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
 src/ap/hostapd.h             |  1 +
 src/ap/ieee802_11.c          | 26 ++++++++++++++++++++------
 src/ap/sta_info.c            | 12 +++++++++++-
 src/ap/sta_info.h            |  1 +
 src/drivers/driver_nl80211.c | 22 +++++++++++++---------
 5 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 3dba7ab3e..a04f195ab 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -208,6 +208,7 @@ struct hostapd_data {
 #define STA_HASH_SIZE 256
 #define STA_HASH(sta) (sta[5])
 	struct sta_info *sta_hash[STA_HASH_SIZE];
+	struct sta_info *link_to_sta_hash[STA_HASH_SIZE];
 
 	/*
 	 * Bitfield for indicating which AIDs are allocated. Only AID values
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 3c47539df..7e54bb4c1 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -407,7 +407,8 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
 	 * handle the translations
 	 */
 	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) {
-		sa = hapd->mld_addr;
+		/* use link addr */
+		/* sa = hapd->mld_addr; */
 
 		ml_resp = hostapd_ml_auth_resp(hapd);
 		if (!ml_resp)
@@ -3060,6 +3061,11 @@ static void handle_auth(struct hostapd_data *hapd,
 			resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 			goto fail;
 		}
+
+		/* store setup link addr */
+		os_memcpy(sta->setup_addr, mgmt->sa, ETH_ALEN);
+		wpa_printf(MSG_INFO, "setup addr: " MACSTR, MAC2STR(sta->setup_addr));
+		hapd->link_to_sta_hash[STA_HASH(mgmt->sa)] = sta;
 	}
 
 #ifdef CONFIG_IEEE80211BE
@@ -3233,7 +3239,9 @@ static void handle_auth(struct hostapd_data *hapd,
 	  * handle the translations
 	  */
 	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) {
-		dst = sta->addr;
+		/* use link addr */
+		/* dst = sta->addr; */
+		dst = sta->setup_addr;
 		bssid = hapd->mld_addr;
 	}
 #endif /* CONFIG_IEEE80211BE */
@@ -4750,8 +4758,9 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 	 * Once an non-AP MLD station is added to the driver, the addressing
 	 * should use MLD address.
 	 */
-	if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta)
-		sa = hapd->mld_addr;
+	/* use link addr */
+	/* if (hapd->conf->mld_ap && sta && sta->mld_info.mld_sta) */
+	/* 	sa = hapd->mld_addr; */
 #endif /* CONFIG_IEEE80211BE */
 
 	os_memcpy(reply->da, addr, ETH_ALEN);
@@ -5158,7 +5167,7 @@ static void handle_assoc(struct hostapd_data *hapd,
 	u16 capab_info, listen_interval, seq_ctrl, fc;
 	int resp = WLAN_STATUS_SUCCESS;
 	u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
-	const u8 *pos;
+	const u8 *pos, *sa;
 	int left, i, ubus_resp;
 	struct sta_info *sta;
 	u8 *tmp = NULL;
@@ -5546,8 +5555,13 @@ static void handle_assoc(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_FILS */
 
+	if (sta->mld_info.mld_sta)
+		sa = sta->setup_addr;
+	else
+		sa = mgmt->sa;
+
 	if (resp >= 0)
-		reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc,
+		reply_res = send_assoc_resp(hapd, sta, sa, resp, reassoc,
 					    pos, left, rssi, omit_rsnxe);
 	os_free(tmp);
 
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index e57bd2a6c..93070b709 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -73,7 +73,17 @@ struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
 	s = hapd->sta_hash[STA_HASH(sta)];
 	while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
 		s = s->hnext;
-	return s;
+	if (s)
+		return s;
+
+	/* check if sta is a setup link address */
+	s = hapd->link_to_sta_hash[STA_HASH(sta)];
+	if (s && hapd->conf->mld_ap && s->mld_info.mld_sta) {
+		if (!os_memcmp(s->setup_addr, sta, 6))
+			return s;
+	}
+
+	return NULL;
 }
 
 
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index e6b68818a..233590e4e 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -102,6 +102,7 @@ struct sta_info {
 	struct sta_info *next; /* next entry in sta list */
 	struct sta_info *hnext; /* next entry in hash table list */
 	u8 addr[6];
+	u8 setup_addr[6];
 	be32 ipaddr;
 	struct dl_list ip6addr; /* list head for struct ip6addr */
 	u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5672a5f56..12aba1fec 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -167,7 +167,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  const u8 *buf, size_t buf_len,
 				  int save_cookie,
 				  int no_cck, int no_ack, int offchanok,
-				  const u16 *csa_offs, size_t csa_offs_len);
+				  const u16 *csa_offs, size_t csa_offs_len,
+				  int link_id);
 static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
 					       int report);
 static int nl80211_put_freq_params(struct nl_msg *msg,
@@ -4339,10 +4340,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR
-		   " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u no_encrypt=%d fc=0x%x (%s) nlmode=%d",
-		   MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
-		   no_encrypt, fc, fc2str(fc), drv->nlmode);
+	wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR" sa=" MACSTR
+		   " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u no_encrypt=%d fc=0x%x (%s) nlmode=%d link_id=%d",
+		   MAC2STR(mgmt->da), MAC2STR(mgmt->sa), noack, freq, no_cck, offchanok, wait_time,
+		   no_encrypt, fc, fc2str(fc), drv->nlmode, link_id);
 
 	if ((is_sta_interface(drv->nlmode) ||
 	     drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
@@ -4466,7 +4467,7 @@ send_frame_cmd:
 	wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame_cmd");
 	res = nl80211_send_frame_cmd(bss, freq, wait_time, data, data_len,
 				     use_cookie, no_cck, noack, offchanok,
-				     csa_offs, csa_offs_len);
+				     csa_offs, csa_offs_len, link_id);
 	if (!res)
 		drv->send_frame_link_id = link_id;
 
@@ -8317,7 +8318,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
 	return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
 					    IEEE80211_HDRLEN +
 					    sizeof(mgmt.u.deauth), 0, 0, 0, 0,
-					    0, NULL, 0, 0, -1);
+					    0, NULL, 0, 0, link_id);
 }
 
 
@@ -9079,7 +9080,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  const u8 *buf, size_t buf_len,
 				  int save_cookie, int no_cck, int no_ack,
 				  int offchanok, const u16 *csa_offs,
-				  size_t csa_offs_len)
+				  size_t csa_offs_len, int link_id)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
@@ -9104,6 +9105,9 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
 	    nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
 		goto fail;
 
+	if (link_id != -1 && nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
+		goto fail;
+
 	cookie = 0;
 	ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL);
 	msg = NULL;
@@ -9218,7 +9222,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
 	else
 		ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
 					     24 + data_len,
-					     1, no_cck, 0, offchanok, NULL, 0);
+					     1, no_cck, 0, offchanok, NULL, 0, -1);
 
 	os_free(buf);
 	return ret;
-- 
2.39.2

