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@xxxxxxxxxxxxxx> --- 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 > > _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap