|
@@ -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);
|