child-sa-manager: Add a global manager storing CHILD_SA relations
To quickly check out IKE_SAs and find associated CHILD_SAs, the child_sa_manager stores relations between CHILD_SAs and IKE_SAs. It provides CHILD_SA specific IKE_SA checkout functions wrapping the ike_sa_manager.
This commit is contained in:
@@ -72,6 +72,7 @@ sa/ike_sa.c sa/ike_sa.h \
|
||||
sa/ike_sa_id.c sa/ike_sa_id.h \
|
||||
sa/keymat.h sa/keymat.c \
|
||||
sa/ike_sa_manager.c sa/ike_sa_manager.h \
|
||||
sa/child_sa_manager.c sa/child_sa_manager.h \
|
||||
sa/task_manager.h sa/task_manager.c \
|
||||
sa/shunt_manager.c sa/shunt_manager.h \
|
||||
sa/trap_manager.c sa/trap_manager.h \
|
||||
@@ -238,4 +239,3 @@ LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ sa/ike_sa.c sa/ike_sa.h \
|
||||
sa/ike_sa_id.c sa/ike_sa_id.h \
|
||||
sa/keymat.h sa/keymat.c \
|
||||
sa/ike_sa_manager.c sa/ike_sa_manager.h \
|
||||
sa/child_sa_manager.c sa/child_sa_manager.h \
|
||||
sa/task_manager.h sa/task_manager.c \
|
||||
sa/shunt_manager.c sa/shunt_manager.h \
|
||||
sa/trap_manager.c sa/trap_manager.h \
|
||||
|
||||
@@ -480,6 +480,7 @@ static void destroy(private_daemon_t *this)
|
||||
DESTROY_IF(this->kernel_handler);
|
||||
DESTROY_IF(this->public.traps);
|
||||
DESTROY_IF(this->public.shunts);
|
||||
DESTROY_IF(this->public.child_sa_manager);
|
||||
DESTROY_IF(this->public.ike_sa_manager);
|
||||
DESTROY_IF(this->public.controller);
|
||||
DESTROY_IF(this->public.eap);
|
||||
@@ -606,6 +607,7 @@ METHOD(daemon_t, initialize, bool,
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->public.child_sa_manager = child_sa_manager_create();
|
||||
|
||||
/* Queue start_action job */
|
||||
lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
|
||||
|
||||
@@ -158,6 +158,7 @@ typedef struct daemon_t daemon_t;
|
||||
#include <control/controller.h>
|
||||
#include <bus/bus.h>
|
||||
#include <sa/ike_sa_manager.h>
|
||||
#include <sa/child_sa_manager.h>
|
||||
#include <sa/trap_manager.h>
|
||||
#include <sa/shunt_manager.h>
|
||||
#include <config/backend_manager.h>
|
||||
@@ -214,6 +215,11 @@ struct daemon_t {
|
||||
*/
|
||||
ike_sa_manager_t *ike_sa_manager;
|
||||
|
||||
/**
|
||||
* A child_sa_manager_t instance.
|
||||
*/
|
||||
child_sa_manager_t *child_sa_manager;
|
||||
|
||||
/**
|
||||
* Manager for triggering policies, called traps
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martin Willi
|
||||
* Copyright (C) 2014 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "child_sa_manager.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <threading/mutex.h>
|
||||
#include <collections/hashtable.h>
|
||||
|
||||
typedef struct private_child_sa_manager_t private_child_sa_manager_t;
|
||||
|
||||
/**
|
||||
* Private data of an child_sa_manager_t object.
|
||||
*/
|
||||
struct private_child_sa_manager_t {
|
||||
|
||||
/**
|
||||
* Public child_sa_manager_t interface.
|
||||
*/
|
||||
child_sa_manager_t public;
|
||||
|
||||
/**
|
||||
* CHILD_SAs by inbound SPI/dst, child_entry_t => child_entry_t
|
||||
*/
|
||||
hashtable_t *in;
|
||||
|
||||
/**
|
||||
* CHILD_SAs by outbound SPI/dst, child_entry_t => child_entry_t
|
||||
*/
|
||||
hashtable_t *out;
|
||||
|
||||
/**
|
||||
* CHILD_SAs by unique ID, child_entry_t => child_entry_t
|
||||
*/
|
||||
hashtable_t *ids;
|
||||
|
||||
/**
|
||||
* Mutex to access any hashtable
|
||||
*/
|
||||
mutex_t *mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hashtable entry for a known CHILD_SA
|
||||
*/
|
||||
typedef struct {
|
||||
/** the associated IKE_SA */
|
||||
ike_sa_id_t *ike_id;
|
||||
/** unique CHILD_SA identifier */
|
||||
u_int32_t unique_id;
|
||||
/** inbound SPI */
|
||||
u_int32_t spi_in;
|
||||
/** outbound SPI */
|
||||
u_int32_t spi_out;
|
||||
/** inbound host address */
|
||||
host_t *host_in;
|
||||
/** outbound host address and port */
|
||||
host_t *host_out;
|
||||
/** IPsec protocol, AH|ESP */
|
||||
protocol_id_t proto;
|
||||
} child_entry_t;
|
||||
|
||||
/**
|
||||
* Destroy a CHILD_SA entry
|
||||
*/
|
||||
static void child_entry_destroy(child_entry_t *entry)
|
||||
{
|
||||
entry->ike_id->destroy(entry->ike_id);
|
||||
entry->host_in->destroy(entry->host_in);
|
||||
entry->host_out->destroy(entry->host_out);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable hash function for inbound SAs
|
||||
*/
|
||||
static u_int hash_in(child_entry_t *entry)
|
||||
{
|
||||
return chunk_hash_inc(chunk_from_thing(entry->spi_in),
|
||||
chunk_hash_inc(entry->host_in->get_address(entry->host_in),
|
||||
chunk_hash(chunk_from_thing(entry->proto))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable equals function for inbound SAs
|
||||
*/
|
||||
static bool equals_in(child_entry_t *a, child_entry_t *b)
|
||||
{
|
||||
return a->spi_in == b->spi_in &&
|
||||
a->proto == b->proto &&
|
||||
a->host_in->ip_equals(a->host_in, b->host_in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable hash function for outbound SAs
|
||||
*/
|
||||
static u_int hash_out(child_entry_t *entry)
|
||||
{
|
||||
return chunk_hash_inc(chunk_from_thing(entry->spi_out),
|
||||
chunk_hash_inc(entry->host_out->get_address(entry->host_out),
|
||||
chunk_hash(chunk_from_thing(entry->proto))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable equals function for outbound SAs
|
||||
*/
|
||||
static bool equals_out(child_entry_t *a, child_entry_t *b)
|
||||
{
|
||||
return a->spi_out == b->spi_out &&
|
||||
a->proto == b->proto &&
|
||||
a->host_out->ip_equals(a->host_out, b->host_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable hash function for SAs by unique ID
|
||||
*/
|
||||
static u_int hash_id(child_entry_t *entry)
|
||||
{
|
||||
return chunk_hash(chunk_from_thing(entry->unique_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable equals function for SAs by unique ID
|
||||
*/
|
||||
static bool equals_id(child_entry_t *a, child_entry_t *b)
|
||||
{
|
||||
return a->unique_id == b->unique_id;
|
||||
}
|
||||
|
||||
METHOD(child_sa_manager_t, add, void,
|
||||
private_child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa)
|
||||
{
|
||||
child_entry_t *entry;
|
||||
host_t *in, *out;
|
||||
ike_sa_id_t *id;
|
||||
|
||||
id = ike_sa->get_id(ike_sa);
|
||||
in = ike_sa->get_my_host(ike_sa);
|
||||
out = ike_sa->get_other_host(ike_sa);
|
||||
|
||||
INIT(entry,
|
||||
.ike_id = id->clone(id),
|
||||
.unique_id = child_sa->get_unique_id(child_sa),
|
||||
.proto = child_sa->get_protocol(child_sa),
|
||||
.spi_in = child_sa->get_spi(child_sa, TRUE),
|
||||
.spi_out = child_sa->get_spi(child_sa, FALSE),
|
||||
.host_in = in->clone(in),
|
||||
.host_out = out->clone(out),
|
||||
);
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
if (!this->in->get(this->in, entry) &&
|
||||
!this->out->get(this->out, entry))
|
||||
{
|
||||
this->in->put(this->in, entry, entry);
|
||||
this->out->put(this->out, entry, entry);
|
||||
entry = this->ids->put(this->ids, entry, entry);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
child_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(child_sa_manager_t, remove_, void,
|
||||
private_child_sa_manager_t *this, child_sa_t *child_sa)
|
||||
{
|
||||
child_entry_t *entry, key = {
|
||||
.unique_id = child_sa->get_unique_id(child_sa),
|
||||
};
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
entry = this->ids->remove(this->ids, &key);
|
||||
if (entry)
|
||||
{
|
||||
this->in->remove(this->in, entry);
|
||||
this->out->remove(this->out, entry);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
child_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out an IKE_SA for a given CHILD_SA
|
||||
*/
|
||||
static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this,
|
||||
ike_sa_id_t *id, u_int32_t unique_id, child_sa_t **child_sa)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
child_sa_t *current;
|
||||
ike_sa_t *ike_sa;
|
||||
bool found = FALSE;
|
||||
|
||||
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
||||
id->destroy(id);
|
||||
if (ike_sa)
|
||||
{
|
||||
enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
found = current->get_unique_id(current) == unique_id;
|
||||
if (found)
|
||||
{
|
||||
if (child_sa)
|
||||
{
|
||||
*child_sa = current;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (found)
|
||||
{
|
||||
return ike_sa;
|
||||
}
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*,
|
||||
private_child_sa_manager_t *this, u_int32_t unique_id,
|
||||
child_sa_t **child_sa)
|
||||
{
|
||||
ike_sa_id_t *id;
|
||||
child_entry_t *entry, key = {
|
||||
.unique_id = unique_id,
|
||||
};
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
entry = this->ids->get(this->ids, &key);
|
||||
if (entry)
|
||||
{
|
||||
id = entry->ike_id->clone(entry->ike_id);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
return checkout_ikesa(this, id, unique_id, child_sa);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(child_sa_manager_t, checkout, ike_sa_t*,
|
||||
private_child_sa_manager_t *this, protocol_id_t protocol, u_int32_t spi,
|
||||
host_t *dst, child_sa_t **child_sa)
|
||||
{
|
||||
ike_sa_id_t *id;
|
||||
u_int32_t unique_id;
|
||||
child_entry_t *entry, key = {
|
||||
.spi_in = spi,
|
||||
.spi_out = spi,
|
||||
.host_in = dst,
|
||||
.host_out = dst,
|
||||
.proto = protocol,
|
||||
};
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
entry = this->in->get(this->in, &key);
|
||||
if (!entry)
|
||||
{
|
||||
entry = this->out->get(this->out, &key);
|
||||
}
|
||||
if (entry)
|
||||
{
|
||||
unique_id = entry->unique_id;
|
||||
id = entry->ike_id->clone(entry->ike_id);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
return checkout_ikesa(this, id, unique_id, child_sa);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(child_sa_manager_t, destroy, void,
|
||||
private_child_sa_manager_t *this)
|
||||
{
|
||||
this->in->destroy(this->in);
|
||||
this->out->destroy(this->out);
|
||||
this->ids->destroy(this->ids);
|
||||
this->mutex->destroy(this->mutex);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
child_sa_manager_t *child_sa_manager_create()
|
||||
{
|
||||
private_child_sa_manager_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.add = _add,
|
||||
.remove = _remove_,
|
||||
.checkout = _checkout,
|
||||
.checkout_by_id = _checkout_by_id,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.in = hashtable_create((hashtable_hash_t)hash_in,
|
||||
(hashtable_equals_t)equals_in, 8),
|
||||
.out = hashtable_create((hashtable_hash_t)hash_out,
|
||||
(hashtable_equals_t)equals_out, 8),
|
||||
.ids = hashtable_create((hashtable_hash_t)hash_id,
|
||||
(hashtable_equals_t)equals_id, 8),
|
||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martin Willi
|
||||
* Copyright (C) 2014 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup child_sa_manager child_sa_manager
|
||||
* @{ @ingroup sa
|
||||
*/
|
||||
|
||||
#ifndef CHILD_SA_MANAGER_H_
|
||||
#define CHILD_SA_MANAGER_H_
|
||||
|
||||
#include <sa/ike_sa.h>
|
||||
#include <sa/child_sa.h>
|
||||
|
||||
typedef struct child_sa_manager_t child_sa_manager_t;
|
||||
|
||||
/**
|
||||
* Handle CHILD_SA to IKE_SA relations
|
||||
*/
|
||||
struct child_sa_manager_t {
|
||||
|
||||
/**
|
||||
* Register a CHILD_SA/IKE_SA relation.
|
||||
*
|
||||
* @param child_sa CHILD_SA to register
|
||||
* @param ike_sa IKE_SA owning the CHILD_SA
|
||||
*/
|
||||
void (*add)(child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa);
|
||||
|
||||
/**
|
||||
* Unregister a CHILD_SA/IKE_SA relation.
|
||||
*
|
||||
* @param child_sa CHILD_SA to unregister
|
||||
*/
|
||||
void (*remove)(child_sa_manager_t *this, child_sa_t *child_sa);
|
||||
|
||||
/**
|
||||
* Find a CHILD_SA and check out the associated IKE_SA by SPI.
|
||||
*
|
||||
* On success, the returned IKE_SA must be checked in after use to
|
||||
* the IKE_SA manager.
|
||||
*
|
||||
* @param protocol IPsec protocol, AH|ESP
|
||||
* @param spi SPI of CHILD_SA to check out
|
||||
* @param dst SA destination host related to SPI
|
||||
* @param child_sa returns CHILD_SA managed by IKE_SA
|
||||
* @return IKE_SA, NULL if not found
|
||||
*/
|
||||
ike_sa_t *(*checkout)(child_sa_manager_t *this,
|
||||
protocol_id_t protocol, u_int32_t spi, host_t *dst,
|
||||
child_sa_t **child_sa);
|
||||
|
||||
/**
|
||||
* Find a CHILD_SA and check out the associated IKE_SA by unique_id.
|
||||
*
|
||||
* On success, the returned IKE_SA must be checked in after use to
|
||||
* the IKE_SA manager.
|
||||
*
|
||||
* @param unique_id unique ID of CHILD_SA to check out
|
||||
* @param child_sa returns CHILD_SA managed by IKE_SA
|
||||
* @return IKE_SA, NULL if not found
|
||||
*/
|
||||
ike_sa_t *(*checkout_by_id)(child_sa_manager_t *this, u_int32_t unique_id,
|
||||
child_sa_t **child_sa);
|
||||
|
||||
/**
|
||||
* Destroy a child_sa_manager_t.
|
||||
*/
|
||||
void (*destroy)(child_sa_manager_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a child_sa_manager instance.
|
||||
*/
|
||||
child_sa_manager_t *child_sa_manager_create();
|
||||
|
||||
#endif /** CHILD_SA_MANAGER_H_ @}*/
|
||||
Reference in New Issue
Block a user