Merge branch 'radius-accounting-unclaimed'
Adds all IPs to RADIUS Accounting-Stop messages even those not claimed by a client. For instance, if the connection fails with FAILED_CP_REQUIRED, adding the unclaimed addresses allows the RADIUS server to release the leases early. Fixes #2856.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015-2017 Tobias Brunner
|
* Copyright (C) 2015-2018 Tobias Brunner
|
||||||
* HSR Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Martin Willi
|
* Copyright (C) 2012 Martin Willi
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eap_radius_accounting.h"
|
#include "eap_radius_accounting.h"
|
||||||
|
#include "eap_radius_provider.h"
|
||||||
#include "eap_radius_plugin.h"
|
#include "eap_radius_plugin.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -460,6 +461,37 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any unclaimed IP addresses to the message
|
||||||
|
*/
|
||||||
|
static void add_unclaimed_ips(radius_message_t *message, ike_sa_t *ike_sa)
|
||||||
|
{
|
||||||
|
eap_radius_provider_t *provider;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
host_t *vip;
|
||||||
|
|
||||||
|
provider = eap_radius_provider_get();
|
||||||
|
enumerator = provider->clear_unclaimed(provider,
|
||||||
|
ike_sa->get_unique_id(ike_sa));
|
||||||
|
while (enumerator->enumerate(enumerator, &vip))
|
||||||
|
{
|
||||||
|
switch (vip->get_family(vip))
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
message->add(message, RAT_FRAMED_IP_ADDRESS,
|
||||||
|
vip->get_address(vip));
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
message->add(message, RAT_FRAMED_IPV6_ADDRESS,
|
||||||
|
vip->get_address(vip));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the Class attributes received in the Access-Accept message to the
|
* Add the Class attributes received in the Access-Accept message to the
|
||||||
* RADIUS accounting message
|
* RADIUS accounting message
|
||||||
@@ -790,6 +822,7 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
|
|||||||
chunk_create(entry->sid, strlen(entry->sid)));
|
chunk_create(entry->sid, strlen(entry->sid)));
|
||||||
add_class_attributes(message, entry);
|
add_class_attributes(message, entry);
|
||||||
add_ike_sa_parameters(this, message, ike_sa);
|
add_ike_sa_parameters(this, message, ike_sa);
|
||||||
|
add_unclaimed_ips(message, ike_sa);
|
||||||
|
|
||||||
value = htonl(entry->usage.bytes.sent);
|
value = htonl(entry->usage.bytes.sent);
|
||||||
message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
|
message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
|
||||||
@@ -816,7 +849,6 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
|
|||||||
value = htonl(time_monotonic(NULL) - entry->created);
|
value = htonl(time_monotonic(NULL) - entry->created);
|
||||||
message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
|
message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value));
|
||||||
|
|
||||||
|
|
||||||
value = htonl(entry->cause);
|
value = htonl(entry->cause);
|
||||||
message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
|
message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2018 Tobias Brunner
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2013 Martin Willi
|
* Copyright (C) 2013 Martin Willi
|
||||||
* Copyright (C) 2013 revosec AG
|
* Copyright (C) 2013 revosec AG
|
||||||
*
|
*
|
||||||
@@ -131,7 +134,7 @@ static entry_t* get_or_create_entry(hashtable_t *hashtable, uintptr_t id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put an entry to hashtable, or destroy it ife empty
|
* Put an entry to hashtable, or destroy it if empty
|
||||||
*/
|
*/
|
||||||
static void put_or_destroy_entry(hashtable_t *hashtable, entry_t *entry)
|
static void put_or_destroy_entry(hashtable_t *hashtable, entry_t *entry)
|
||||||
{
|
{
|
||||||
@@ -494,6 +497,24 @@ METHOD(eap_radius_provider_t, add_attribute, void,
|
|||||||
this->listener.mutex->unlock(this->listener.mutex);
|
this->listener.mutex->unlock(this->listener.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(eap_radius_provider_t, clear_unclaimed, enumerator_t*,
|
||||||
|
private_eap_radius_provider_t *this, uint32_t id)
|
||||||
|
{
|
||||||
|
entry_t *entry;
|
||||||
|
|
||||||
|
this->listener.mutex->lock(this->listener.mutex);
|
||||||
|
entry = this->listener.unclaimed->remove(this->listener.unclaimed,
|
||||||
|
(void*)(uintptr_t)id);
|
||||||
|
this->listener.mutex->unlock(this->listener.mutex);
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
return enumerator_create_empty();
|
||||||
|
}
|
||||||
|
return enumerator_create_cleaner(
|
||||||
|
entry->addrs->create_enumerator(entry->addrs),
|
||||||
|
(void*)destroy_entry, entry);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(eap_radius_provider_t, destroy, void,
|
METHOD(eap_radius_provider_t, destroy, void,
|
||||||
private_eap_radius_provider_t *this)
|
private_eap_radius_provider_t *this)
|
||||||
{
|
{
|
||||||
@@ -523,6 +544,7 @@ eap_radius_provider_t *eap_radius_provider_create()
|
|||||||
},
|
},
|
||||||
.add_framed_ip = _add_framed_ip,
|
.add_framed_ip = _add_framed_ip,
|
||||||
.add_attribute = _add_attribute,
|
.add_attribute = _add_attribute,
|
||||||
|
.clear_unclaimed = _clear_unclaimed,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.listener = {
|
.listener = {
|
||||||
@@ -539,6 +561,14 @@ eap_radius_provider_t *eap_radius_provider_create()
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (lib->settings->get_bool(lib->settings,
|
||||||
|
"%s.plugins.eap-radius.accounting", FALSE, lib->ns))
|
||||||
|
{
|
||||||
|
/* if RADIUS accounting is enabled, keep unclaimed IPs around until
|
||||||
|
* the Accounting-Stop message is sent */
|
||||||
|
this->listener.public.message = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
charon->bus->add_listener(charon->bus, &this->listener.public);
|
charon->bus->add_listener(charon->bus, &this->listener.public);
|
||||||
|
|
||||||
singleton = &this->public;
|
singleton = &this->public;
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2018 Tobias Brunner
|
||||||
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2013 Martin Willi
|
* Copyright (C) 2013 Martin Willi
|
||||||
* Copyright (C) 2013 revosec AG
|
* Copyright (C) 2013 revosec AG
|
||||||
*
|
*
|
||||||
@@ -55,6 +58,14 @@ struct eap_radius_provider_t {
|
|||||||
void (*add_attribute)(eap_radius_provider_t *this, uint32_t id,
|
void (*add_attribute)(eap_radius_provider_t *this, uint32_t id,
|
||||||
configuration_attribute_type_t type, chunk_t data);
|
configuration_attribute_type_t type, chunk_t data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears any unclaimed IP addresses and attributes for the given IKE_SA.
|
||||||
|
*
|
||||||
|
* @param id IKE_SA unique identifier
|
||||||
|
* @return enumerator over unclaimed IP addresses, if any
|
||||||
|
*/
|
||||||
|
enumerator_t *(*clear_unclaimed)(eap_radius_provider_t *this, uint32_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a eap_radius_provider_t.
|
* Destroy a eap_radius_provider_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user