aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/charon-tkm/src/tkm/tkm_kernel_sad.c40
-rw-r--r--src/charon-tkm/src/tkm/tkm_kernel_sad.h11
-rw-r--r--src/charon-tkm/tests/kernel_sad_tests.c28
3 files changed, 79 insertions, 0 deletions
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.c b/src/charon-tkm/src/tkm/tkm_kernel_sad.c
index f8f23a8f8..3394b58af 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_sad.c
+++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.c
@@ -114,6 +114,19 @@ static bool sad_entry_match(sad_entry_t * const entry, const host_t * const src,
}
/**
+ * Find a list entry with given reqid, spi and proto values.
+ */
+static bool sad_entry_match_dst(sad_entry_t * const entry,
+ const u_int32_t * const reqid,
+ const u_int32_t * const spi,
+ const u_int8_t * const proto)
+{
+ return entry->reqid == *reqid &&
+ entry->spi == *spi &&
+ entry->proto == *proto;
+}
+
+/**
* Compare two SAD entries for equality.
*/
static bool sad_entry_equal(sad_entry_t * const left, sad_entry_t * const right)
@@ -196,6 +209,32 @@ METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type,
return id;
}
+METHOD(tkm_kernel_sad_t, get_dst_host, host_t *,
+ private_tkm_kernel_sad_t * const this, const u_int32_t reqid,
+ const u_int32_t spi, const u_int8_t proto)
+{
+ host_t *dst = NULL;
+ sad_entry_t *entry = NULL;
+
+ this->mutex->lock(this->mutex);
+ const status_t res = this->data->find_first(this->data,
+ (linked_list_match_t)sad_entry_match_dst,
+ (void**)&entry, &reqid, &spi, &proto);
+ if (res == SUCCESS && entry)
+ {
+ dst = entry->dst;
+ DBG3(DBG_KNL, "returning destination host %H of SAD entry (reqid: %u,"
+ " spi: %x, proto: %u)", dst, reqid, ntohl(spi), proto);
+ }
+ else
+ {
+ DBG3(DBG_KNL, "no SAD entry found for reqid %u, spi %x, proto: %u",
+ reqid, ntohl(spi), proto);
+ }
+ this->mutex->unlock(this->mutex);
+ return dst;
+}
+
METHOD(tkm_kernel_sad_t, _remove, bool,
private_tkm_kernel_sad_t * const this, const esa_id_type esa_id)
{
@@ -250,6 +289,7 @@ tkm_kernel_sad_t *tkm_kernel_sad_create()
.public = {
.insert = _insert,
.get_esa_id = _get_esa_id,
+ .get_dst_host = _get_dst_host,
.remove = __remove,
.destroy = _destroy,
},
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.h b/src/charon-tkm/src/tkm/tkm_kernel_sad.h
index 39388f8a8..38b19dd01 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_sad.h
+++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.h
@@ -63,6 +63,17 @@ struct tkm_kernel_sad_t {
const u_int32_t spi, const u_int8_t proto);
/**
+ * Get destination host for entry with given parameters.
+ *
+ * @param reqid reqid of CHILD SA
+ * @param spi SPI of CHILD SA
+ * @param proto protocol of CHILD SA (ESP/AH)
+ * @return destination host of entry if found, NULL otherwise
+ */
+ host_t * (*get_dst_host)(tkm_kernel_sad_t * const this,
+ const u_int32_t reqid, const u_int32_t spi, const u_int8_t proto);
+
+ /**
* Remove entry with given ESA id from SAD.
*
* @param esa_id ESA identifier of entry to remove
diff --git a/src/charon-tkm/tests/kernel_sad_tests.c b/src/charon-tkm/tests/kernel_sad_tests.c
index 7eb2ff8e6..b9ab3cb5e 100644
--- a/src/charon-tkm/tests/kernel_sad_tests.c
+++ b/src/charon-tkm/tests/kernel_sad_tests.c
@@ -81,6 +81,29 @@ START_TEST(test_get_esa_id_nonexistent)
}
END_TEST
+START_TEST(test_get_dst_host)
+{
+ host_t *addr = host_create_from_string("127.0.0.1", 1024);
+ tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
+ fail_unless(sad->insert(sad, 23, 54, addr, addr, 42, 50),
+ "Error inserting SAD entry");
+
+ host_t *dst = sad->get_dst_host(sad, 54, 42, 50);
+ fail_unless(addr->equals(addr, dst), "Error getting dst host");
+ sad->destroy(sad);
+ addr->destroy(addr);
+}
+END_TEST
+
+START_TEST(test_get_dst_host_nonexistent)
+{
+ tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
+ fail_unless(sad->get_dst_host(sad, 1, 12, 50) == NULL,
+ "Got dst for nonexistent SAD entry");
+ sad->destroy(sad);
+}
+END_TEST
+
START_TEST(test_remove)
{
host_t *addr = host_create_from_string("127.0.0.1", 1024);
@@ -128,6 +151,11 @@ Suite *make_kernel_sad_tests()
tcase_add_test(tc, test_get_esa_id_nonexistent);
suite_add_tcase(s, tc);
+ tc = tcase_create("get_dst_host");
+ tcase_add_test(tc, test_get_dst_host);
+ tcase_add_test(tc, test_get_dst_host_nonexistent);
+ suite_add_tcase(s, tc);
+
tc = tcase_create("remove");
tcase_add_test(tc, test_remove);
tcase_add_test(tc, test_remove_nonexistent);