added child_sa serialization to ha_sync plugin
This commit is contained in:
committed by
Martin Willi
parent
e67f5136c0
commit
e16d76f9a4
@@ -4,6 +4,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
|
|||||||
AM_CFLAGS = -rdynamic
|
AM_CFLAGS = -rdynamic
|
||||||
|
|
||||||
plugin_LTLIBRARIES = libstrongswan-ha-sync.la
|
plugin_LTLIBRARIES = libstrongswan-ha-sync.la
|
||||||
libstrongswan_ha_sync_la_SOURCES = ha_sync_plugin.h ha_sync_plugin.c
|
libstrongswan_ha_sync_la_SOURCES = ha_sync_plugin.h ha_sync_plugin.c \
|
||||||
|
ha_sync_child.h ha_sync_child.c
|
||||||
libstrongswan_ha_sync_la_LDFLAGS = -module
|
libstrongswan_ha_sync_la_LDFLAGS = -module
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ha_sync_child.h"
|
||||||
|
|
||||||
|
typedef struct private_ha_sync_child_t private_ha_sync_child_t;
|
||||||
|
typedef struct serialized_child_sa_t serialized_child_sa_t;
|
||||||
|
typedef struct serialized_ts_t serialized_ts_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an ha_sync_child_t object.
|
||||||
|
*/
|
||||||
|
struct private_ha_sync_child_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public ha_sync_child_t interface.
|
||||||
|
*/
|
||||||
|
ha_sync_child_t public;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* version number of serialization fromat */
|
||||||
|
#define SERIALIZE_VERSION 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serialized traffic selector
|
||||||
|
*/
|
||||||
|
struct serialized_ts_t {
|
||||||
|
u_int8_t type;
|
||||||
|
u_int8_t protocol;
|
||||||
|
u_int8_t dynamic;
|
||||||
|
struct {
|
||||||
|
u_int8_t addr[16];
|
||||||
|
u_int16_t port;
|
||||||
|
} from, to;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serialized CHILD_SA
|
||||||
|
*/
|
||||||
|
struct serialized_child_sa_t {
|
||||||
|
|
||||||
|
u_int8_t version;
|
||||||
|
|
||||||
|
/* per CHILD values */
|
||||||
|
u_int8_t protocol;
|
||||||
|
u_int8_t mode;
|
||||||
|
u_int8_t encap;
|
||||||
|
u_int8_t ipcomp;
|
||||||
|
u_int32_t soft_lifetime;
|
||||||
|
u_int32_t hard_lifetime;
|
||||||
|
|
||||||
|
/* configuration name */
|
||||||
|
char config[32];
|
||||||
|
|
||||||
|
/* algs and keys */
|
||||||
|
struct {
|
||||||
|
u_int16_t alg;
|
||||||
|
u_int16_t keylen;
|
||||||
|
u_int8_t in[64], out[64];
|
||||||
|
} integrity, encryption;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u_int32_t spi;
|
||||||
|
u_int16_t cpi;
|
||||||
|
|
||||||
|
u_int8_t addr_fam;
|
||||||
|
u_int8_t addr[16];
|
||||||
|
u_int16_t port;
|
||||||
|
|
||||||
|
/* traffic selector, currently only one, TODO */
|
||||||
|
serialized_ts_t ts;
|
||||||
|
} in, out;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize a traffic selector list
|
||||||
|
*/
|
||||||
|
static void serialize_ts_list(linked_list_t *ts_list, serialized_ts_t *ser)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
traffic_selector_t *ts;
|
||||||
|
chunk_t chunk;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
enumerator = ts_list->create_enumerator(ts_list);
|
||||||
|
if (enumerator->enumerate(enumerator, &ts))
|
||||||
|
{
|
||||||
|
ser->type = ts->get_type(ts);
|
||||||
|
ser->protocol = ts->get_protocol(ts);
|
||||||
|
ser->dynamic = ts->is_dynamic(ts);
|
||||||
|
ser->from.port = htons(ts->get_from_port(ts));
|
||||||
|
ser->to.port = htons(ts->get_to_port(ts));
|
||||||
|
chunk = ts->get_from_address(ts);
|
||||||
|
memcpy(ser->from.addr, chunk.ptr, min(chunk.len, sizeof(ser->from.addr)));
|
||||||
|
chunk = ts->get_to_address(ts);
|
||||||
|
memcpy(ser->to.addr, chunk.ptr, min(chunk.len, sizeof(ser->to.addr)));
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize a CHILD_SA
|
||||||
|
*/
|
||||||
|
static chunk_t serialize(ike_sa_t *ike_sa, child_sa_t *child_sa)
|
||||||
|
{
|
||||||
|
serialized_child_sa_t *ser;
|
||||||
|
child_cfg_t *config;
|
||||||
|
host_t *me, *other;
|
||||||
|
chunk_t chunk;
|
||||||
|
|
||||||
|
config = child_sa->get_config(child_sa);
|
||||||
|
me = ike_sa->get_my_host(ike_sa);
|
||||||
|
other = ike_sa->get_other_host(ike_sa);
|
||||||
|
|
||||||
|
ser = malloc_thing(serialized_child_sa_t);
|
||||||
|
memset(ser, 0, sizeof(serialized_child_sa_t));
|
||||||
|
|
||||||
|
ser->version = SERIALIZE_VERSION;
|
||||||
|
ser->protocol = child_sa->get_protocol(child_sa);
|
||||||
|
ser->mode = child_sa->get_mode(child_sa);
|
||||||
|
ser->encap = child_sa->has_encap(child_sa);
|
||||||
|
ser->ipcomp = child_sa->get_ipcomp(child_sa);
|
||||||
|
ser->soft_lifetime = child_sa->get_lifetime(child_sa, FALSE);
|
||||||
|
ser->hard_lifetime = child_sa->get_lifetime(child_sa, TRUE);
|
||||||
|
ser->in.spi = child_sa->get_spi(child_sa, TRUE);
|
||||||
|
ser->in.cpi = child_sa->get_cpi(child_sa, TRUE);
|
||||||
|
ser->out.spi = child_sa->get_spi(child_sa, FALSE);
|
||||||
|
ser->out.cpi = child_sa->get_cpi(child_sa, FALSE);
|
||||||
|
snprintf(ser->config, sizeof(ser->config), config->get_name(config));
|
||||||
|
|
||||||
|
ser->integrity.alg = child_sa->get_integrity(child_sa, TRUE, &chunk);
|
||||||
|
ser->integrity.keylen = chunk.len;
|
||||||
|
memcpy(ser->integrity.in, chunk.ptr, ser->integrity.keylen);
|
||||||
|
child_sa->get_integrity(child_sa, FALSE, &chunk);
|
||||||
|
memcpy(ser->integrity.out, chunk.ptr, ser->integrity.keylen);
|
||||||
|
|
||||||
|
ser->encryption.alg = child_sa->get_encryption(child_sa, TRUE, &chunk);
|
||||||
|
ser->encryption.keylen = chunk.len;
|
||||||
|
memcpy(ser->encryption.in, chunk.ptr, ser->encryption.keylen);
|
||||||
|
child_sa->get_integrity(child_sa, FALSE, &chunk);
|
||||||
|
memcpy(ser->encryption.out, chunk.ptr, ser->encryption.keylen);
|
||||||
|
|
||||||
|
ser->in.addr_fam = me->get_family(me);
|
||||||
|
ser->in.port = htons(me->get_port(me));
|
||||||
|
chunk = me->get_address(me);
|
||||||
|
memcpy(ser->in.addr, chunk.ptr, chunk.len);
|
||||||
|
|
||||||
|
ser->out.addr_fam = other->get_family(other);
|
||||||
|
ser->out.port = htons(other->get_port(other));
|
||||||
|
chunk = other->get_address(other);
|
||||||
|
memcpy(ser->out.addr, chunk.ptr, chunk.len);
|
||||||
|
|
||||||
|
serialize_ts_list(child_sa->get_traffic_selectors(child_sa, TRUE),
|
||||||
|
&ser->in.ts);
|
||||||
|
serialize_ts_list(child_sa->get_traffic_selectors(child_sa, FALSE),
|
||||||
|
&ser->out.ts);
|
||||||
|
|
||||||
|
return chunk_create((void*)ser, sizeof(serialized_child_sa_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener implementation
|
||||||
|
*/
|
||||||
|
static bool child_state_change(private_ha_sync_child_t *this, ike_sa_t *ike_sa,
|
||||||
|
child_sa_t *child_sa, child_sa_state_t state)
|
||||||
|
{
|
||||||
|
if (state == CHILD_INSTALLED)
|
||||||
|
{
|
||||||
|
chunk_t chunk;
|
||||||
|
|
||||||
|
chunk = serialize(ike_sa, child_sa);
|
||||||
|
DBG1(DBG_IKE, "NEW CHILD: %B", &chunk);
|
||||||
|
|
||||||
|
chunk_clear(&chunk);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ha_sync_child_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_ha_sync_child_t *this)
|
||||||
|
{
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
ha_sync_child_t *ha_sync_child_create()
|
||||||
|
{
|
||||||
|
private_ha_sync_child_t *this = malloc_thing(private_ha_sync_child_t);
|
||||||
|
|
||||||
|
memset(&this->public.listener, 0, sizeof(listener_t));
|
||||||
|
|
||||||
|
this->public.listener.child_state_change = (void*)child_state_change;
|
||||||
|
this->public.destroy = (void(*)(ha_sync_child_t*))destroy;
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup ha_sync_child ha_sync_child
|
||||||
|
* @{ @ingroup ha_sync
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HA_SYNC_CHILD_H_
|
||||||
|
#define HA_SYNC_CHILD_H_
|
||||||
|
|
||||||
|
#include <daemon.h>
|
||||||
|
|
||||||
|
typedef struct ha_sync_child_t ha_sync_child_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize CHILD_SAs.
|
||||||
|
*/
|
||||||
|
struct ha_sync_child_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements bus listener interface.
|
||||||
|
*/
|
||||||
|
listener_t listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a ha_sync_child_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(ha_sync_child_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ha_sync_child instance.
|
||||||
|
*/
|
||||||
|
ha_sync_child_t *ha_sync_child_create();
|
||||||
|
|
||||||
|
#endif /* HA_SYNC_CHILD_ @}*/
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ha_sync_plugin.h"
|
#include "ha_sync_plugin.h"
|
||||||
|
#include "ha_sync_child.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <config/child_cfg.h>
|
#include <config/child_cfg.h>
|
||||||
@@ -33,35 +34,18 @@ struct private_ha_sync_plugin_t {
|
|||||||
ha_sync_plugin_t public;
|
ha_sync_plugin_t public;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener interface, listens to CHILD_SA state changes
|
* CHILD_SA sync
|
||||||
*/
|
*/
|
||||||
listener_t listener;
|
ha_sync_child_t *child;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener implementation
|
|
||||||
*/
|
|
||||||
static bool child_state_change(listener_t *this, ike_sa_t *ike_sa,
|
|
||||||
child_sa_t *child_sa, child_sa_state_t state)
|
|
||||||
{
|
|
||||||
if (state == CHILD_INSTALLED)
|
|
||||||
{
|
|
||||||
chunk_t chunk;
|
|
||||||
|
|
||||||
chunk = child_sa->serialize(child_sa);
|
|
||||||
DBG1(DBG_IKE, "NEW CHILD: %B", &chunk);
|
|
||||||
|
|
||||||
chunk_clear(&chunk);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of plugin_t.destroy
|
* Implementation of plugin_t.destroy
|
||||||
*/
|
*/
|
||||||
static void destroy(private_ha_sync_plugin_t *this)
|
static void destroy(private_ha_sync_plugin_t *this)
|
||||||
{
|
{
|
||||||
charon->bus->remove_listener(charon->bus, &this->listener);
|
charon->bus->remove_listener(charon->bus, &this->child->listener);
|
||||||
|
this->child->destroy(this->child);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,10 +58,8 @@ plugin_t *plugin_create()
|
|||||||
|
|
||||||
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
|
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
|
||||||
|
|
||||||
memset(&this->listener, 0, sizeof(listener_t));
|
this->child = ha_sync_child_create();
|
||||||
this->listener.child_state_change = child_state_change;
|
charon->bus->add_listener(charon->bus, &this->child->listener);
|
||||||
|
|
||||||
charon->bus->add_listener(charon->bus, &this->listener);
|
|
||||||
|
|
||||||
return &this->public.plugin;
|
return &this->public.plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user