added child_sa serialization to ha_sync plugin
authorMartin Willi <martin@strongswan.org>
Fri, 24 Oct 2008 12:42:06 +0000 (12:42 +0000)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:11 +0000 (13:55 +0200)
src/charon/plugins/ha_sync/Makefile.am
src/charon/plugins/ha_sync/ha_sync_child.c [new file with mode: 0644]
src/charon/plugins/ha_sync/ha_sync_child.h [new file with mode: 0644]
src/charon/plugins/ha_sync/ha_sync_plugin.c

index fc122c0..be4e358 100644 (file)
@@ -4,6 +4,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
 AM_CFLAGS = -rdynamic
 
 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
 
diff --git a/src/charon/plugins/ha_sync/ha_sync_child.c b/src/charon/plugins/ha_sync/ha_sync_child.c
new file mode 100644 (file)
index 0000000..1d05f20
--- /dev/null
@@ -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;
+}
+
diff --git a/src/charon/plugins/ha_sync/ha_sync_child.h b/src/charon/plugins/ha_sync/ha_sync_child.h
new file mode 100644 (file)
index 0000000..6b66c8c
--- /dev/null
@@ -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_ @}*/
index 40e5f18..1dfa14d 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "ha_sync_plugin.h"
+#include "ha_sync_child.h"
 
 #include <daemon.h>
 #include <config/child_cfg.h>
@@ -33,35 +34,18 @@ struct private_ha_sync_plugin_t {
        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
  */
 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);
 }
 
@@ -74,10 +58,8 @@ plugin_t *plugin_create()
 
        this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
 
-       memset(&this->listener, 0, sizeof(listener_t));
-       this->listener.child_state_change = child_state_change;
-
-       charon->bus->add_listener(charon->bus, &this->listener);
+       this->child = ha_sync_child_create();
+       charon->bus->add_listener(charon->bus, &this->child->listener);
 
        return &this->public.plugin;
 }