summaryrefslogtreecommitdiff
path: root/src/libipsec/ipsec_sa_mgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libipsec/ipsec_sa_mgr.c')
-rw-r--r--src/libipsec/ipsec_sa_mgr.c75
1 files changed, 57 insertions, 18 deletions
diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c
index e42c77aa5..28748971d 100644
--- a/src/libipsec/ipsec_sa_mgr.c
+++ b/src/libipsec/ipsec_sa_mgr.c
@@ -18,13 +18,13 @@
#include "ipsec.h"
#include "ipsec_sa_mgr.h"
-#include <debug.h>
+#include <utils/debug.h>
#include <library.h>
#include <processing/jobs/callback_job.h>
#include <threading/condvar.h>
#include <threading/mutex.h>
-#include <utils/hashtable.h>
-#include <utils/linked_list.h>
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
typedef struct private_ipsec_sa_mgr_t private_ipsec_sa_mgr_t;
@@ -237,29 +237,29 @@ static bool match_entry_by_sa_ptr(ipsec_sa_entry_t *item, ipsec_sa_t *sa)
return item->sa == sa;
}
-static bool match_entry_by_spi_inbound(ipsec_sa_entry_t *item, u_int32_t spi,
- bool inbound)
+static bool match_entry_by_spi_inbound(ipsec_sa_entry_t *item, u_int32_t *spi,
+ bool *inbound)
{
- return item->sa->get_spi(item->sa) == spi &&
- item->sa->is_inbound(item->sa) == inbound;
+ return item->sa->get_spi(item->sa) == *spi &&
+ item->sa->is_inbound(item->sa) == *inbound;
}
-static bool match_entry_by_spi_src_dst(ipsec_sa_entry_t *item, u_int32_t spi,
+static bool match_entry_by_spi_src_dst(ipsec_sa_entry_t *item, u_int32_t *spi,
host_t *src, host_t *dst)
{
- return item->sa->match_by_spi_src_dst(item->sa, spi, src, dst);
+ return item->sa->match_by_spi_src_dst(item->sa, *spi, src, dst);
}
static bool match_entry_by_reqid_inbound(ipsec_sa_entry_t *item,
- u_int32_t reqid, bool inbound)
+ u_int32_t *reqid, bool *inbound)
{
- return item->sa->match_by_reqid(item->sa, reqid, inbound);
+ return item->sa->match_by_reqid(item->sa, *reqid, *inbound);
}
-static bool match_entry_by_spi_dst(ipsec_sa_entry_t *item, u_int32_t spi,
+static bool match_entry_by_spi_dst(ipsec_sa_entry_t *item, u_int32_t *spi,
host_t *dst)
{
- return item->sa->match_by_spi_dst(item->sa, spi, dst);
+ return item->sa->match_by_spi_dst(item->sa, *spi, dst);
}
/**
@@ -381,7 +381,7 @@ static bool allocate_spi(private_ipsec_sa_mgr_t *this, u_int32_t spi)
if (this->allocated_spis->get(this->allocated_spis, &spi) ||
this->sas->find_first(this->sas, (void*)match_entry_by_spi_inbound,
- NULL, spi, TRUE) == SUCCESS)
+ NULL, &spi, TRUE) == SUCCESS)
{
return FALSE;
}
@@ -471,7 +471,7 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
}
if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_src_dst,
- NULL, spi, src, dst) == SUCCESS)
+ NULL, &spi, src, dst) == SUCCESS)
{
this->mutex->unlock(this->mutex);
DBG1(DBG_ESP, "failed to install SAD entry: already installed");
@@ -487,6 +487,44 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
return SUCCESS;
}
+METHOD(ipsec_sa_mgr_t, update_sa, status_t,
+ private_ipsec_sa_mgr_t *this, u_int32_t spi, u_int8_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap, mark_t mark)
+{
+ ipsec_sa_entry_t *entry = NULL;
+
+ DBG2(DBG_ESP, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+
+ if (!new_encap)
+ {
+ DBG1(DBG_ESP, "failed to update SAD entry: can't deactivate UDP "
+ "encapsulation");
+ return NOT_SUPPORTED;
+ }
+
+ this->mutex->lock(this->mutex);
+ if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_src_dst,
+ (void**)&entry, &spi, src, dst) == SUCCESS &&
+ wait_for_entry(this, entry))
+ {
+ entry->sa->set_source(entry->sa, new_src);
+ entry->sa->set_destination(entry->sa, new_dst);
+ /* checkin the entry */
+ entry->locked = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (!entry)
+ {
+ DBG1(DBG_ESP, "failed to update SAD entry: not found");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
METHOD(ipsec_sa_mgr_t, del_sa, status_t,
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
u_int8_t protocol, u_int16_t cpi, mark_t mark)
@@ -498,7 +536,7 @@ METHOD(ipsec_sa_mgr_t, del_sa, status_t,
enumerator = this->sas->create_enumerator(this->sas);
while (enumerator->enumerate(enumerator, (void**)&current))
{
- if (match_entry_by_spi_src_dst(current, spi, src, dst))
+ if (match_entry_by_spi_src_dst(current, &spi, src, dst))
{
if (wait_remove_entry(this, current))
{
@@ -529,7 +567,7 @@ METHOD(ipsec_sa_mgr_t, checkout_by_reqid, ipsec_sa_t*,
this->mutex->lock(this->mutex);
if (this->sas->find_first(this->sas, (void*)match_entry_by_reqid_inbound,
- (void**)&entry, reqid, inbound) == SUCCESS &&
+ (void**)&entry, &reqid, &inbound) == SUCCESS &&
wait_for_entry(this, entry))
{
sa = entry->sa;
@@ -546,7 +584,7 @@ METHOD(ipsec_sa_mgr_t, checkout_by_spi, ipsec_sa_t*,
this->mutex->lock(this->mutex);
if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_dst,
- (void**)&entry, spi, dst) == SUCCESS &&
+ (void**)&entry, &spi, dst) == SUCCESS &&
wait_for_entry(this, entry))
{
sa = entry->sa;
@@ -609,6 +647,7 @@ ipsec_sa_mgr_t *ipsec_sa_mgr_create()
.public = {
.get_spi = _get_spi,
.add_sa = _add_sa,
+ .update_sa = _update_sa,
.del_sa = _del_sa,
.checkout_by_spi = _checkout_by_spi,
.checkout_by_reqid = _checkout_by_reqid,