pushing basic CHILD_SA sync data to backup node

This commit is contained in:
Martin Willi
2010-04-07 13:55:11 +02:00
committed by Martin Willi
parent 765935c8f6
commit 7999be5b0e
4 changed files with 256 additions and 1 deletions
@@ -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;
@@ -270,6 +270,28 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this,
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
*/
@@ -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",
@@ -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;
+20 -1
View 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;
};
/**