Skip to content

Commit 5da7d7f

Browse files
Venkat ChimataVenkat Chimata
authored andcommitted
hostapd / mediatek: store RADIUS Class per STA instead of
EAPOL SM; preserve Class for ACL/MAC auth and accounting Move storage of RADIUS Class attributes from the EAPOL state machine to struct sta_info and update all users accordingly. Previously, Class was kept only in eapol_state_machine->radius_class, which caused Class to be lost for authentication paths where eapol_sm is not created. As a result, Accounting messages and PMKSA cache operations could miss the Class attribute. This change makes sta_info->radius_class the single source of truth for RADIUS Class attributes and ensures they are preserved and echoed in Accounting regardless of whether an EAPOL state machine exists. Signed-off-by: Venkat Chimata <venkat@nearhop.com>
1 parent 5a5c031 commit 5da7d7f

1 file changed

Lines changed: 368 additions & 0 deletions

File tree

Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
From 74e2910a10a70201291608ba094423e3c5289845 Mon Sep 17 00:00:00 2001
2+
From: Venkat Chimata <venkat@nearhop.com>
3+
Date: Mon, 2 Feb 2026 12:35:08 +0530
4+
Subject: [PATCH] hostapd / mediatek: store RADIUS Class per STA instead of
5+
EAPOL SM; preserve Class for ACL/MAC auth and accounting
6+
7+
Move storage of RADIUS Class attributes from the EAPOL state machine to
8+
struct sta_info and update all users accordingly. Previously, Class was
9+
kept only in eapol_state_machine->radius_class, which caused Class to be
10+
lost for authentication paths where eapol_sm is not created. As a result,
11+
Accounting messages and PMKSA cache operations could miss the
12+
Class attribute.
13+
14+
This change makes sta_info->radius_class the single source of truth for
15+
RADIUS Class attributes and ensures they are preserved and echoed in
16+
Accounting regardless of whether an EAPOL state machine exists.
17+
18+
Signed-off-by: Venkat Chimata <venkat@nearhop.com>
19+
---
20+
src/ap/accounting.c | 3 +-
21+
src/ap/ieee802_11.c | 65 ++++++++++++++++++++++++++++++
22+
src/ap/ieee802_11.h | 5 +++
23+
src/ap/ieee802_11_auth.c | 3 ++
24+
src/ap/ieee802_1x.c | 69 +-------------------------------
25+
src/ap/ieee802_1x.h | 2 -
26+
src/ap/pmksa_cache_auth.c | 10 ++---
27+
src/ap/sta_info.c | 2 +
28+
src/ap/sta_info.h | 2 +
29+
src/eapol_auth/eapol_auth_sm_i.h | 1 -
30+
10 files changed, 86 insertions(+), 76 deletions(-)
31+
32+
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
33+
index 9fc1886..99f8ac9 100644
34+
--- a/src/ap/accounting.c
35+
+++ b/src/ap/accounting.c
36+
@@ -15,6 +15,7 @@
37+
#include "radius/radius.h"
38+
#include "radius/radius_client.h"
39+
#include "hostapd.h"
40+
+#include "ieee802_11.h"
41+
#include "ieee802_1x.h"
42+
#include "ap_config.h"
43+
#include "sta_info.h"
44+
@@ -102,7 +103,7 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
45+
46+
if (sta) {
47+
for (i = 0; ; i++) {
48+
- val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
49+
+ val = radius_get_class(sta, &len,
50+
i);
51+
if (val == NULL)
52+
break;
53+
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
54+
index ac6e8e4..ad4f524 100644
55+
--- a/src/ap/ieee802_11.c
56+
+++ b/src/ap/ieee802_11.c
57+
@@ -10,6 +10,7 @@
58+
59+
#ifndef CONFIG_NATIVE_WINDOWS
60+
61+
+#include<stdint.h>
62+
#include "utils/common.h"
63+
#include "utils/eloop.h"
64+
#include "crypto/crypto.h"
65+
@@ -8018,4 +8019,68 @@ void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
66+
/* TODO: 320 MHz */
67+
}
68+
69+
+void radius_store_class(struct hostapd_data *hapd,
70+
+ struct sta_info *sta,
71+
+ struct radius_msg *msg)
72+
+{
73+
+ u8 *attr_class;
74+
+ size_t class_len;
75+
+ int count, i;
76+
+ struct radius_attr_data *nclass;
77+
+ size_t nclass_count;
78+
+
79+
+ if (!hapd->conf->radius->acct_server || !hapd->radius)
80+
+ return;
81+
+
82+
+ radius_free_class(&sta->radius_class);
83+
+ count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
84+
+ if (count <= 0)
85+
+ return;
86+
+
87+
+ nclass = os_calloc(count, sizeof(struct radius_attr_data));
88+
+ if (!nclass)
89+
+ return;
90+
+
91+
+ nclass_count = 0;
92+
+
93+
+ attr_class = NULL;
94+
+ for (i = 0; i < count; i++) {
95+
+ do {
96+
+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
97+
+ &attr_class, &class_len,
98+
+ attr_class) < 0) {
99+
+ i = count;
100+
+ break;
101+
+ }
102+
+ } while (class_len < 1);
103+
+
104+
+ nclass[nclass_count].data = os_memdup(attr_class, class_len);
105+
+ if (!nclass[nclass_count].data)
106+
+ break;
107+
+
108+
+ nclass[nclass_count].len = class_len;
109+
+ nclass_count++;
110+
+ }
111+
+
112+
+ sta->radius_class.attr = nclass;
113+
+ sta->radius_class.count = nclass_count;
114+
+ wpa_printf(MSG_DEBUG,
115+
+ "IEEE 802.1X: Stored %lu RADIUS Class attributes for "
116+
+ MACSTR,
117+
+ (unsigned long) sta->radius_class.count,
118+
+ MAC2STR(sta->addr));
119+
+}
120+
+
121+
+u8* radius_get_class(struct sta_info *sta, size_t *len,
122+
+ int idx)
123+
+{
124+
+ if (!sta || !sta->radius_class.attr ||
125+
+ idx >= (int) sta->radius_class.count)
126+
+ return NULL;
127+
+
128+
+ *len = sta->radius_class.attr[idx].len;
129+
+ return sta->radius_class.attr[idx].data;
130+
+}
131+
+
132+
+
133+
#endif /* CONFIG_NATIVE_WINDOWS */
134+
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
135+
index 4e7d8fb..21d7956 100644
136+
--- a/src/ap/ieee802_11.h
137+
+++ b/src/ap/ieee802_11.h
138+
@@ -238,5 +238,10 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
139+
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
140+
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
141+
bool hostapd_is_mld_ap(struct hostapd_data *hapd);
142+
+void radius_store_class(struct hostapd_data *hapd,
143+
+ struct sta_info *sta,
144+
+ struct radius_msg *msg);
145+
+u8* radius_get_class(struct sta_info *sta, size_t *len,
146+
+ int idx);
147+
148+
#endif /* IEEE802_11_H */
149+
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
150+
index d2ee69b..af7604b 100644
151+
--- a/src/ap/ieee802_11_auth.c
152+
+++ b/src/ap/ieee802_11_auth.c
153+
@@ -489,6 +489,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
154+
struct hostapd_cached_radius_acl *cache;
155+
struct radius_sta *info;
156+
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
157+
+ struct sta_info *sta;
158+
159+
query = hapd->acl_queries;
160+
prev = NULL;
161+
@@ -528,6 +529,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
162+
os_get_reltime(&cache->timestamp);
163+
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
164+
info = &cache->info;
165+
+ sta = ap_get_sta(hapd, query->addr);
166+
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
167+
u8 *buf;
168+
size_t len;
169+
@@ -564,6 +566,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
170+
if (info->identity)
171+
os_memcpy(info->identity, buf, len);
172+
}
173+
+ radius_store_class(hapd, sta, msg);
174+
if (radius_msg_get_attr_ptr(
175+
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
176+
&buf, &len, NULL) == 0) {
177+
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
178+
index 421bc7e..c146e43 100644
179+
--- a/src/ap/ieee802_1x.c
180+
+++ b/src/ap/ieee802_1x.c
181+
@@ -1487,7 +1487,7 @@ void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta)
182+
183+
#ifndef CONFIG_NO_RADIUS
184+
radius_msg_free(sm->last_recv_radius);
185+
- radius_free_class(&sm->radius_class);
186+
+ radius_free_class(&sta->radius_class);
187+
#endif /* CONFIG_NO_RADIUS */
188+
189+
eapol_auth_free(sm);
190+
@@ -1635,59 +1635,6 @@ static void ieee802_1x_get_keys(struct hostapd_data *hapd,
191+
}
192+
193+
194+
-static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
195+
- struct sta_info *sta,
196+
- struct radius_msg *msg)
197+
-{
198+
- u8 *attr_class;
199+
- size_t class_len;
200+
- struct eapol_state_machine *sm = sta->eapol_sm;
201+
- int count, i;
202+
- struct radius_attr_data *nclass;
203+
- size_t nclass_count;
204+
-
205+
- if (!hapd->conf->radius->acct_server || !hapd->radius || !sm)
206+
- return;
207+
-
208+
- radius_free_class(&sm->radius_class);
209+
- count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
210+
- if (count <= 0)
211+
- return;
212+
-
213+
- nclass = os_calloc(count, sizeof(struct radius_attr_data));
214+
- if (!nclass)
215+
- return;
216+
-
217+
- nclass_count = 0;
218+
-
219+
- attr_class = NULL;
220+
- for (i = 0; i < count; i++) {
221+
- do {
222+
- if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
223+
- &attr_class, &class_len,
224+
- attr_class) < 0) {
225+
- i = count;
226+
- break;
227+
- }
228+
- } while (class_len < 1);
229+
-
230+
- nclass[nclass_count].data = os_memdup(attr_class, class_len);
231+
- if (!nclass[nclass_count].data)
232+
- break;
233+
-
234+
- nclass[nclass_count].len = class_len;
235+
- nclass_count++;
236+
- }
237+
-
238+
- sm->radius_class.attr = nclass;
239+
- sm->radius_class.count = nclass_count;
240+
- wpa_printf(MSG_DEBUG,
241+
- "IEEE 802.1X: Stored %lu RADIUS Class attributes for "
242+
- MACSTR,
243+
- (unsigned long) sm->radius_class.count,
244+
- MAC2STR(sta->addr));
245+
-}
246+
-
247+
248+
/* Update sta->identity based on User-Name attribute in Access-Accept */
249+
static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
250+
@@ -2147,7 +2094,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
251+
override_eapReq = 1;
252+
ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
253+
shared_secret_len);
254+
- ieee802_1x_store_radius_class(hapd, sta, msg);
255+
+ radius_store_class(hapd, sta, msg);
256+
ieee802_1x_update_sta_identity(hapd, sta, msg);
257+
ieee802_1x_update_sta_cui(hapd, sta, msg);
258+
ieee802_1x_check_hs20(hapd, sta, msg,
259+
@@ -2778,18 +2725,6 @@ u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len)
260+
}
261+
262+
263+
-u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
264+
- int idx)
265+
-{
266+
- if (!sm || !sm->radius_class.attr ||
267+
- idx >= (int) sm->radius_class.count)
268+
- return NULL;
269+
-
270+
- *len = sm->radius_class.attr[idx].len;
271+
- return sm->radius_class.attr[idx].data;
272+
-}
273+
-
274+
-
275+
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm)
276+
{
277+
if (!sm)
278+
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
279+
index 1469351..60af508 100644
280+
--- a/src/ap/ieee802_1x.h
281+
+++ b/src/ap/ieee802_1x.h
282+
@@ -35,8 +35,6 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
283+
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
284+
const u8 *data, int len, int ack);
285+
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
286+
-u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
287+
- int idx);
288+
struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm);
289+
const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
290+
const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
291+
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
292+
index 32d291d..251f668 100644
293+
--- a/src/ap/pmksa_cache_auth.c
294+
+++ b/src/ap/pmksa_cache_auth.c
295+
@@ -160,7 +160,7 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
296+
entry->cui = wpabuf_dup(eapol->radius_cui);
297+
298+
#ifndef CONFIG_NO_RADIUS
299+
- radius_copy_class(&entry->radius_class, &eapol->radius_class);
300+
+ radius_copy_class(&entry->radius_class, &((struct sta_info *) eapol->sta)->radius_class);
301+
#endif /* CONFIG_NO_RADIUS */
302+
303+
entry->eap_type_authsrv = eapol->eap_type_authsrv;
304+
@@ -203,12 +203,12 @@ void pmksa_cache_to_eapol_data(struct hostapd_data *hapd,
305+
}
306+
307+
#ifndef CONFIG_NO_RADIUS
308+
- radius_free_class(&eapol->radius_class);
309+
- radius_copy_class(&eapol->radius_class, &entry->radius_class);
310+
+ radius_free_class(&((struct sta_info *) eapol->sta)->radius_class);
311+
+ radius_copy_class(&((struct sta_info *) eapol->sta)->radius_class, &entry->radius_class);
312+
#endif /* CONFIG_NO_RADIUS */
313+
- if (eapol->radius_class.attr) {
314+
+ if (((struct sta_info *) eapol->sta)->radius_class.attr) {
315+
wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
316+
- "PMKSA", (unsigned long) eapol->radius_class.count);
317+
+ "PMKSA", (unsigned long) ((struct sta_info *) eapol->sta)->radius_class.count);
318+
}
319+
320+
eapol->eap_type_authsrv = entry->eap_type_authsrv;
321+
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
322+
index 8348dca..c3a3ee3 100644
323+
--- a/src/ap/sta_info.c
324+
+++ b/src/ap/sta_info.c
325+
@@ -314,6 +314,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
326+
#ifndef CONFIG_NO_RADIUS
327+
if (hapd->radius)
328+
radius_client_flush_auth(hapd->radius, sta->addr);
329+
+
330+
+ radius_free_class(&sta->radius_class);
331+
#endif /* CONFIG_NO_RADIUS */
332+
333+
#ifndef CONFIG_NO_VLAN
334+
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
335+
index f825b32..90c9b5c 100644
336+
--- a/src/ap/sta_info.h
337+
+++ b/src/ap/sta_info.h
338+
@@ -17,6 +17,7 @@
339+
#include "common/sae.h"
340+
#include "crypto/sha384.h"
341+
#include "pasn/pasn_common.h"
342+
+#include "radius/radius.h"
343+
344+
/* STA flags */
345+
#define WLAN_STA_AUTH BIT(0)
346+
@@ -340,6 +341,7 @@ struct sta_info {
347+
struct mld_info mld_info;
348+
u8 mld_assoc_link_id;
349+
#endif /* CONFIG_IEEE80211BE */
350+
+ struct radius_class_data radius_class;
351+
};
352+
353+
354+
diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h
355+
index a0cef0f..7e1d6bc 100644
356+
--- a/src/eapol_auth/eapol_auth_sm_i.h
357+
+++ b/src/eapol_auth/eapol_auth_sm_i.h
358+
@@ -156,7 +156,6 @@ struct eapol_state_machine {
359+
u8 eap_type_authsrv; /* EAP type of the last EAP packet from
360+
* Authentication server */
361+
u8 eap_type_supp; /* EAP type of the last EAP packet from Supplicant */
362+
- struct radius_class_data radius_class;
363+
struct wpabuf *radius_cui; /* Chargeable-User-Identity */
364+
365+
struct eap_sm *eap;
366+
--
367+
2.34.1
368+

0 commit comments

Comments
 (0)