summaryrefslogtreecommitdiff
path: root/src/libcharon/tests/utils/mock_ipsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/tests/utils/mock_ipsec.c')
-rw-r--r--src/libcharon/tests/utils/mock_ipsec.c179
1 files changed, 177 insertions, 2 deletions
diff --git a/src/libcharon/tests/utils/mock_ipsec.c b/src/libcharon/tests/utils/mock_ipsec.c
index d57a26a87..d6172f5bd 100644
--- a/src/libcharon/tests/utils/mock_ipsec.c
+++ b/src/libcharon/tests/utils/mock_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,12 @@
#include "mock_ipsec.h"
+#include <daemon.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+
+#include <assert.h>
+
typedef struct private_kernel_ipsec_t private_kernel_ipsec_t;
/**
@@ -29,16 +35,80 @@ struct private_kernel_ipsec_t {
kernel_ipsec_t public;
/**
+ * Rekey listener
+ */
+ listener_t listener;
+
+ /**
* Allocated SPI
*/
refcount_t spi;
+
+ /**
+ * Installed SAs
+ */
+ hashtable_t *sas;
};
+/**
+ * Global instance
+ */
+static private_kernel_ipsec_t *instance;
+
+/**
+ * Data about installed IPsec SAs
+ */
+typedef struct {
+ /**
+ * SPI of the SA
+ */
+ uint32_t spi;
+
+ /**
+ * Associated IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if this was an allocated SPI
+ */
+ bool alloc;
+
+} entry_t;
+
+/**
+ * Hash an IPsec SA entry
+ */
+static u_int entry_hash(const void *key)
+{
+ entry_t *entry = (entry_t*)key;
+ return chunk_hash_inc(chunk_from_thing(entry->spi),
+ chunk_hash(chunk_from_thing(entry->ike_sa)));
+}
+
+/**
+ * Compare an IPsec SA entry
+ */
+static bool entry_equals(const void *key, const void *other_key)
+{
+ entry_t *a = (entry_t*)key, *b = (entry_t*)other_key;
+ return a->spi == b->spi && a->ike_sa == b->ike_sa;
+}
+
METHOD(kernel_ipsec_t, get_spi, status_t,
private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol,
uint32_t *spi)
{
+ entry_t *entry;
+
*spi = (uint32_t)ref_get(&this->spi);
+ INIT(entry,
+ .spi = *spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ .alloc = TRUE,
+ );
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
return SUCCESS;
}
@@ -52,6 +122,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_add_sa_t *data)
{
+ entry_t *entry;
+
+ INIT(entry,
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ );
+ if (data->inbound)
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(entry && entry->alloc);
+ free(entry);
+ }
+ else
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
+ }
return SUCCESS;
}
@@ -74,9 +161,47 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_del_sa_t *data)
{
+ entry_t *entry, lookup = {
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ };
+
+ entry = this->sas->remove(this->sas, &lookup);
+ assert(entry);
+ free(entry);
return SUCCESS;
}
+METHOD(listener_t, ike_rekey, bool,
+ listener_t *listener, ike_sa_t *old, ike_sa_t *new)
+{
+ enumerator_t *enumerator;
+ array_t *sas = NULL;
+ entry_t *entry;
+
+ enumerator = instance->sas->create_enumerator(instance->sas);
+ while (enumerator->enumerate(enumerator, &entry, NULL))
+ {
+ if (entry->ike_sa == old)
+ {
+ instance->sas->remove_at(instance->sas, enumerator);
+ array_insert_create(&sas, ARRAY_TAIL, entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ enumerator = array_create_enumerator(sas);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ array_remove_at(sas, enumerator);
+ entry->ike_sa = new;
+ entry = instance->sas->put(instance->sas, entry, entry);
+ assert(!entry);
+ }
+ enumerator->destroy(enumerator);
+ array_destroy(sas);
+ return TRUE;
+}
+
METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
kernel_ipsec_manage_policy_t *data)
@@ -99,6 +224,14 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_ipsec_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener);
+ this->sas->destroy(this->sas);
+ free(this);
+}
+
/*
* Described in header
*/
@@ -121,8 +254,50 @@ kernel_ipsec_t *mock_ipsec_create()
.flush_policies = (void*)return_failed,
.bypass_socket = (void*)return_true,
.enable_udp_decap = (void*)return_true,
- .destroy = (void*)free,
+ .destroy = _destroy,
+ },
+ .listener = {
+ .ike_rekey = _ike_rekey,
},
+ .sas = hashtable_create(entry_hash, entry_equals, 8),
);
+
+ instance = this;
+
+ charon->bus->add_listener(charon->bus, &this->listener);
+
return &this->public;
}
+
+
+CALLBACK(filter_sas, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ entry_t *entry;
+ ike_sa_t **ike_sa;
+ uint32_t *spi;
+
+ VA_ARGS_VGET(args, ike_sa, spi);
+
+ while (orig->enumerate(orig, &entry, NULL))
+ {
+ if (entry->alloc)
+ {
+ continue;
+ }
+ *ike_sa = entry->ike_sa;
+ *spi = entry->spi;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Described in header
+ */
+enumerator_t *mock_ipsec_create_sa_enumerator()
+{
+ return enumerator_create_filter(
+ instance->sas->create_enumerator(instance->sas),
+ filter_sas, NULL, NULL);
+}