summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/eap_radius
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-11-18 14:49:27 +0100
committerYves-Alexis Perez <corsac@debian.org>2015-11-18 14:49:27 +0100
commit1e980d6be0ef0e243c6fe82b5e855454b97e24a4 (patch)
tree0d59eec2ce2ed332434ae80fc78a44db9ad293c5 /src/libcharon/plugins/eap_radius
parent5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (diff)
downloadvyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.tar.gz
vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.zip
Imported Upstream version 5.3.4
Diffstat (limited to 'src/libcharon/plugins/eap_radius')
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_provider.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_provider.c b/src/libcharon/plugins/eap_radius/eap_radius_provider.c
index 0cf723711..0f207fbe6 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_provider.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_provider.c
@@ -178,18 +178,38 @@ static void add_addr(private_eap_radius_provider_t *this,
* Remove the next address from the locked hashtable stored for given id
*/
static host_t* remove_addr(private_eap_radius_provider_t *this,
- hashtable_t *hashtable, uintptr_t id)
+ hashtable_t *hashtable, uintptr_t id, host_t *addr)
{
+ enumerator_t *enumerator;
entry_t *entry;
- host_t *addr = NULL;
+ host_t *found = NULL, *current;
entry = hashtable->remove(hashtable, (void*)id);
if (entry)
{
- entry->addrs->remove_first(entry->addrs, (void**)&addr);
+ enumerator = entry->addrs->create_enumerator(entry->addrs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (addr->ip_equals(addr, current))
+ { /* prefer an exact match */
+ entry->addrs->remove_at(entry->addrs, enumerator);
+ enumerator->destroy(enumerator);
+ put_or_destroy_entry(hashtable, entry);
+ return current;
+ }
+ if (!found && addr->get_family(addr) == current->get_family(current))
+ { /* fallback to the first IP with a matching address family */
+ found = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ entry->addrs->remove(entry->addrs, found, NULL);
+ }
put_or_destroy_entry(hashtable, entry);
}
- return addr;
+ return found;
}
/**
@@ -326,7 +346,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
if (streq(name, "radius"))
{
this->listener.mutex->lock(this->listener.mutex);
- addr = remove_addr(this, this->listener.unclaimed, sa);
+ addr = remove_addr(this, this->listener.unclaimed, sa, requested);
if (addr)
{
add_addr(this, this->listener.claimed, sa, addr->clone(addr));
@@ -357,7 +377,7 @@ METHOD(attribute_provider_t, release_address, bool,
if (streq(name, "radius"))
{
this->listener.mutex->lock(this->listener.mutex);
- found = remove_addr(this, this->listener.claimed, sa);
+ found = remove_addr(this, this->listener.claimed, sa, address);
this->listener.mutex->unlock(this->listener.mutex);
break;
}