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;
}
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;
enumerator->destroy(enumerator);
}
+/**
+ * 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
*/
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",
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
*/
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;
/** 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;
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);
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))
{
/** 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))
{
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;
#include <utils/host.h>
#include <utils/identification.h>
#include <sa/ike_sa_id.h>
+#include <config/traffic_selector.h>
/**
* Protocol version of this implementation
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;
};
/**