pushing basic CHILD_SA sync data to backup node
authorMartin Willi <martin@strongswan.org>
Tue, 18 Nov 2008 15:21:10 +0000 (15:21 +0000)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:11 +0000 (13:55 +0200)
src/charon/plugins/ha_sync/ha_sync_child.c
src/charon/plugins/ha_sync/ha_sync_dispatcher.c
src/charon/plugins/ha_sync/ha_sync_message.c
src/charon/plugins/ha_sync/ha_sync_message.h

index ab6908e..260d33e 100644 (file)
@@ -42,6 +42,85 @@ static bool child_keys(private_ha_sync_child_t *this, ike_sa_t *ike_sa,
                                           child_sa_t *child_sa, diffie_hellman_t *dh,
                                           chunk_t nonce_i, chunk_t nonce_r)
 {
+       ha_sync_message_t *m;
+       chunk_t secret;
+       proposal_t *proposal;
+       u_int16_t alg, len;
+       linked_list_t *list;
+       enumerator_t *enumerator;
+       traffic_selector_t *ts;
+
+       m = ha_sync_message_create(HA_SYNC_CHILD_ADD);
+
+       m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
+       m->add_attribute(m, HA_SYNC_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE));
+       m->add_attribute(m, HA_SYNC_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE));
+       m->add_attribute(m, HA_SYNC_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE));
+       m->add_attribute(m, HA_SYNC_OUTBOUND_CPI, child_sa->get_cpi(child_sa, FALSE));
+       m->add_attribute(m, HA_SYNC_IPSEC_MODE, child_sa->get_mode(child_sa));
+       m->add_attribute(m, HA_SYNC_IPCOMP, child_sa->get_ipcomp(child_sa));
+       m->add_attribute(m, HA_SYNC_CONFIG_NAME, child_sa->get_name(child_sa));
+
+       proposal = child_sa->get_proposal(child_sa);
+       if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
+       {
+               m->add_attribute(m, HA_SYNC_ALG_ENCR, alg);
+               if (len)
+               {
+                       m->add_attribute(m, HA_SYNC_ALG_ENCR_LEN, len);
+               }
+       }
+       if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+       {
+               m->add_attribute(m, HA_SYNC_ALG_INTEG, alg);
+       }
+       m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i);
+       m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r);
+       if (dh && dh->get_shared_secret(dh, &secret) == SUCCESS)
+       {
+               m->add_attribute(m, HA_SYNC_SECRET, secret);
+               chunk_clear(&secret);
+       }
+
+       list = child_sa->get_traffic_selectors(child_sa, TRUE);
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &ts))
+       {
+               m->add_attribute(m, HA_SYNC_LOCAL_TS, ts);
+       }
+       enumerator->destroy(enumerator);
+       list = child_sa->get_traffic_selectors(child_sa, FALSE);
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &ts))
+       {
+               m->add_attribute(m, HA_SYNC_REMOTE_TS, ts);
+       }
+       enumerator->destroy(enumerator);
+
+       this->socket->push(this->socket, m);
+       m->destroy(m);
+
+       return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+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_DESTROYING)
+       {
+               ha_sync_message_t *m;
+
+               m = ha_sync_message_create(HA_SYNC_CHILD_DELETE);
+
+               m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
+               m->add_attribute(m, HA_SYNC_INBOUND_SPI,
+                                                child_sa->get_spi(child_sa, TRUE));
+               this->socket->push(this->socket, m);
+               m->destroy(m);
+       }
        return TRUE;
 }
 
@@ -62,6 +141,7 @@ ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket)
 
        memset(&this->public.listener, 0, sizeof(listener_t));
        this->public.listener.child_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
+       this->public.listener.child_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state))child_state_change;
        this->public.destroy = (void(*)(ha_sync_child_t*))destroy;
 
        this->socket = socket;
index b42ca51..dc404a5 100644 (file)
@@ -271,6 +271,28 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this,
 }
 
 /**
+ * Process messages of type CHILD_ADD
+ */
+static void process_child_add(private_ha_sync_dispatcher_t *this,
+                                                         ha_sync_message_t *message)
+{
+       chunk_t chunk = message->get_encoding(message);
+
+       DBG1(DBG_CHD, "CHILD_ADD: %B", &chunk);
+}
+
+/**
+ * Process messages of type CHILD_DELETE
+ */
+static void process_child_delete(private_ha_sync_dispatcher_t *this,
+                                                                ha_sync_message_t *message)
+{
+       chunk_t chunk = message->get_encoding(message);
+
+       DBG1(DBG_CHD, "CHILD_DELETE: %B", &chunk);
+}
+
+/**
  * Dispatcher job function
  */
 static job_requeue_t dispatch(private_ha_sync_dispatcher_t *this)
