blob: 0c17b68d5c9d9c4ba7055ef2b41177cd4000308c [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From 11cfbaf42eaadf0fd7b50d13f0b7664c1675dc11 Mon Sep 17 00:00:00 2001
2From: Rameshkumar Sundaram <quic_ramess@quicinc.com>
3Date: Thu, 28 Mar 2024 23:46:46 +0530
4Subject: [PATCH 016/104] hostapd: MLO: Enhance wpa state machine
5
6Add required ML Specific members in wpa_authenticator and struct
7wpa_state_machine to maintain self and partner link information.
8
9Maintain state machine object in all associated link stations and
10destroy/remove references from the same whenever link stations are getting
11removed.
12
13Increase the wpa_group object reference count for all links in which ML
14station is getting associated and release the same whenever link stations
15are getting removed.
16
17Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
18Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
19---
20 src/ap/ieee802_11.c | 9 ++--
21 src/ap/sta_info.c | 35 ++++++++++++++-
22 src/ap/wpa_auth.c | 101 +++++++++++++++++++++++++++++++++++++++++---
23 src/ap/wpa_auth.h | 16 +++++++
24 src/ap/wpa_auth_i.h | 8 ++++
25 5 files changed, 159 insertions(+), 10 deletions(-)
26
27diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
28index 39c63f29b..9d04bdf43 100644
29--- a/src/ap/ieee802_11.c
30+++ b/src/ap/ieee802_11.c
31@@ -4467,6 +4467,8 @@ static int ieee80211_ml_process_link(struct hostapd_data *hapd,
32 }
33
34 sta->flags |= origin_sta->flags | WLAN_STA_ASSOC_REQ_OK;
35+ sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
36+
37 status = __check_assoc_ies(hapd, sta, NULL, 0, &elems, reassoc, true);
38 if (status != WLAN_STATUS_SUCCESS) {
39 wpa_printf(MSG_DEBUG, "MLD: link: Element check failed");
40@@ -4474,7 +4476,6 @@ static int ieee80211_ml_process_link(struct hostapd_data *hapd,
41 }
42
43 ap_sta_set_mld(sta, true);
44- sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
45
46 os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
47 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
48@@ -4501,9 +4502,11 @@ static int ieee80211_ml_process_link(struct hostapd_data *hapd,
49 ieee802_11_update_beacons(hapd->iface);
50 }
51
52- /* RSN Authenticator should always be the one on the original station */
53+ /* Maintain state machine reference on all link STAs, this is needed
54+ * during Group rekey handling.
55+ */
56 wpa_auth_sta_deinit(sta->wpa_sm);
57- sta->wpa_sm = NULL;
58+ sta->wpa_sm = origin_sta->wpa_sm;
59
60 /*
61 * Do not initialize the EAPOL state machine.
62diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
63index 2423ff189..d483aa9d3 100644
64--- a/src/ap/sta_info.c
65+++ b/src/ap/sta_info.c
66@@ -199,6 +199,26 @@ static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
67 hostapd_drv_sta_remove(hapd, sta->addr);
68 }
69
70+#ifdef CONFIG_IEEE80211BE
71+static void set_for_each_partner_link_sta(struct hostapd_data *hapd,
72+ struct sta_info *psta, void *data)
73+{
74+ struct sta_info *lsta;
75+ struct hostapd_data *lhapd;
76+
77+ if (!ap_sta_is_mld(hapd, psta))
78+ return;
79+
80+ for_each_mld_link(lhapd, hapd) {
81+ if (lhapd == hapd)
82+ continue;
83+
84+ lsta = ap_get_sta(lhapd, psta->addr);
85+ if (lsta)
86+ lsta->wpa_sm = data;
87+ }
88+}
89+#endif /* CONFIG_IEEE80211BE */
90
91 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
92 {
93@@ -317,8 +337,17 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
94
95 #ifdef CONFIG_IEEE80211BE
96 if (!ap_sta_is_mld(hapd, sta) ||
97- hapd->mld_link_id == sta->mld_assoc_link_id)
98+ hapd->mld_link_id == sta->mld_assoc_link_id) {
99 wpa_auth_sta_deinit(sta->wpa_sm);
100+ /* Remove refrences from partner links. */
101+ set_for_each_partner_link_sta(hapd, sta, NULL);
102+ }
103+
104+ /* Release group references in case non assoc link STA is removed
105+ * before assoc link STA
106+ */
107+ if (hostapd_sta_is_link_sta(hapd, sta))
108+ wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id);
109 #else
110 wpa_auth_sta_deinit(sta->wpa_sm);
111 #endif /* CONFIG_IEEE80211BE */
112@@ -903,8 +932,10 @@ static void ap_sta_disconnect_common(struct hostapd_data *hapd,
113 ieee802_1x_free_station(hapd, sta);
114 #ifdef CONFIG_IEEE80211BE
115 if (!hapd->conf->mld_ap ||
116- hapd->mld_link_id == sta->mld_assoc_link_id)
117+ hapd->mld_link_id == sta->mld_assoc_link_id) {
118 wpa_auth_sta_deinit(sta->wpa_sm);
119+ set_for_each_partner_link_sta(hapd, sta, NULL);
120+ }
121 #else
122 wpa_auth_sta_deinit(sta->wpa_sm);
123 #endif /* CONFIG_IEEE80211BE */
124diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
125index 0d15c4209..8c1052c25 100644
126--- a/src/ap/wpa_auth.c
127+++ b/src/ap/wpa_auth.c
128@@ -102,6 +102,59 @@ static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
129 return sm->addr;
130 }
131
132+#ifdef CONFIG_IEEE80211BE
133+void wpa_release_link_auth_ref(struct wpa_state_machine *sm, int release_link_id)
134+{
135+ int link_id;
136+
137+ if (!sm || release_link_id >= MAX_NUM_MLD_LINKS)
138+ return;
139+
140+ for_each_sm_auth(sm, link_id)
141+ if (link_id == release_link_id) {
142+ wpa_group_put(sm->mld_links[link_id].wpa_auth,
143+ sm->mld_links[link_id].wpa_auth->group);
144+ sm->mld_links[link_id].wpa_auth = NULL;
145+ }
146+}
147+
148+static int wpa_get_link_sta_auth(struct wpa_authenticator *wpa_auth, void *data)
149+{
150+ struct wpa_get_link_auth_ctx *ctx = data;
151+
152+ if (os_memcmp(wpa_auth->addr, ctx->addr, ETH_ALEN) != 0)
153+ return 0;
154+ ctx->wpa_auth = wpa_auth;
155+ return 1;
156+}
157+
158+static int wpa_get_primary_wpa_auth_cb(struct wpa_authenticator *wpa_auth, void *data)
159+{
160+ struct wpa_get_link_auth_ctx *ctx = data;
161+
162+ if (!wpa_auth->is_ml || os_memcmp(wpa_auth->mld_addr, ctx->addr, ETH_ALEN) != 0 ||
163+ !wpa_auth->primary_auth)
164+ return 0;
165+
166+ ctx->wpa_auth = wpa_auth;
167+ return 1;
168+}
169+
170+static struct wpa_authenticator *
171+wpa_get_primary_wpa_auth(struct wpa_authenticator *wpa_auth)
172+{
173+ struct wpa_get_link_auth_ctx ctx;
174+
175+ if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
176+ return wpa_auth;
177+
178+ ctx.addr = wpa_auth->mld_addr;
179+ ctx.wpa_auth = NULL;
180+ wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_wpa_auth_cb, &ctx);
181+
182+ return ctx.wpa_auth;
183+}
184+#endif /* CONFIG_IEEE80211BE */
185
186 static inline int wpa_auth_mic_failure_report(
187 struct wpa_authenticator *wpa_auth, const u8 *addr)
188@@ -798,6 +851,10 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
189
190 static void wpa_free_sta_sm(struct wpa_state_machine *sm)
191 {
192+#ifdef CONFIG_IEEE80211BE
193+ int link_id;
194+#endif /* CONFIG_IEEE80211BE */
195+
196 #ifdef CONFIG_P2P
197 if (WPA_GET_BE32(sm->ip_addr)) {
198 wpa_printf(MSG_DEBUG,
199@@ -821,6 +878,13 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
200 os_free(sm->last_rx_eapol_key);
201 os_free(sm->wpa_ie);
202 os_free(sm->rsnxe);
203+#ifdef CONFIG_IEEE80211BE
204+ for_each_sm_auth(sm, link_id) {
205+ wpa_group_put(sm->mld_links[link_id].wpa_auth,
206+ sm->mld_links[link_id].wpa_auth->group);
207+ sm->mld_links[link_id].wpa_auth = NULL;
208+ }
209+#endif /* CONFIG_IEEE80211BE */
210 wpa_group_put(sm->wpa_auth, sm->group);
211 #ifdef CONFIG_DPP2
212 wpabuf_clear_free(sm->dpp_z);
213@@ -831,7 +895,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
214
215 void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
216 {
217- struct wpa_authenticator *wpa_auth;
218+ struct wpa_authenticator *wpa_auth, *primary_wpa_auth;
219
220 if (!sm)
221 return;
222@@ -840,10 +904,18 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
223 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
224 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
225 "strict rekeying - force GTK rekey since STA is leaving");
226+
227+#ifdef CONFIG_IEEE80211BE
228+ if (wpa_auth->is_ml && !wpa_auth->primary_auth)
229+ primary_wpa_auth = wpa_get_primary_wpa_auth(wpa_auth);
230+ else
231+#endif /* CONFIG_IEEE80211BE */
232+ primary_wpa_auth = wpa_auth;
233+
234 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
235- wpa_auth, NULL) == -1)
236+ primary_wpa_auth, NULL) == -1)
237 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
238- wpa_auth, NULL);
239+ primary_wpa_auth, NULL);
240 }
241
242 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
243@@ -6835,6 +6907,7 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr,
244 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
245 struct mld_link_info *link = &info->links[link_id];
246 struct mld_link *sm_link = &sm->mld_links[link_id];
247+ struct wpa_get_link_auth_ctx ctx;
248
249 sm_link->valid = link->valid;
250 if (!link->valid)
251@@ -6849,10 +6922,28 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr,
252 MAC2STR(sm_link->own_addr),
253 MAC2STR(sm_link->peer_addr));
254
255- if (link_id != mld_assoc_link_id)
256+ ml_rsn_info.links[i++].link_id = link_id;
257+
258+ if (link_id != mld_assoc_link_id) {
259 sm->n_mld_affiliated_links++;
260+ ctx.addr = link->local_addr;
261+ ctx.wpa_auth = NULL;
262+ wpa_auth_for_each_auth(sm->wpa_auth, wpa_get_link_sta_auth, &ctx);
263+
264+ if (ctx.wpa_auth) {
265+ sm_link->wpa_auth = ctx.wpa_auth;
266+ wpa_group_get(sm_link->wpa_auth,
267+ sm_link->wpa_auth->group);
268+ }
269+ } else {
270+ sm_link->wpa_auth = sm->wpa_auth;
271+ }
272
273- ml_rsn_info.links[i++].link_id = link_id;
274+ if (!sm_link->wpa_auth)
275+ wpa_printf(MSG_ERROR, "Unable to find authenticator object for "
276+ "ML STA " MACSTR " on link " MACSTR " link id %d",
277+ MAC2STR(sm->own_mld_addr), MAC2STR(sm_link->own_addr),
278+ link_id);
279 }
280
281 ml_rsn_info.n_mld_links = i;
282diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
283index c74862307..1446872f3 100644
284--- a/src/ap/wpa_auth.h
285+++ b/src/ap/wpa_auth.h
286@@ -647,4 +647,20 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
287 struct wpa_auth_ml_link_key_info *info,
288 bool mgmt_frame_prot, bool beacon_prot);
289
290+#ifdef CONFIG_IEEE80211BE
291+void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
292+ int release_link_id);
293+
294+#define for_each_sm_auth(sm, link_id) \
295+ for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \
296+ if (sm->mld_links[link_id].valid && \
297+ sm->mld_links[link_id].wpa_auth && \
298+ sm->wpa_auth != sm->mld_links[link_id].wpa_auth) \
299+
300+struct wpa_get_link_auth_ctx {
301+ u8 *addr;
302+ struct wpa_authenticator *wpa_auth;
303+};
304+#endif /* CONFIG_IEEE80211BE */
305+
306 #endif /* WPA_AUTH_H */
307diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
308index 9ba830415..9ba90749d 100644
309--- a/src/ap/wpa_auth_i.h
310+++ b/src/ap/wpa_auth_i.h
311@@ -186,6 +186,7 @@ struct wpa_state_machine {
312 size_t rsne_len;
313 const u8 *rsnxe;
314 size_t rsnxe_len;
315+ struct wpa_authenticator *wpa_auth;
316 } mld_links[MAX_NUM_MLD_LINKS];
317 #endif /* CONFIG_IEEE80211BE */
318 };
319@@ -262,6 +263,13 @@ struct wpa_authenticator {
320 #ifdef CONFIG_P2P
321 struct bitfield *ip_pool;
322 #endif /* CONFIG_P2P */
323+
324+#ifdef CONFIG_IEEE80211BE
325+ bool is_ml;
326+ u8 mld_addr[ETH_ALEN];
327+ u8 link_id;
328+ bool primary_auth;
329+#endif /* CONFIG_IEEE80211BE */
330 };
331
332
333--
3342.39.2
335