ha_tunnel_t *tunnel;
/**
- * message cache
+ * Segment handling
*/
- ha_cache_t *cache;
+ ha_segments_t *segments;
+
+ /**
+ * Kernel helper
+ */
+ ha_kernel_t *kernel;
};
METHOD(listener_t, child_keys, bool,
chunk_t secret;
proposal_t *proposal;
u_int16_t alg, len;
- linked_list_t *list;
+ linked_list_t *local_ts, *remote_ts;
enumerator_t *enumerator;
traffic_selector_t *ts;
+ u_int seg_i, seg_o;
if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
{ /* do not sync SA between nodes */
chunk_clear(&secret);
}
- list = child_sa->get_traffic_selectors(child_sa, TRUE);
- enumerator = list->create_enumerator(list);
+ local_ts = child_sa->get_traffic_selectors(child_sa, TRUE);
+ enumerator = local_ts->create_enumerator(local_ts);
while (enumerator->enumerate(enumerator, &ts))
{
m->add_attribute(m, HA_LOCAL_TS, ts);
}
enumerator->destroy(enumerator);
- list = child_sa->get_traffic_selectors(child_sa, FALSE);
- enumerator = list->create_enumerator(list);
+ remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE);
+ enumerator = remote_ts->create_enumerator(remote_ts);
while (enumerator->enumerate(enumerator, &ts))
{
m->add_attribute(m, HA_REMOTE_TS, ts);
}
enumerator->destroy(enumerator);
+ seg_i = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_my_host(ike_sa), child_sa->get_spi(child_sa, TRUE));
+ seg_o = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_other_host(ike_sa), child_sa->get_spi(child_sa, FALSE));
+ DBG1(DBG_CFG, "handling HA CHILD_SA %s{%d} %#R=== %#R "
+ "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa), local_ts, remote_ts,
+ seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+ seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
+
this->socket->push(this->socket, m);
m->destroy(m);
* See header
*/
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
- ha_cache_t *cache)
+ ha_segments_t *segments, ha_kernel_t *kernel)
{
private_ha_child_t *this;
},
.socket = socket,
.tunnel = tunnel,
- .cache = cache,
+ .segments = segments,
+ .kernel = kernel,
);
return &this->public;
#include "ha_socket.h"
#include "ha_tunnel.h"
#include "ha_segments.h"
-#include "ha_cache.h"
+#include "ha_kernel.h"
#include <daemon.h>
*
* @param socket socket to use for sending synchronization messages
* @param tunnel tunnel securing sync messages, if any
- * @param cache message resync cache
+ * @param segments segment handling
+ * @param kernel kernel helper
* @return CHILD listener
*/
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
- ha_cache_t *cache);
+ ha_segments_t *segments, ha_kernel_t *kernel);
#endif /** HA_CHILD_ @}*/
*/
ha_cache_t *cache;
+ /**
+ * Kernel helper
+ */
+ ha_kernel_t *kernel;
+
/**
* Dispatcher job
*/
u_int16_t inbound_cpi = 0, outbound_cpi = 0;
u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ u_int seg_i, seg_o;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
chunk_t encr_i, integ_i, encr_r, integ_r;
linked_list_t *local_ts, *remote_ts;
return;
}
- DBG1(DBG_CFG, "installed HA CHILD_SA '%s' %#R=== %#R",
- child_sa->get_name(child_sa), local_ts, remote_ts);
+ seg_i = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_my_host(ike_sa), inbound_spi);
+ seg_o = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_other_host(ike_sa), outbound_spi);
+
+ DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R=== %#R "
+ "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa), local_ts, remote_ts,
+ seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+ seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
child_sa->add_policies(child_sa, local_ts, remote_ts);
local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
* See header
*/
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
- ha_segments_t *segments, ha_cache_t *cache)
+ ha_segments_t *segments, ha_cache_t *cache, ha_kernel_t *kernel)
{
private_ha_dispatcher_t *this;
.socket = socket,
.segments = segments,
.cache = cache,
+ .kernel = kernel,
);
this->job = callback_job_create((callback_job_cb_t)dispatch,
this, NULL, NULL);
#include "ha_socket.h"
#include "ha_segments.h"
#include "ha_cache.h"
+#include "ha_kernel.h"
typedef struct ha_dispatcher_t ha_dispatcher_t;
* @param socket socket to pull messages from
* @param segments segments to control based on received messages
* @param cache message cache to use for resynchronization
+ * @param kernel kernel helper
* @return dispatcher object
*/
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
- ha_segments_t *segments, ha_cache_t *cache);
+ ha_segments_t *segments, ha_cache_t *cache, ha_kernel_t *kernel);
#endif /** HA_DISPATCHER_ @}*/
return 0;
}
+METHOD(ha_kernel_t, get_segment_spi, u_int,
+ private_ha_kernel_t *this, host_t *host, u_int32_t spi)
+{
+ if (host->get_family(host) == AF_INET)
+ {
+ unsigned long hash;
+ u_int32_t addr;
+
+ addr = *(u_int32_t*)host->get_address(host).ptr;
+ hash = jhash_2words(ntohl(addr), ntohl(spi), this->initval);
+
+ return (((u_int64_t)hash * this->count) >> 32) + 1;
+ }
+ return 0;
+}
+
/**
* Activate/Deactivate a segment for a given clusterip file
*/
INIT(this,
.public = {
.get_segment = _get_segment,
+ .get_segment_spi = _get_segment_spi,
.activate = _activate,
.deactivate = _deactivate,
.destroy = _destroy,
*/
u_int (*get_segment)(ha_kernel_t *this, host_t *host);
+ /**
+ * Get the segment a host/SPI is in, as used for CHILD_SA segmentation.
+ *
+ * @param host host to get segment for
+ * @param spi SPI to include in hash
+ * @return segment number
+ */
+ u_int (*get_segment_spi)(ha_kernel_t *this, host_t *host, u_int32_t spi);
+
/**
* Activate a segment at kernel level for all cluster addresses.
*
this->ctl = ha_ctl_create(this->segments, this->cache);
}
this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
- this->cache);
+ this->cache, this->kernel);
this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
- this->child = ha_child_create(this->socket, this->tunnel, this->cache);
+ this->child = ha_child_create(this->socket, this->tunnel, this->segments,
+ this->kernel);
charon->bus->add_listener(charon->bus, &this->segments->listener);
charon->bus->add_listener(charon->bus, &this->ike->listener);
charon->bus->add_listener(charon->bus, &this->child->listener);
return JOB_REQUEUE_NONE;
}
+METHOD(ha_segments_t, is_active, bool,
+ private_ha_segments_t *this, u_int segment)
+{
+ return (this->active & SEGMENTS_BIT(segment)) != 0;
+}
+
METHOD(ha_segments_t, destroy, void,
private_ha_segments_t *this)
{
.activate = _activate,
.deactivate = _deactivate,
.handle_status = _handle_status,
+ .is_active = _is_active,
.destroy = _destroy,
},
.socket = socket,
*/
void (*handle_status)(ha_segments_t *this, segment_mask_t mask);
+ /**
+ * Check if a given segment is currently active.
+ *
+ * @param segment segment to check
+ * @return TRUE if segment active
+ */
+ bool (*is_active)(ha_segments_t *this, u_int segment);
+
/**
* Destroy a ha_segments_t.
*/