ha_sync_socket_t *socket;
};
+/**
+ * Return condition if it is set on ike_sa
+ */
+static ike_condition_t copy_condition(ike_sa_t *ike_sa, ike_condition_t cond)
+{
+ if (ike_sa->has_condition(ike_sa, cond))
+ {
+ return cond;
+ }
+ return 0;
+}
+
+/**
+ * Return extension if it is supported by peers IKE_SA
+ */
+static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
+{
+ if (ike_sa->supports_extension(ike_sa, ext))
+ {
+ return ext;
+ }
+ return 0;
+}
+
/**
* Implementation of listener_t.ike_keys
*/
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
ike_sa_t *rekey)
{
+ iterator_t *iterator;
+ ha_sync_message_t *m;
+ peer_cfg_t *peer_cfg;
+ u_int32_t extension, condition;
+ host_t *local_vip, *remote_vip, *addr;
+ identification_t *eap_id;
+ chunk_t secret;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ condition = copy_condition(ike_sa, COND_NAT_ANY)
+ | copy_condition(ike_sa, COND_NAT_HERE)
+ | copy_condition(ike_sa, COND_NAT_THERE)
+ | copy_condition(ike_sa, COND_NAT_FAKE)
+ | copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
+ | copy_condition(ike_sa, COND_CERTREQ_SEEN)
+ | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR);
+
+ extension = copy_extension(ike_sa, EXT_NATT)
+ | copy_extension(ike_sa, EXT_MOBIKE)
+ | copy_extension(ike_sa, EXT_HASH_AND_URL);
+
+ local_vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
+ remote_vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ eap_id = ike_sa->get_eap_identity(ike_sa);
+
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return TRUE;
+ }
+
+ if (rekey == NULL)
+ {
+ m = ha_sync_message_create(HA_SYNC_IKE_ADD);
+
+ m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_SYNC_LOCAL_ID, ike_sa->get_my_id(ike_sa));
+ m->add_attribute(m, HA_SYNC_REMOTE_ID, ike_sa->get_other_id(ike_sa));
+ m->add_attribute(m, HA_SYNC_LOCAL_ADDR, ike_sa->get_my_host(ike_sa));
+ m->add_attribute(m, HA_SYNC_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
+ m->add_attribute(m, HA_SYNC_CONFIG_NAME, peer_cfg->get_name(peer_cfg));
+ m->add_attribute(m, HA_SYNC_CONDITIONS, condition);
+ m->add_attribute(m, HA_SYNC_EXTENSIONS, extension);
+ if (local_vip)
+ {
+ m->add_attribute(m, HA_SYNC_LOCAL_VIP, local_vip);
+ }
+ if (remote_vip)
+ {
+ m->add_attribute(m, HA_SYNC_REMOTE_VIP, remote_vip);
+ }
+ if (eap_id)
+ {
+ m->add_attribute(m, HA_SYNC_EAP_ID, eap_id);
+ }
+ iterator = ike_sa->create_additional_address_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&addr))
+ {
+ m->add_attribute(m, HA_SYNC_ADDITIONAL_ADDR, addr);
+ }
+ iterator->destroy(iterator);
+ }
+ else
+ {
+ m = ha_sync_message_create(HA_SYNC_IKE_REKEY);
+
+ m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_SYNC_IKE_REKEY_ID, rekey->get_id(rekey));
+ }
+
+ m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i);
+ m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r);
+ m->add_attribute(m, HA_SYNC_SECRET, secret);
+ chunk_clear(&secret);
+
+ this->socket->push(this->socket, m);
+ m->destroy(m);
+
return TRUE;
}
#include <daemon.h>
+#define ALLOCATION_BLOCK 64
+
typedef struct private_ha_sync_message_t private_ha_sync_message_t;
/**
ha_sync_message_t public;
/**
- * Number of bytes allocted in buffer
+ * Allocated size of buf
*/
size_t allocated;
chunk_t buf;
};
+typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
+
+/**
+ * Encoding if an ike_sa_id_t
+ */
+struct ike_sa_id_encoding_t {
+ u_int64_t initiator_spi;
+ u_int64_t responder_spi;
+ u_int8_t initiator;
+} __attribute__((packed));
+
+typedef struct identification_encoding_t identification_encoding_t;
+
+/**
+ * Encoding of a identification_t
+ */
+struct identification_encoding_t {
+ u_int8_t type;
+ u_int8_t len;
+ char encoding[];
+} __attribute__((packed));
+
+typedef struct host_encoding_t host_encoding_t;
+
+/**
+ * encoding of a host_t
+ */
+struct host_encoding_t {
+ u_int16_t port;
+ u_int8_t family;
+ char encoding[];
+} __attribute__((packed));
+
/**
* Implementation of ha_sync_message_t.get_type
*/
*/
static void check_buf(private_ha_sync_message_t *this, size_t len)
{
+ int increased = 0;
+
while (this->buf.len + len > this->allocated)
{ /* double size */
- this->allocated = this->allocated * 2;
+ this->allocated += ALLOCATION_BLOCK;
+ increased++;
+ }
+ if (increased)
+ {
this->buf.ptr = realloc(this->buf.ptr, this->allocated);
}
}
* Implementation of ha_sync_message_t.add_attribute
*/
static void add_attribute(private_ha_sync_message_t *this,
- ha_sync_message_attribute_t attribute,
- ha_sync_message_value_t value)
+ ha_sync_message_attribute_t attribute, ...)
{
size_t len;
+ va_list args;
check_buf(this, sizeof(u_int8_t));
this->buf.ptr[this->buf.len] = attribute;
this->buf.len += sizeof(u_int8_t);
+ va_start(args, attribute);
switch (attribute)
{
- case HA_SYNC_ENCAP_U8:
- case HA_SYNC_MODE_U8:
- case HA_SYNC_IPCOMP_U8:
- check_buf(this, sizeof(value.u8));
- this->buf.ptr[this->buf.len] = value.u8;
- this->buf.len += sizeof(value.u8);
- break;
- case HA_SYNC_PORT_L_U16:
- case HA_SYNC_PORT_R_U16:
- case HA_SYNC_CPI_L_U16:
- case HA_SYNC_CPI_R_U16:
- case HA_SYNC_ALG_INTEG_U16:
- case HA_SYNC_ALG_ENC_U16:
- check_buf(this, sizeof(value.u16));
- this->buf.ptr[this->buf.len] = htons(value.u16);
- this->buf.len += sizeof(value.u16);
+ /* ike_sa_id_t* */
+ case HA_SYNC_IKE_ID:
+ case HA_SYNC_IKE_REKEY_ID:
+ {
+ ike_sa_id_encoding_t *enc;
+ ike_sa_id_t *id;
+
+ id = va_arg(args, ike_sa_id_t*);
+ check_buf(this, sizeof(ike_sa_id_encoding_t));
+ enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(ike_sa_id_encoding_t);
+ enc->initiator = id->is_initiator(id);
+ enc->initiator_spi = id->get_initiator_spi(id);
+ enc->responder_spi = id->get_responder_spi(id);
break;
- case HA_SYNC_SPI_L_U32:
- case HA_SYNC_SPI_R_U32:
- check_buf(this, sizeof(value.u32));
- this->buf.ptr[this->buf.len] = htonl(value.u32);
- this->buf.len += sizeof(value.u32);
+ }
+ /* identification_t* */
+ case HA_SYNC_LOCAL_ID:
+ case HA_SYNC_REMOTE_ID:
+ case HA_SYNC_EAP_ID:
+ {
+ identification_encoding_t *enc;
+ identification_t *id;
+ chunk_t data;
+
+ id = va_arg(args, identification_t*);
+ data = id->get_encoding(id);
+ check_buf(this, sizeof(identification_encoding_t) + data.len);
+ enc = (identification_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(identification_encoding_t) + data.len;
+ enc->type = id->get_type(id);
+ enc->len = data.len;
+ memcpy(enc->encoding, data.ptr, data.len);
break;
- case HA_SYNC_IPV4_L_CHNK:
- case HA_SYNC_IPV4_R_CHNK:
- case HA_SYNC_NONCE_I_CHNK:
- case HA_SYNC_NONCE_R_CHNK:
- case HA_SYNC_SECRET_CHNK:
- check_buf(this, value.chnk.len);
- memcpy(this->buf.ptr + this->buf.len, value.chnk.ptr, value.chnk.len);
- this->buf.len += value.chnk.len;
+ }
+ /* host_t* */
+ case HA_SYNC_LOCAL_ADDR:
+ case HA_SYNC_REMOTE_ADDR:
+ case HA_SYNC_LOCAL_VIP:
+ case HA_SYNC_REMOTE_VIP:
+ case HA_SYNC_ADDITIONAL_ADDR:
+ {
+ host_encoding_t *enc;
+ host_t *host;
+ chunk_t data;
+
+ host = va_arg(args, host_t*);
+ data = host->get_address(host);
+ check_buf(this, sizeof(host_encoding_t) + data.len);
+ enc = (host_encoding_t*)(this->buf.ptr + this->buf.len);
+ this->buf.len += sizeof(host_encoding_t) + data.len;
+ enc->family = host->get_family(host);
+ enc->port = htons(host->get_port(host));
+ memcpy(enc->encoding, data.ptr, data.len);
break;
- case HA_SYNC_CONFIG_STR:
- len = strlen(value.str) + 1;
+ }
+ /* char* */
+ case HA_SYNC_CONFIG_NAME:
+ {
+ char *str;
+
+ str = va_arg(args, char*);
+ len = strlen(str) + 1;
check_buf(this, len);
- memcpy(this->buf.ptr + this->buf.len, value.str, len);
+ memcpy(this->buf.ptr + this->buf.len, str, len);
this->buf.len += len;
break;
+ }
+ /** u_int32_t */
+ case HA_SYNC_CONDITIONS:
+ case HA_SYNC_EXTENSIONS:
+ {
+ u_int32_t val;
+
+ val = va_arg(args, u_int32_t);
+ check_buf(this, sizeof(val));
+ this->buf.ptr[this->buf.len] = htonl(val);
+ this->buf.len += sizeof(val);
+ break;
+ }
+ /** chunk_t */
+ case HA_SYNC_NONCE_I:
+ case HA_SYNC_NONCE_R:
+ case HA_SYNC_SECRET:
+ {
+ chunk_t chunk;
+
+ chunk = va_arg(args, chunk_t);
+ check_buf(this, chunk.len);
+ memcpy(this->buf.ptr + this->buf.len, chunk.ptr, chunk.len);
+ this->buf.len += chunk.len;
+ break;
+ }
default:
+ {
DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
this->buf.len -= sizeof(u_int8_t);
break;
+ }
}
+ va_end(args);
}
/**
{
private_ha_sync_message_t *this = ha_sync_message_create_generic();
- this->allocated = 64;
+ this->allocated = ALLOCATION_BLOCK;
this->buf.ptr = malloc(this->allocated);
this->buf.len = 2;
this->buf.ptr[0] = HA_SYNC_MESSAGE_VERSION;
#define HA_SYNC_MESSAGE_H_
#include <library.h>
+#include <utils/host.h>
+#include <utils/identification.h>
+#include <sa/ike_sa_id.h>
/**
* Protocol version of this implementation
* Type of a sync message
*/
enum ha_sync_message_type_t {
- HA_SYNC_CHILD_SA = 0,
- HA_SYNC_IKE_SA,
- HA_SYNC_IKE_MID,
+ /** add a completely new IKE_SA */
+ HA_SYNC_IKE_ADD = 1,
+ /** update an existing IKE_SA (message IDs, address update, ...) */
+ HA_SYNC_IKE_UPDATE,
+ /** delete an existing IKE_SA */
+ HA_SYNC_IKE_DELETE,
+ /** rekeying an existing IKE_SA, transferring CHILD_SAs to a new one */
+ HA_SYNC_IKE_REKEY,
+ /** add a new CHILD_SA */
+ HA_SYNC_CHILD_ADD,
+ /** delete an existing CHILD_SA */
+ HA_SYNC_CHILD_DELETE,
};
/**
* Type of attributes contained in a message
*/
enum ha_sync_message_attribute_t {
- HA_SYNC_CONFIG_STR = 0,
- HA_SYNC_IPV4_L_CHNK,
- HA_SYNC_IPV4_R_CHNK,
- HA_SYNC_PORT_L_U16,
- HA_SYNC_PORT_R_U16,
- HA_SYNC_SPI_L_U32,
- HA_SYNC_SPI_R_U32,
- HA_SYNC_CPI_L_U16,
- HA_SYNC_CPI_R_U16,
- HA_SYNC_ENCAP_U8,
- HA_SYNC_MODE_U8,
- HA_SYNC_IPCOMP_U8,
- HA_SYNC_NONCE_I_CHNK,
- HA_SYNC_NONCE_R_CHNK,
- HA_SYNC_SECRET_CHNK,
- HA_SYNC_ALG_INTEG_U16,
- HA_SYNC_ALG_ENC_U16,
+ /** ike_sa_id_t*, to identify IKE_SA */
+ HA_SYNC_IKE_ID = 1,
+ /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */
+ HA_SYNC_IKE_REKEY_ID,
+ /** identification_t*, local identity */
+ HA_SYNC_LOCAL_ID,
+ /** identification_t*, remote identity */
+ HA_SYNC_REMOTE_ID,
+ /** identification_t*, EAP identity */
+ HA_SYNC_EAP_ID,
+ /** host_t*, local address */
+ HA_SYNC_LOCAL_ADDR,
+ /** host_t*, remote address */
+ HA_SYNC_REMOTE_ADDR,
+ /** char*, name of configuration */
+ HA_SYNC_CONFIG_NAME,
+ /** u_int32_t, bitset of ike_condition_t */
+ HA_SYNC_CONDITIONS,
+ /** u_int32_t, bitset of ike_extension_t */
+ HA_SYNC_EXTENSIONS,
+ /** host_t*, local virtual IP */
+ HA_SYNC_LOCAL_VIP,
+ /** host_t*, remote virtual IP */
+ HA_SYNC_REMOTE_VIP,
+ /** host_t*, additional MOBIKE peer address */
+ HA_SYNC_ADDITIONAL_ADDR,
+ /** chunk_t, initiators nonce */
+ HA_SYNC_NONCE_I,
+ /** chunk_t, responders nonce */
+ HA_SYNC_NONCE_R,
+ /** chunk_t, diffie hellman shared secret */
+ HA_SYNC_SECRET,
};
/**
u_int32_t u32;
u_int16_t u16;
chunk_t chnk;
+ host_t *host;
+ identification_t *id;
+ ike_sa_id_t *ike_sa_id;
char *str;
};