mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-03 00:00:24 -04:00
ipsec-sa-mgr: Optionally keep track of acquires for outbound SAs
Currently just based on the reqid. An acquire for the same reqid is triggered at most every 10 seconds (gets ignored in trap_manager_t if the SA is still getting established). Entries are only cleaned up if an SA is eventually installed (similar to the allocated SPIs). Should that ever be a problem, we could probably schedule a job that regularly flushes old entries.
This commit is contained in:
parent
ec503ade58
commit
4e9acf98d0
@ -208,7 +208,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
||||
}
|
||||
|
||||
sa = ipsec->sas->checkout_by_reqid(ipsec->sas, policy->get_reqid(policy),
|
||||
FALSE);
|
||||
FALSE, NULL);
|
||||
if (!sa)
|
||||
{ /* TODO-IPSEC: send an acquire to upper layer */
|
||||
DBG1(DBG_ESP, "could not find an outbound IPsec SA for reqid {%u}, "
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Tobias Brunner
|
||||
* Copyright (C) 2012-2023 Tobias Brunner
|
||||
* Copyright (C) 2012 Giuliano Grassi
|
||||
* Copyright (C) 2012 Ralf Sager
|
||||
*
|
||||
@ -27,6 +27,12 @@
|
||||
#include <collections/hashtable.h>
|
||||
#include <collections/linked_list.h>
|
||||
|
||||
/**
|
||||
* Timeout in seconds for acquries for the same reqid (i.e. the interval used
|
||||
* to trigger acquires while no SA is established).
|
||||
*/
|
||||
#define ACQUIRE_TIMEOUT 10
|
||||
|
||||
typedef struct private_ipsec_sa_mgr_t private_ipsec_sa_mgr_t;
|
||||
|
||||
/**
|
||||
@ -49,6 +55,11 @@ struct private_ipsec_sa_mgr_t {
|
||||
*/
|
||||
hashtable_t *allocated_spis;
|
||||
|
||||
/**
|
||||
* Pending acquires (uint32_t => acquire_entry_t)
|
||||
*/
|
||||
hashtable_t *acquires;
|
||||
|
||||
/**
|
||||
* Mutex used to synchronize access to the SA manager
|
||||
*/
|
||||
@ -119,15 +130,32 @@ typedef struct {
|
||||
|
||||
} ipsec_sa_expired_t;
|
||||
|
||||
/*
|
||||
* Used for the hash table of allocated SPIs
|
||||
/**
|
||||
* Struct to keep track of acquires
|
||||
*/
|
||||
static bool spi_equals(uint32_t *spi, uint32_t *other_spi)
|
||||
typedef struct {
|
||||
|
||||
/**
|
||||
* Reqid of this acquire
|
||||
*/
|
||||
uint32_t reqid;
|
||||
|
||||
/**
|
||||
* Time the entry was created or updated
|
||||
*/
|
||||
time_t triggered;
|
||||
|
||||
} acquire_entry_t;
|
||||
|
||||
/**
|
||||
* Used for the hash table of allocated SPIs and pending acquires
|
||||
*/
|
||||
static bool uint32_equals(const uint32_t *spi, const uint32_t *other_spi)
|
||||
{
|
||||
return *spi == *other_spi;
|
||||
}
|
||||
|
||||
static u_int spi_hash(uint32_t *spi)
|
||||
static u_int uint32_hash(const uint32_t *spi)
|
||||
{
|
||||
return chunk_hash(chunk_from_thing(*spi));
|
||||
}
|
||||
@ -508,6 +536,10 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
|
||||
spi_alloc = this->allocated_spis->remove(this->allocated_spis, &spi);
|
||||
free(spi_alloc);
|
||||
}
|
||||
if (!inbound)
|
||||
{ /* remove any acquires for outbound SAs */
|
||||
free(this->acquires->remove(this->acquires, &reqid));
|
||||
}
|
||||
|
||||
if (this->sas->find_first(this->sas, match_entry_by_spi_src_dst_cb, NULL,
|
||||
spi, src, dst))
|
||||
@ -620,8 +652,53 @@ METHOD(ipsec_sa_mgr_t, del_sa, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all acquires
|
||||
*/
|
||||
static void flush_acquires(private_ipsec_sa_mgr_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
acquire_entry_t *entry;
|
||||
|
||||
DBG2(DBG_ESP, "flushing acquires");
|
||||
enumerator = this->acquires->create_enumerator(this->acquires);
|
||||
while (enumerator->enumerate(enumerator, NULL, (void**)&entry))
|
||||
{
|
||||
this->acquires->remove_at(this->acquires, enumerator);
|
||||
DBG2(DBG_ESP, " removed acquire for reqid {%u}", entry->reqid);
|
||||
free(entry);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an acquire should be sent for the given reqid.
|
||||
*/
|
||||
static bool check_acquire(private_ipsec_sa_mgr_t *this, uint32_t reqid)
|
||||
{
|
||||
acquire_entry_t *entry;
|
||||
time_t now;
|
||||
|
||||
now = time_monotonic(NULL);
|
||||
|
||||
entry = this->acquires->get(this->acquires, &reqid);
|
||||
if (!entry)
|
||||
{
|
||||
INIT(entry,
|
||||
.reqid = reqid,
|
||||
);
|
||||
this->acquires->put(this->acquires, &entry->reqid, entry);
|
||||
}
|
||||
else if (now - entry->triggered <= ACQUIRE_TIMEOUT)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
entry->triggered = now;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*,
|
||||
private_ipsec_sa_mgr_t *this, uint32_t reqid, bool inbound)
|
||||
private_ipsec_sa_mgr_t *this, uint32_t reqid, bool inbound, bool *acquire)
|
||||
{
|
||||
ipsec_sa_entry_t *entry;
|
||||
ipsec_sa_t *sa = NULL;
|
||||
@ -633,6 +710,10 @@ METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*,
|
||||
{
|
||||
sa = entry->sa;
|
||||
}
|
||||
if (!sa && acquire)
|
||||
{
|
||||
*acquire = !inbound && check_acquire(this, reqid);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
return sa;
|
||||
}
|
||||
@ -687,9 +768,11 @@ METHOD(ipsec_sa_mgr_t, destroy, void,
|
||||
this->mutex->lock(this->mutex);
|
||||
flush_entries(this);
|
||||
flush_allocated_spis(this);
|
||||
flush_acquires(this);
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
this->allocated_spis->destroy(this->allocated_spis);
|
||||
this->acquires->destroy(this->acquires);
|
||||
this->sas->destroy(this->sas);
|
||||
|
||||
this->mutex->destroy(this->mutex);
|
||||
@ -719,8 +802,10 @@ ipsec_sa_mgr_t *ipsec_sa_mgr_create()
|
||||
},
|
||||
.sas = linked_list_create(),
|
||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||
.allocated_spis = hashtable_create((hashtable_hash_t)spi_hash,
|
||||
(hashtable_equals_t)spi_equals, 16),
|
||||
.allocated_spis = hashtable_create((hashtable_hash_t)uint32_hash,
|
||||
(hashtable_equals_t)uint32_equals, 16),
|
||||
.acquires = hashtable_create((hashtable_hash_t)uint32_hash,
|
||||
(hashtable_equals_t)uint32_equals, 16),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2012-2023 Tobias Brunner
|
||||
* Copyright (C) 2012 Giuliano Grassi
|
||||
* Copyright (C) 2012 Ralf Sager
|
||||
*
|
||||
@ -174,12 +174,17 @@ struct ipsec_sa_mgr_t {
|
||||
* Since other threads may be waiting for a checked out SA, it should be
|
||||
* checked in as soon as possible after use.
|
||||
*
|
||||
* If no matching outbound SA is found, acquire indicates if an acquire
|
||||
* should be sent for the given reqid.
|
||||
*
|
||||
* @param reqid reqid of the SA
|
||||
* @param inbound TRUE for an inbound SA, FALSE for an outbound SA
|
||||
* @param[out] acquire TRUE if an acquire should be triggered, FALSE if one
|
||||
* is already pending or an SA was found
|
||||
* @return the matching IPsec SA, or NULL if none is found
|
||||
*/
|
||||
ipsec_sa_t *(*checkout_by_reqid)(ipsec_sa_mgr_t *this, uint32_t reqid,
|
||||
bool inbound);
|
||||
bool inbound, bool *acquire);
|
||||
|
||||
/**
|
||||
* Checkin an SA after use.
|
||||
|
Loading…
x
Reference in New Issue
Block a user