@@ -292,8 +314,10 @@ static job_requeue_t dispatch(private_ha_sync_dispatcher_t *this)
                case HA_SYNC_IKE_REKEY:
                        break;
                case HA_SYNC_CHILD_ADD:
+                       process_child_add(this, message);
                        break;
                case HA_SYNC_CHILD_DELETE:
+                       process_child_delete(this, message);
                        break;
                default:
                        DBG1(DBG_CFG, "received unknown HA sync message type %d",
index 7a1fc71..ad94928 100644 (file)
@@ -81,6 +81,20 @@ struct host_encoding_t {
        char encoding[];
 } __attribute__((packed));
 
+typedef struct ts_encoding_t ts_encoding_t;
+
+/**
+ * encoding of a traffic_selector_t
+ */
+struct ts_encoding_t {
+       u_int8_t type;
+       u_int8_t protocol;
+       u_int16_t from_port;
+       u_int16_t to_port;
+       u_int8_t dynamic;
+       char encoding[];
+} __attribute__((packed));
+
 /**
  * Implementation of ha_sync_message_t.get_type
  */
@@ -191,11 +205,25 @@ static void add_attribute(private_ha_sync_message_t *this,
                        this->buf.len += len;
                        break;
                }
+               /* u_int8_t */
+               case HA_SYNC_IPSEC_MODE:
+               case HA_SYNC_IPCOMP:
+               {
+                       u_int8_t val;
+
+                       val = (u_int8_t)va_arg(args, u_int32_t);
+                       check_buf(this, sizeof(val));
+                       this->buf.ptr[this->buf.len] = val;
+                       this->buf.len += sizeof(val);
+                       break;
+               }
                /* u_int16_t */
                case HA_SYNC_ALG_PRF:
                case HA_SYNC_ALG_ENCR:
                case HA_SYNC_ALG_ENCR_LEN:
                case HA_SYNC_ALG_INTEG:
+               case HA_SYNC_INBOUND_CPI:
+               case HA_SYNC_OUTBOUND_CPI:
                {
                        u_int16_t val;
 
@@ -208,6 +236,8 @@ static void add_attribute(private_ha_sync_message_t *this,
                /** u_int32_t */
                case HA_SYNC_CONDITIONS:
                case HA_SYNC_EXTENSIONS:
+               case HA_SYNC_INBOUND_SPI:
+               case HA_SYNC_OUTBOUND_SPI:
                {
                        u_int32_t val;
 
@@ -232,6 +262,28 @@ static void add_attribute(private_ha_sync_message_t *this,
                        this->buf.len += chunk.len + sizeof(u_int16_t);;
                        break;
                }
+               /** traffic_selector_t */
+               case HA_SYNC_LOCAL_TS:
+               case HA_SYNC_REMOTE_TS:
+               {
+                       ts_encoding_t *enc;
+                       traffic_selector_t *ts;
+                       chunk_t data;
+
+                       ts = va_arg(args, traffic_selector_t*);
+                       data = chunk_cata("cc", ts->get_from_address(ts),
+                                                         ts->get_to_address(ts));
+                       check_buf(this, sizeof(ts_encoding_t) + data.len);
+                       enc = (ts_encoding_t*)(this->buf.ptr + this->buf.len);
+                       this->buf.len += sizeof(ts_encoding_t) + data.len;
+                       enc->type = ts->get_type(ts);
+                       enc->protocol = ts->get_protocol(ts);
+                       enc->from_port = htons(ts->get_from_port(ts));
+                       enc->to_port = htons(ts->get_to_port(ts));
+                       enc->dynamic = ts->is_dynamic(ts);
+                       memcpy(enc->encoding, data.ptr, data.len);
+                       break;
+               }
                default:
                {
                        DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
@@ -363,11 +415,26 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
                        this->buf = chunk_skip(this->buf, len + 1);
                        return TRUE;
                }
+               /* u_int8_t */
+               case HA_SYNC_IPSEC_MODE:
+               case HA_SYNC_IPCOMP:
+               {
+                       if (this->buf.len < sizeof(u_int8_t))
+                       {
+                               return FALSE;
+                       }
+                       value->u8 = *(u_int8_t*)this->buf.ptr;
+                       *attr_out = attr;
+                       this->buf = chunk_skip(this->buf, sizeof(u_int8_t));
+                       return TRUE;
+               }
                /** u_int16_t */
                case HA_SYNC_ALG_PRF:
                case HA_SYNC_ALG_ENCR:
                case HA_SYNC_ALG_ENCR_LEN:
                case HA_SYNC_ALG_INTEG:
+               case HA_SYNC_INBOUND_CPI:
+               case HA_SYNC_OUTBOUND_CPI:
                {
                        if (this->buf.len < sizeof(u_int16_t))
                        {
@@ -381,6 +448,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
                /** u_int32_t */
                case HA_SYNC_CONDITIONS:
                case HA_SYNC_EXTENSIONS:
+               case HA_SYNC_INBOUND_SPI:
+               case HA_SYNC_OUTBOUND_SPI:
                {
                        if (this->buf.len < sizeof(u_int32_t))
                        {
@@ -414,6 +483,69 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
                        this->buf = chunk_skip(this->buf, len);
                        return TRUE;
                }
+               case HA_SYNC_LOCAL_TS:
+               case HA_SYNC_REMOTE_TS:
+               {
+                       ts_encoding_t *enc;
+                       host_t *host;
+                       int addr_len;
+
+                       enc = (ts_encoding_t*)(this->buf.ptr);
+                       if (this->buf.len < sizeof(ts_encoding_t))
+                       {
+                               return FALSE;
+                       }
+                       switch (enc->type)
+                       {
+                               case TS_IPV4_ADDR_RANGE:
+                                       addr_len = 4;
+                                       if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
+                                       {
+                                               return FALSE;
+                                       }
+                                       break;
+                               case TS_IPV6_ADDR_RANGE:
+                                       addr_len = 16;
+                                       if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
+                                       {
+                                               return FALSE;
+                                       }
+                                       break;
+                               default:
+                                       return FALSE;
+                       }
+                       if (enc->dynamic)
+                       {
+                               host = host_create_from_chunk(0,
+                                                                       chunk_create(enc->encoding, addr_len), 0);
+                               if (!host)
+                               {
+                                       return FALSE;
+                               }
+                               value->ts = traffic_selector_create_dynamic(enc->protocol,
+                                                                       ntohs(enc->from_port), ntohs(enc->to_port));
+                               value->ts->set_address(value->ts, host);
+                               host->destroy(host);
+                       }
+                       else
+                       {
+                               value->ts = traffic_selector_create_from_bytes(enc->protocol,
+                                                               enc->type, chunk_create(enc->encoding, addr_len),
+                                                               ntohs(enc->from_port),
+                                                               chunk_create(enc->encoding + addr_len, addr_len),
+                                                               ntohs(enc->to_port));
+                               if (!value->ts)
+                               {
+                                       return FALSE;
+                               }
+                       }
+                       *attr_out = attr;
+                       this->cleanup = (void*)value->ts->destroy;
+                       this->cleanup_data = value->ts;
+                       this->buf = chunk_skip(this->buf, sizeof(ts_encoding_t)
+                                                                               + addr_len * 2);
+                       return TRUE;
+               }
                default:
                {
                        return FALSE;
index e7d358c..c28b842 100644 (file)
@@ -27,6 +27,7 @@
 #include <utils/host.h>
 #include <utils/identification.h>
 #include <sa/ike_sa_id.h>
+#include <config/traffic_selector.h>
 
 /**
  * Protocol version of this implementation
@@ -100,19 +101,37 @@ enum ha_sync_message_attribute_t {
        HA_SYNC_ALG_ENCR_LEN,
        /** u_int16_t, integrity protection algorithm */
        HA_SYNC_ALG_INTEG,
+       /** u_int8_t, IPsec mode, TUNNEL|TRANSPORT|... */
+       HA_SYNC_IPSEC_MODE,
+       /** u_int8_t, IPComp protocol */
+       HA_SYNC_IPCOMP,
+       /** u_int32_t, inbound security parameter index */
+       HA_SYNC_INBOUND_SPI,
+       /** u_int32_t, outbound security parameter index */
+       HA_SYNC_OUTBOUND_SPI,
+       /** u_int16_t, inbound security parameter index */
+       HA_SYNC_INBOUND_CPI,
+       /** u_int16_t, outbound security parameter index */
+       HA_SYNC_OUTBOUND_CPI,
+       /** traffic_selector_t*, local traffic selector */
+       HA_SYNC_LOCAL_TS,
+       /** traffic_selector_t*, remote traffic selector */
+       HA_SYNC_REMOTE_TS,
 };
 
 /**
  * Union to enumerate typed attributes in a message
  */
 union ha_sync_message_value_t {
-       u_int32_t u32;
+       u_int8_t u8;
        u_int16_t u16;
+       u_int32_t u32;
        char *str;
        chunk_t chunk;
        ike_sa_id_t *ike_sa_id;
        identification_t *id;
        host_t *host;
+       traffic_selector_t *ts;
 };
 
 /**