Send Acct-Terminate-Cause based on some alerts catched on the bus

Currently supported are user disconnects, session timeouts and if the peer does
not respond on IKE packets or DPDs.
This commit is contained in:
Martin Willi
2013-03-14 14:20:55 +01:00
parent 335982169a
commit 552b8ad5f5
@@ -52,6 +52,30 @@ struct private_eap_radius_accounting_t {
u_int32_t prefix;
};
/**
* Acct-Terminate-Cause
*/
typedef enum {
ACCT_CAUSE_USER_REQUEST = 1,
ACCT_CAUSE_LOST_CARRIER = 2,
ACCT_CAUSE_LOST_SERVICE = 3,
ACCT_CAUSE_IDLE_TIMEOUT = 4,
ACCT_CAUSE_SESSION_TIMEOUT = 5,
ACCT_CAUSE_ADMIN_RESET = 6,
ACCT_CAUSE_ADMIN_REBOOT = 7,
ACCT_CAUSE_PORT_ERROR = 8,
ACCT_CAUSE_NAS_ERROR = 9,
ACCT_CAUSE_NAS_REQUEST = 10,
ACCT_CAUSE_NAS_REBOOT = 11,
ACCT_CAUSE_PORT_UNNEEDED = 12,
ACCT_CAUSE_PORT_PREEMPTED = 13,
ACCT_CAUSE_PORT_SUSPENDED = 14,
ACCT_CAUSE_SERVICE_UNAVAILABLE = 15,
ACCT_CAUSE_CALLBACK = 16,
ACCT_CAUSE_USER_ERROR = 17,
ACCT_CAUSE_HOST_REQUEST = 18,
} radius_acct_terminate_cause_t;
/**
* Hashtable entry with usage stats
*/
@@ -65,6 +89,8 @@ typedef struct {
} bytes, packets;
/** session creation time */
time_t created;
/** terminate cause */
radius_acct_terminate_cause_t cause;
} entry_t;
/**
@@ -225,6 +251,8 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
id = ike_sa->get_unique_id(ike_sa);
INIT(entry,
.created = time_monotonic(NULL),
/* default terminate cause, if none other catched */
.cause = ACCT_CAUSE_USER_REQUEST,
);
snprintf(entry->sid, sizeof(entry->sid), "%u-%u", this->prefix, id);
@@ -291,12 +319,45 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
value = htonl(time_monotonic(NULL) - entry->created);
message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
value = htonl(entry->cause);
message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
send_message(this, message);
message->destroy(message);
free(entry);
}
}
METHOD(listener_t, alert, bool,
private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, alert_t alert,
va_list args)
{
radius_acct_terminate_cause_t cause;
entry_t *entry;
switch (alert)
{
case ALERT_IKE_SA_EXPIRED:
cause = ACCT_CAUSE_SESSION_TIMEOUT;
break;
case ALERT_RETRANSMIT_SEND_TIMEOUT:
cause = ACCT_CAUSE_LOST_SERVICE;
break;
default:
return TRUE;
}
this->mutex->lock(this->mutex);
entry = this->sessions->get(this->sessions,
(void*)(uintptr_t)ike_sa->get_unique_id(ike_sa));
if (entry)
{
entry->cause = cause;
}
this->mutex->unlock(this->mutex);
return TRUE;
}
METHOD(listener_t, ike_updown, bool,
private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, bool up)
{
@@ -400,6 +461,7 @@ eap_radius_accounting_t *eap_radius_accounting_create()
INIT(this,
.public = {
.listener = {
.alert = _alert,
.ike_updown = _ike_updown,
.ike_rekey = _ike_rekey,
.message = _message_hook,