aboutsummaryrefslogtreecommitdiffstats
path: root/src/radius
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2016-02-29 09:44:43 (GMT)
committerJouni Malinen <j@w1.fi>2016-02-29 09:52:16 (GMT)
commit669b5324e1a8af354bc17f516980e17071e48233 (patch)
treed7fac8070247cab84983e7010076a5510a7e7e7e /src/radius
parent251953bcb6f1503ce8bb2f1f57b2c2a44c601685 (diff)
downloadhostap-669b5324e1a8af354bc17f516980e17071e48233.zip
hostap-669b5324e1a8af354bc17f516980e17071e48233.tar.gz
hostap-669b5324e1a8af354bc17f516980e17071e48233.tar.bz2
RADIUS: Update full message for interim accounting updates
Instead of using the RADIUS client retransmission design with the old RADIUS message contents for each retry, trigger a completely new interim accounting update instance more quickly (using the same schedule as RADIUS message retransmissions) to improve accounting updates in cases where RADIUS message delivery fails. This allows the server to get up to date information from the time the "retry" message was sent instead of the old information from the time the first failed attempt was sent. Signed-off-by: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'src/radius')
-rw-r--r--src/radius/radius_client.c92
-rw-r--r--src/radius/radius_client.h3
2 files changed, 52 insertions, 43 deletions
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index b24bbf8..5e705e6 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -226,6 +226,16 @@ struct radius_client_data {
* next_radius_identifier - Next RADIUS message identifier to use
*/
u8 next_radius_identifier;
+
+ /**
+ * interim_error_cb - Interim accounting error callback
+ */
+ void (*interim_error_cb)(const u8 *addr, void *ctx);
+
+ /**
+ * interim_error_cb_ctx - interim_error_cb() context data
+ */
+ void *interim_error_cb_ctx;
};
@@ -297,6 +307,25 @@ int radius_client_register(struct radius_client_data *radius,
}
+/**
+ * radius_client_set_interim_erro_cb - Register an interim acct error callback
+ * @radius: RADIUS client context from radius_client_init()
+ * @addr: Station address from the failed message
+ * @cb: Handler for interim accounting errors
+ * @ctx: Context pointer for handler callbacks
+ *
+ * This function is used to register a handler for processing failed
+ * transmission attempts of interim accounting update messages.
+ */
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx)
+{
+ radius->interim_error_cb = cb;
+ radius->interim_error_cb_ctx = ctx;
+}
+
+
/*
* Returns >0 if message queue was flushed (i.e., the message that triggered
* the error is not available anymore)
@@ -371,6 +400,18 @@ static int radius_client_retransmit(struct radius_client_data *radius,
conf->auth_server->retransmissions++;
}
}
+
+ if (entry->msg_type == RADIUS_ACCT_INTERIM) {
+ wpa_printf(MSG_DEBUG,
+ "RADIUS: Failed to transmit interim accounting update to "
+ MACSTR " - drop message and request a new update",
+ MAC2STR(entry->addr));
+ if (radius->interim_error_cb)
+ radius->interim_error_cb(entry->addr,
+ radius->interim_error_cb_ctx);
+ return 1;
+ }
+
if (s < 0) {
wpa_printf(MSG_INFO,
"RADIUS: No valid socket for retransmission");
@@ -624,39 +665,6 @@ static void radius_client_list_add(struct radius_client_data *radius,
}
-static void radius_client_list_del(struct radius_client_data *radius,
- RadiusType msg_type, const u8 *addr)
-{
- struct radius_msg_list *entry, *prev, *tmp;
-
- if (addr == NULL)
- return;
-
- entry = radius->msgs;
- prev = NULL;
- while (entry) {
- if (entry->msg_type == msg_type &&
- os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
- if (prev)
- prev->next = entry->next;
- else
- radius->msgs = entry->next;
- tmp = entry;
- entry = entry->next;
- hostapd_logger(radius->ctx, addr,
- HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_DEBUG,
- "Removing matching RADIUS message");
- radius_client_msg_free(tmp);
- radius->num_msgs--;
- continue;
- }
- prev = entry;
- entry = entry->next;
- }
-}
-
-
/**
* radius_client_send - Send a RADIUS request
* @radius: RADIUS client context from radius_client_init()
@@ -668,16 +676,19 @@ static void radius_client_list_del(struct radius_client_data *radius,
* This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
* accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
* between accounting and interim accounting messages is that the interim
- * message will override any pending interim accounting updates while a new
- * accounting message does not remove any pending messages.
+ * message will not be retransmitted. Instead, a callback is used to indicate
+ * that the transmission failed for the specific station @addr so that a new
+ * interim accounting update message can be generated with up-to-date session
+ * data instead of trying to resend old information.
*
* The message is added on the retransmission queue and will be retransmitted
* automatically until a response is received or maximum number of retries
- * (RADIUS_CLIENT_MAX_RETRIES) is reached.
+ * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with
+ * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue
+ * automatically on transmission failure.
*
* The related device MAC address can be used to identify pending messages that
- * can be removed with radius_client_flush_auth() or with interim accounting
- * updates.
+ * can be removed with radius_client_flush_auth().
*/
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg, RadiusType msg_type,
@@ -690,11 +701,6 @@ int radius_client_send(struct radius_client_data *radius,
int s, res;
struct wpabuf *buf;
- if (msg_type == RADIUS_ACCT_INTERIM) {
- /* Remove any pending interim acct update for the same STA. */
- radius_client_list_del(radius, msg_type, addr);
- }
-
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
if (conf->acct_server && radius->acct_sock < 0)
radius_client_init_acct(radius);
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 3db16aa..8ca0874 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -241,6 +241,9 @@ int radius_client_register(struct radius_client_data *radius,
const u8 *shared_secret, size_t shared_secret_len,
void *data),
void *data);
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx);
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg,
RadiusType msg_type, const u8 *addr);