[PATCH 1/2] RADIUS server: add accounting message callback
Dávid Benko
davidbenko at davidbenko.dev
Sun Feb 23 14:39:55 PST 2025
Adds a configurable callback for incoming Accounting-Request messages to
integrated RADIUS server. This approach allows different implementation by
hostapd itself and other binaries built on top of hostap -- for example --
OpenWrt's RADIUS server.
Signed-off-by: Dávid Benko <davidbenko at davidbenko.dev>
---
src/radius/radius_server.c | 42 ++++++++++++++++++++++++++++++++++++--
src/radius/radius_server.h | 26 ++++++++++++++++++++++-
2 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 715b6d928..bbb493b41 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -146,7 +146,8 @@ struct radius_server_data {
/**
* conf_ctx - Context pointer for callbacks
*
- * This is used as the ctx argument in get_eap_user() calls.
+ * This is used as the ctx argument in get_eap_user() and acct_req_cb()
+ * calls.
*/
void *conf_ctx;
@@ -193,6 +194,27 @@ struct radius_server_data {
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
int phase2, struct eap_user *user);
+ /**
+ * acct_req_cb - Callback for processing received RADIUS accounting
+ * requests
+ * @ctx: Context data from conf_ctx
+ * @msg: Received RADIUS accounting request
+ * @status_type: Status type from the message (parsed Acct-Status-Type
+ * attribute)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This can be used to log accounting information into file, database,
+ * syslog server, etc.
+ * Callback should not modify the message.
+ * If 0 is returned, response is automatically created. Otherwise,
+ * no response is created.
+ *
+ * acct_req_cb can be set to null to omit any custom processing of
+ * account requests. Statistics counters will be incremented in any
+ * case.
+ */
+ int (*acct_req_cb)(void *ctx, struct radius_msg *msg, u32 status_type);
+
/**
* eap_req_id_text - Optional data for EAP-Request/Identity
*
@@ -1674,7 +1696,22 @@ static void radius_server_receive_acct(int sock, void *eloop_ctx,
goto fail;
}
- /* TODO: Write accounting information to a file or database */
+ /* Parse Acct-Status-Type from Accounting-Request */
+ u32 status_type = 0;
+ if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
+ &status_type) != 0) {
+ RADIUS_DEBUG("Unable to parse Acct-Status-Type from %s", abuf);
+ goto fail;
+ }
+
+ /* Process accounting information by configured callback */
+ if (data->acct_req_cb != NULL &&
+ data->acct_req_cb(data->conf_ctx, msg, status_type) != 0) {
+ RADIUS_DEBUG("Accounting request callback returned non-zero "
+ "code indicating processing failure (from %s)",
+ abuf);
+ goto fail;
+ }
hdr = radius_msg_get_hdr(msg);
@@ -1999,6 +2036,7 @@ radius_server_init(struct radius_server_conf *conf)
conf->eap_cfg->eap_server = 1;
data->ipv6 = conf->ipv6;
data->get_eap_user = conf->get_eap_user;
+ data->acct_req_cb = conf->acct_req_cb;
if (conf->eap_req_id_text) {
data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
if (!data->eap_req_id_text)
diff --git a/src/radius/radius_server.h b/src/radius/radius_server.h
index 2a6f56796..9124b91f2 100644
--- a/src/radius/radius_server.h
+++ b/src/radius/radius_server.h
@@ -9,6 +9,8 @@
#ifndef RADIUS_SERVER_H
#define RADIUS_SERVER_H
+#include "radius.h"
+
struct radius_server_data;
struct eap_user;
@@ -47,7 +49,8 @@ struct radius_server_conf {
/**
* conf_ctx - Context pointer for callbacks
*
- * This is used as the ctx argument in get_eap_user() calls.
+ * This is used as the ctx argument in get_eap_user() and acct_req_cb()
+ * calls.
*/
void *conf_ctx;
@@ -75,6 +78,27 @@ struct radius_server_conf {
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
int phase2, struct eap_user *user);
+ /**
+ * acct_req_cb - Callback for processing received RADIUS accounting
+ * requests
+ * @ctx: Context data from conf_ctx
+ * @msg: Received RADIUS accounting request
+ * @status_type: Status type from the message (parsed Acct-Status-Type
+ * attribute)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This can be used to log accounting information into file, database,
+ * syslog server, etc.
+ * Callback should not modify the message.
+ * If 0 is returned, response is automatically created. Otherwise,
+ * no response is created.
+ *
+ * acct_req_cb can be set to null to omit any custom processing of
+ * account requests. Statistics counters will be incremented in any
+ * case.
+ */
+ int (*acct_req_cb)(void *ctx, struct radius_msg *msg, u32 status_type);
+
/**
* eap_req_id_text - Optional data for EAP-Request/Identity
*
--
2.25.1
---- On Sun, 23 Feb 2025 23:37:59 +0100 Dávid Benko wrote ---
> There is a long standing (over a decade) TODO on processing RADIUS server
> accounting requests:
> https://w1.fi/cgit/hostap/tree/src/radius/radius_server.c?id=012a893c469157d5734f6f33953497ea6e3b0169#n1677
>
> I created a pair of patches implementing a new callback interface for
> accounting requests (patch 1) and the callback which simply logs all received
> messages (patch 2). Configuration option to turn it on or off is also included.
>
> Even though the TODO mentions writing accounting information to a file or
> database, I think logging is well sufficient for many of hostapd's use cases
> and definitely better than nothing.
>
> Dávid Benko
>
>
More information about the Hostap
mailing list