diff options
author | Martin Willi <martin@revosec.ch> | 2010-07-26 13:49:35 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-07-26 13:53:54 +0200 |
commit | 08e266a119e77bc7df84b5a7066e216ec1f9e984 (patch) | |
tree | cb15ad6547381a6d15ce2eaa9810f44289e95230 | |
parent | 3e6736f67e9c3535543bc3d2381ec21cf3902023 (diff) | |
download | strongswan-08e266a119e77bc7df84b5a7066e216ec1f9e984.tar.bz2 strongswan-08e266a119e77bc7df84b5a7066e216ec1f9e984.tar.xz |
Log CHILD_SA segment responsibility
-rw-r--r-- | src/libcharon/plugins/ha/ha_child.c | 35 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_child.h | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.c | 21 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.h | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_kernel.c | 17 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_kernel.h | 9 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_plugin.c | 5 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_segments.c | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_segments.h | 8 |
9 files changed, 95 insertions, 18 deletions
diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index 640aa1640..1a9425423 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -38,9 +38,14 @@ struct private_ha_child_t { 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, @@ -51,9 +56,10 @@ 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 */ @@ -93,21 +99,31 @@ METHOD(listener_t, child_keys, bool, 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); @@ -155,7 +171,7 @@ METHOD(ha_child_t, destroy, void, * 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; @@ -169,7 +185,8 @@ ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel, }, .socket = socket, .tunnel = tunnel, - .cache = cache, + .segments = segments, + .kernel = kernel, ); return &this->public; diff --git a/src/libcharon/plugins/ha/ha_child.h b/src/libcharon/plugins/ha/ha_child.h index 9a28e5123..56cd769ba 100644 --- a/src/libcharon/plugins/ha/ha_child.h +++ b/src/libcharon/plugins/ha/ha_child.h @@ -26,7 +26,7 @@ typedef struct ha_child_t ha_child_t; #include "ha_socket.h" #include "ha_tunnel.h" #include "ha_segments.h" -#include "ha_cache.h" +#include "ha_kernel.h" #include <daemon.h> @@ -51,10 +51,11 @@ struct ha_child_t { * * @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_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index af45429c5..2385be328 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -46,6 +46,11 @@ struct private_ha_dispatcher_t { ha_cache_t *cache; /** + * Kernel helper + */ + ha_kernel_t *kernel; + + /** * Dispatcher job */ callback_job_t *job; @@ -428,6 +433,7 @@ static void process_child_add(private_ha_dispatcher_t *this, 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; @@ -594,8 +600,16 @@ static void process_child_add(private_ha_dispatcher_t *this, 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)); @@ -808,7 +822,7 @@ METHOD(ha_dispatcher_t, destroy, void, * 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; @@ -820,6 +834,7 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, .socket = socket, .segments = segments, .cache = cache, + .kernel = kernel, ); this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.h b/src/libcharon/plugins/ha/ha_dispatcher.h index 3190458fc..3a5ec7985 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.h +++ b/src/libcharon/plugins/ha/ha_dispatcher.h @@ -24,6 +24,7 @@ #include "ha_socket.h" #include "ha_segments.h" #include "ha_cache.h" +#include "ha_kernel.h" typedef struct ha_dispatcher_t ha_dispatcher_t; @@ -44,9 +45,10 @@ struct 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_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c index 7428de497..69ba29521 100644 --- a/src/libcharon/plugins/ha/ha_kernel.c +++ b/src/libcharon/plugins/ha/ha_kernel.c @@ -67,6 +67,22 @@ METHOD(ha_kernel_t, get_segment, u_int, 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 */ @@ -206,6 +222,7 @@ ha_kernel_t *ha_kernel_create(u_int count) INIT(this, .public = { .get_segment = _get_segment, + .get_segment_spi = _get_segment_spi, .activate = _activate, .deactivate = _deactivate, .destroy = _destroy, diff --git a/src/libcharon/plugins/ha/ha_kernel.h b/src/libcharon/plugins/ha/ha_kernel.h index b9341f4cc..5e8c054ab 100644 --- a/src/libcharon/plugins/ha/ha_kernel.h +++ b/src/libcharon/plugins/ha/ha_kernel.h @@ -39,6 +39,15 @@ struct ha_kernel_t { 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. * * @param segment segment to activate diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index cfce45e47..b20868b71 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -156,9 +156,10 @@ plugin_t *ha_plugin_create() 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); diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index bdd850fc7..c8748ab3c 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -343,6 +343,12 @@ static job_requeue_t send_status(private_ha_segments_t *this) 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) { @@ -370,6 +376,7 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel, .activate = _activate, .deactivate = _deactivate, .handle_status = _handle_status, + .is_active = _is_active, .destroy = _destroy, }, .socket = socket, diff --git a/src/libcharon/plugins/ha/ha_segments.h b/src/libcharon/plugins/ha/ha_segments.h index 1699f7b0d..eb9e5c1d5 100644 --- a/src/libcharon/plugins/ha/ha_segments.h +++ b/src/libcharon/plugins/ha/ha_segments.h @@ -75,6 +75,14 @@ struct ha_segments_t { 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. */ void (*destroy)(ha_segments_t *this); |