pushing basic CHILD_SA sync data to backup node
This commit is contained in:
committed by
Martin Willi
parent
765935c8f6
commit
7999be5b0e
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user