diff options
| author | Martin Willi <martin@strongswan.org> | 2008-11-28 15:45:17 +0000 |
|---|---|---|
| committer | Martin Willi <martin@revosec.ch> | 2010-04-07 13:55:12 +0200 |
| commit | 34d240a6e3c60560cb62e0a84e2cdc62bdf47ea2 (patch) | |
| tree | 3c9c455838cac9fc63f07dae3414f5ce3d10fa32 /src/charon/plugins | |
| parent | d4113a42e9ac5c1085bebc07a5aa8da20174d52d (diff) | |
| download | strongswan-34d240a6e3c60560cb62e0a84e2cdc62bdf47ea2.tar.bz2 strongswan-34d240a6e3c60560cb62e0a84e2cdc62bdf47ea2.tar.xz | |
manage synced SAs in IKE_SA Manager, tag them with IKE_PASSIVE state
Diffstat (limited to 'src/charon/plugins')
| -rw-r--r-- | src/charon/plugins/ha_sync/Makefile.am | 2 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_cache.h | 89 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_child.c | 18 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_child.h | 6 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ctl.c | 12 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ctl.h | 6 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_dispatcher.c | 153 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_dispatcher.h | 5 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ike.c | 83 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ike.h | 6 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_message.c | 10 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_message.h | 4 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_plugin.c | 18 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_segments.c (renamed from src/charon/plugins/ha_sync/ha_sync_cache.c) | 139 | ||||
| -rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_segments.h | 64 |
15 files changed, 272 insertions, 343 deletions
diff --git a/src/charon/plugins/ha_sync/Makefile.am b/src/charon/plugins/ha_sync/Makefile.am index e30376d1a..15f409699 100644 --- a/src/charon/plugins/ha_sync/Makefile.am +++ b/src/charon/plugins/ha_sync/Makefile.am @@ -9,7 +9,7 @@ libstrongswan_ha_sync_la_SOURCES = \ ha_sync_message.h ha_sync_message.c \ ha_sync_socket.h ha_sync_socket.c \ ha_sync_dispatcher.h ha_sync_dispatcher.c \ - ha_sync_cache.h ha_sync_cache.c \ + ha_sync_segments.h ha_sync_segments.c \ ha_sync_ctl.h ha_sync_ctl.c \ ha_sync_ike.h ha_sync_ike.c \ ha_sync_child.h ha_sync_child.c diff --git a/src/charon/plugins/ha_sync/ha_sync_cache.h b/src/charon/plugins/ha_sync/ha_sync_cache.h deleted file mode 100644 index cf9e0d72b..000000000 --- a/src/charon/plugins/ha_sync/ha_sync_cache.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * $Id$ - */ - -/** - * @defgroup ha_sync_cache ha_sync_cache - * @{ @ingroup ha_sync - */ - -#ifndef HA_SYNC_CACHE_H_ -#define HA_SYNC_CACHE_H_ - -#include <daemon.h> - -typedef struct ha_sync_cache_t ha_sync_cache_t; - -/** - * Locally cached HA state synced from other nodes. - */ -struct ha_sync_cache_t { - - /** - * Get a synced and cached IKE_SA entry. - * - * If no cached IKE_SA with such an id exists, it gets created. - * - * @param id IKE_SA identifier of cached SA. - * @return cached IKE_SA - */ - ike_sa_t* (*get_ike_sa)(ha_sync_cache_t *this, ike_sa_id_t *id); - - /** - * Check if an IKE_SA is in the cache. - * - * @param id IKE_SA identifier of cached SA. - * @return TRUE if IKE_SA found - */ - bool (*has_ike_sa)(ha_sync_cache_t *this, ike_sa_id_t *id); - - /** - * Delete a synced and cached IKE_SA entry. - * - * @param id IKE_SA identifier of cached SA to delete. - */ - void (*delete_ike_sa)(ha_sync_cache_t *this, ike_sa_id_t *id); - - /** - * Activate a set of IKE_SAs identified by a segment. - * - * Activating means do a takeover of SAs as the responsible node has failed. - * This involves moving all SAs to the daemons IKE_SA manager and handle - * them actively now. - * - * @param segment numerical segment to takeover - */ - void (*activate)(ha_sync_cache_t *this, u_int segment); - - /** - * Deactivate a set of IKE_SAs identified by a segment. - * - * @param segment numerical segment to takeover - */ - void (*deactivate)(ha_sync_cache_t *this, u_int segment); - - /** - * Destroy a ha_sync_cache_t. - */ - void (*destroy)(ha_sync_cache_t *this); -}; - -/** - * Create a ha_sync_cache instance. - */ -ha_sync_cache_t *ha_sync_cache_create(); - -#endif /* HA_SYNC_CACHE_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_child.c b/src/charon/plugins/ha_sync/ha_sync_child.c index b3ace7269..1c1c6fcfa 100644 --- a/src/charon/plugins/ha_sync/ha_sync_child.c +++ b/src/charon/plugins/ha_sync/ha_sync_child.c @@ -33,11 +33,6 @@ struct private_ha_sync_child_t { * socket we use for syncing */ ha_sync_socket_t *socket; - - /** - * synced and cached IKE_SA state - */ - ha_sync_cache_t *cache; }; /** @@ -55,11 +50,6 @@ static bool child_keys(private_ha_sync_child_t *this, ike_sa_t *ike_sa, enumerator_t *enumerator; traffic_selector_t *ts; - if (this->cache->has_ike_sa(this->cache, ike_sa->get_id(ike_sa))) - { /* IKE_SA is cached, do not sync */ - return TRUE; - } - m = ha_sync_message_create(HA_SYNC_CHILD_ADD); m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); @@ -119,8 +109,8 @@ static bool child_keys(private_ha_sync_child_t *this, ike_sa_t *ike_sa, 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 (this->cache->has_ike_sa(this->cache, ike_sa->get_id(ike_sa))) - { /* IKE_SA is cached, do not sync */ + if (ike_sa->get_state(ike_sa) == IKE_PASSIVE) + { /* only sync active IKE_SAs */ return TRUE; } @@ -150,8 +140,7 @@ static void destroy(private_ha_sync_child_t *this) /** * See header */ -ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache) +ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket) { private_ha_sync_child_t *this = malloc_thing(private_ha_sync_child_t); @@ -161,7 +150,6 @@ ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket, this->public.destroy = (void(*)(ha_sync_child_t*))destroy; this->socket = socket; - this->cache = cache; return &this->public; } diff --git a/src/charon/plugins/ha_sync/ha_sync_child.h b/src/charon/plugins/ha_sync/ha_sync_child.h index fe7e5ec65..13faa914e 100644 --- a/src/charon/plugins/ha_sync/ha_sync_child.h +++ b/src/charon/plugins/ha_sync/ha_sync_child.h @@ -24,7 +24,7 @@ #define HA_SYNC_CHILD_H_ #include "ha_sync_socket.h" -#include "ha_sync_cache.h" +#include "ha_sync_segments.h" #include <daemon.h> @@ -50,10 +50,8 @@ struct ha_sync_child_t { * Create a ha_sync_child instance. * * @param socket socket to use for sending synchronization messages - * @param cache synced and cached SAs * @return CHILD listener */ -ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache); +ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket); #endif /* HA_SYNC_CHILD_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_ctl.c b/src/charon/plugins/ha_sync/ha_sync_ctl.c index cf747f20f..30c9261e6 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ctl.c +++ b/src/charon/plugins/ha_sync/ha_sync_ctl.c @@ -42,9 +42,9 @@ struct private_ha_sync_ctl_t { ha_sync_ctl_t public; /** - * Cache to control + * Segments to control */ - ha_sync_cache_t *cache; + ha_sync_segments_t *segments; /** * FIFO reader thread @@ -80,10 +80,10 @@ static job_requeue_t dispatch_fifo(private_ha_sync_ctl_t *this) switch (buf[0]) { case '+': - this->cache->activate(this->cache, segment); + this->segments->activate(this->segments, segment); break; case '-': - this->cache->deactivate(this->cache, segment); + this->segments->deactivate(this->segments, segment); break; default: break; @@ -107,7 +107,7 @@ static void destroy(private_ha_sync_ctl_t *this) /** * See header */ -ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_cache_t *cache) +ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_segments_t *segments) { private_ha_sync_ctl_t *this = malloc_thing(private_ha_sync_ctl_t); @@ -122,7 +122,7 @@ ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_cache_t *cache) } } - this->cache = cache; + this->segments = segments; this->job = callback_job_create((callback_job_cb_t)dispatch_fifo, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/charon/plugins/ha_sync/ha_sync_ctl.h b/src/charon/plugins/ha_sync/ha_sync_ctl.h index cd2c7a28f..5aa3aacff 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ctl.h +++ b/src/charon/plugins/ha_sync/ha_sync_ctl.h @@ -23,7 +23,7 @@ #ifndef HA_SYNC_CTL_H_ #define HA_SYNC_CTL_H_ -#include "ha_sync_cache.h" +#include "ha_sync_segments.h" typedef struct ha_sync_ctl_t ha_sync_ctl_t; @@ -41,9 +41,9 @@ struct ha_sync_ctl_t { /** * Create a ha_sync_ctl instance. * - * @param cache cache to control in this socket + * @param segments segments to control * @return HA sync control interface */ -ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_cache_t *cache); +ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_segments_t *segments); #endif /* HA_SYNC_CTL_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c index 787321628..78c62c0f1 100644 --- a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c @@ -38,11 +38,6 @@ struct private_ha_sync_dispatcher_t { ha_sync_socket_t *socket; /** - * Synced SA state cache - */ - ha_sync_cache_t *cache; - - /** * Dispatcher job */ callback_job_t *job; @@ -77,14 +72,11 @@ static void process_ike_add(private_ha_sync_dispatcher_t *this, switch (attribute) { case HA_SYNC_IKE_ID: - ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); - DBG2(DBG_IKE, "got HA_SYNC_IKE_ADD: %llx:%llx - %p", - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id), - ike_sa); + ike_sa = ike_sa_create(value.ike_sa_id); break; case HA_SYNC_IKE_REKEY_ID: - old_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); + old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); break; case HA_SYNC_NONCE_I: nonce_i = value.chunk; @@ -142,19 +134,30 @@ static void process_ike_add(private_ha_sync_dispatcher_t *this, proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); } charon->bus->set_sa(charon->bus, ike_sa); - if (!keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r, + if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd)) { + if (old_sa) + { + ike_sa->inherit(ike_sa, old_sa); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, old_sa); + old_sa = NULL; + } + ike_sa->set_state(ike_sa, IKE_CONNECTING); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { DBG1(DBG_IKE, "HA sync keymat derivation failed"); + ike_sa->destroy(ike_sa); } charon->bus->set_sa(charon->bus, NULL); proposal->destroy(proposal); - - if (old_sa) - { - ike_sa->inherit(ike_sa, old_sa); - this->cache->delete_ike_sa(this->cache, old_sa->get_id(old_sa)); - } + } + if (old_sa) + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa); } } @@ -196,17 +199,14 @@ static void process_ike_update(private_ha_sync_dispatcher_t *this, { if (attribute != HA_SYNC_IKE_ID && ike_sa == NULL) { - DBG1(DBG_IKE, "HA_SYNC_IKE_ID must be first attribute"); + /* must be first attribute */ break; } switch (attribute) { case HA_SYNC_IKE_ID: - ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); - DBG2(DBG_IKE, "got HA_SYNC_IKE_UPDATE: %llx:%llx - %p", - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id), - ike_sa); + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); break; case HA_SYNC_LOCAL_ID: ike_sa->set_my_id(ike_sa, value.id->clone(value.id)); @@ -235,6 +235,15 @@ static void process_ike_update(private_ha_sync_dispatcher_t *this, case HA_SYNC_CONFIG_NAME: peer_cfg = charon->backends->get_peer_cfg_by_name( charon->backends, value.str); + if (peer_cfg) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + peer_cfg->destroy(peer_cfg); + } + else + { + DBG1(DBG_IKE, "HA sync is missing nodes peer configuration"); + } break; case HA_SYNC_CONDITIONS: set_condition(ike_sa, value.u32, EXT_NATT); @@ -250,26 +259,26 @@ static void process_ike_update(private_ha_sync_dispatcher_t *this, set_extension(ike_sa, value.u32, COND_CERTREQ_SEEN); set_extension(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); break; + case HA_SYNC_INITIATE_MID: + ike_sa->set_message_id(ike_sa, TRUE, value.u32); + break; + case HA_SYNC_RESPOND_MID: + ike_sa->set_message_id(ike_sa, FALSE, value.u32); + break; default: break; } } enumerator->destroy(enumerator); - if (peer_cfg) - { - ike_sa->set_peer_cfg(ike_sa, peer_cfg); - peer_cfg->destroy(peer_cfg); - - charon->bus->set_sa(charon->bus, ike_sa); - /* we use the CONNECTING state to indicate sync is complete. */ - /* TODO: add an additional HOT_COPY state? */ - ike_sa->set_state(ike_sa, IKE_CONNECTING); - charon->bus->set_sa(charon->bus, NULL); - } - else + if (ike_sa) { - DBG1(DBG_IKE, "HA sync is missing nodes peer configuration"); + if (ike_sa->get_state(ike_sa) == IKE_CONNECTING && + ike_sa->get_peer_cfg(ike_sa)) + { + ike_sa->set_state(ike_sa, IKE_PASSIVE); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } @@ -282,6 +291,7 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this, ha_sync_message_attribute_t attribute; ha_sync_message_value_t value; enumerator_t *enumerator; + ike_sa_t *ike_sa; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -289,10 +299,13 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this, switch (attribute) { case HA_SYNC_IKE_ID: - DBG2(DBG_IKE, "got HA_SYNC_IKE_DELETE: %llx:%llx", - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id)); - this->cache->delete_ike_sa(this->cache, value.ike_sa_id); + ike_sa = charon->ike_sa_manager->checkout( + charon->ike_sa_manager, value.ike_sa_id); + if (ike_sa) + { + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } break; default: break; @@ -301,17 +314,16 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this, enumerator->destroy(enumerator); } - /** - * get the child_cfg with the same name as the peer cfg + * Lookup a child cfg from the peer cfg by name */ -static child_cfg_t* find_child_cfg(char *name) +static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name) { peer_cfg_t *peer_cfg; child_cfg_t *current, *found = NULL; enumerator_t *enumerator; - peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name); + peer_cfg = ike_sa->get_peer_cfg(ike_sa); if (peer_cfg) { enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); @@ -320,12 +332,10 @@ static child_cfg_t* find_child_cfg(char *name) if (streq(current->get_name(current), name)) { found = current; - found->get_ref(found); break; } } enumerator->destroy(enumerator); - peer_cfg->destroy(peer_cfg); } return found; } @@ -340,6 +350,7 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, ha_sync_message_value_t value; enumerator_t *enumerator; ike_sa_t *ike_sa = NULL; + char *config_name; child_cfg_t *config = NULL; child_sa_t *child_sa; proposal_t *proposal; @@ -362,15 +373,12 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, switch (attribute) { case HA_SYNC_IKE_ID: - ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); initiator = value.ike_sa_id->is_initiator(value.ike_sa_id); - DBG2(DBG_CHD, "got HA_SYNC_CHILD_ADD: %llx:%llx - %p", - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id), - ike_sa); break; case HA_SYNC_CONFIG_NAME: - config = find_child_cfg(value.str); + config_name = value.str; break; case HA_SYNC_INBOUND_SPI: inbound_spi = value.u32; @@ -414,22 +422,22 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, } enumerator->destroy(enumerator); - if (!config) + if (!ike_sa) { - DBG1(DBG_CHD, "HA sync is missing nodes child configuration"); + DBG1(DBG_CHD, "IKE_SA for HA sync CHILD_SA not found"); return; } - if (!ike_sa) + config = find_child_cfg(ike_sa, config_name); + if (!config) { - config->destroy(config); - DBG1(DBG_CHD, "IKE_SA for HA sync CHILD_SA not found"); + DBG1(DBG_CHD, "HA sync is missing nodes child configuration"); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); return; } - charon->bus->set_sa(charon->bus, ike_sa); + child_sa = child_sa_create(ike_sa->get_my_host(ike_sa), ike_sa->get_other_host(ike_sa), config, 0, ike_sa->has_condition(ike_sa, COND_NAT_ANY)); - config->destroy(config); child_sa->set_mode(child_sa, mode); child_sa->set_protocol(child_sa, PROTO_ESP); child_sa->set_ipcomp(child_sa, ipcomp); @@ -451,7 +459,7 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, DBG1(DBG_CHD, "HA sync CHILD_SA key derivation failed"); child_sa->destroy(child_sa); proposal->destroy(proposal); - charon->bus->set_sa(charon->bus, NULL); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); return; } child_sa->set_proposal(child_sa, proposal); @@ -487,7 +495,7 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, { DBG1(DBG_CHD, "HA sync CHILD_SA installation failed"); child_sa->destroy(child_sa); - charon->bus->set_sa(charon->bus, NULL); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); return; } @@ -516,7 +524,7 @@ static void process_child_add(private_ha_sync_dispatcher_t *this, child_sa->set_state(child_sa, CHILD_INSTALLED); ike_sa->add_child_sa(ike_sa, child_sa); - charon->bus->set_sa(charon->bus, NULL); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } /** @@ -536,15 +544,8 @@ static void process_child_delete(private_ha_sync_dispatcher_t *this, switch (attribute) { case HA_SYNC_IKE_ID: - if (this->cache->has_ike_sa(this->cache, value.ike_sa_id)) - { - ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); - DBG2(DBG_CHD, "got HA_SYNC_CHILD_DELETE: %llx:%llx - %p", - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id), - ike_sa); - continue; - } + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); break; case HA_SYNC_INBOUND_SPI: if (!ike_sa || ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, @@ -559,6 +560,10 @@ static void process_child_delete(private_ha_sync_dispatcher_t *this, } break; } + if (ike_sa) + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } enumerator->destroy(enumerator); } @@ -609,15 +614,13 @@ static void destroy(private_ha_sync_dispatcher_t *this) /** * See header */ -ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache) +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket) { private_ha_sync_dispatcher_t *this = malloc_thing(private_ha_sync_dispatcher_t); this->public.destroy = (void(*)(ha_sync_dispatcher_t*))destroy; this->socket = socket; - this->cache = cache; this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.h b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h index eda4c4ddb..eb2817e91 100644 --- a/src/charon/plugins/ha_sync/ha_sync_dispatcher.h +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h @@ -24,7 +24,6 @@ #define HA_SYNC_DISPATCHER_H_ #include "ha_sync_socket.h" -#include "ha_sync_cache.h" typedef struct ha_sync_dispatcher_t ha_sync_dispatcher_t; @@ -43,10 +42,8 @@ struct ha_sync_dispatcher_t { * Create a ha_sync_dispatcher instance pulling from socket. * * @param socket socket to pull messages from - * @param cache cache to push synced SAs to * @return dispatcher object */ -ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache); +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket); #endif /* HA_SYNC_DISPATCHER_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.c b/src/charon/plugins/ha_sync/ha_sync_ike.c index b528a33dc..fb518e688 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.c +++ b/src/charon/plugins/ha_sync/ha_sync_ike.c @@ -33,11 +33,6 @@ struct private_ha_sync_ike_t { * socket we use for syncing */ ha_sync_socket_t *socket; - - /** - * Synced and cached SAs - */ - ha_sync_cache_t *cache; }; /** @@ -76,11 +71,6 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, proposal_t *proposal; u_int16_t alg, len; - if (this->cache->has_ike_sa(this->cache, ike_sa->get_id(ike_sa))) - { /* IKE_SA is cached, do not sync */ - return TRUE; - } - if (dh->get_shared_secret(dh, &secret) != SUCCESS) { return TRUE; @@ -136,8 +126,8 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, { ha_sync_message_t *m; - if (this->cache->has_ike_sa(this->cache, ike_sa->get_id(ike_sa))) - { /* IKE_SA is cached, do not sync */ + if (ike_sa->get_state(ike_sa) == IKE_PASSIVE) + { /* only sync active IKE_SAs */ return TRUE; } @@ -148,8 +138,9 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, iterator_t *iterator; peer_cfg_t *peer_cfg; u_int32_t extension, condition; - host_t *local_vip, *remote_vip, *addr; + host_t *addr; identification_t *eap_id; + ike_sa_id_t *id; peer_cfg = ike_sa->get_peer_cfg(ike_sa); @@ -165,12 +156,11 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, | copy_extension(ike_sa, EXT_MOBIKE) | copy_extension(ike_sa, EXT_HASH_AND_URL); - local_vip = ike_sa->get_virtual_ip(ike_sa, TRUE); - remote_vip = ike_sa->get_virtual_ip(ike_sa, FALSE); eap_id = ike_sa->get_eap_identity(ike_sa); + id = ike_sa->get_id(ike_sa); m = ha_sync_message_create(HA_SYNC_IKE_UPDATE); - m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_SYNC_IKE_ID, id); m->add_attribute(m, HA_SYNC_LOCAL_ID, ike_sa->get_my_id(ike_sa)); m->add_attribute(m, HA_SYNC_REMOTE_ID, ike_sa->get_other_id(ike_sa)); m->add_attribute(m, HA_SYNC_LOCAL_ADDR, ike_sa->get_my_host(ike_sa)); @@ -178,14 +168,6 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, m->add_attribute(m, HA_SYNC_CONDITIONS, condition); m->add_attribute(m, HA_SYNC_EXTENSIONS, extension); m->add_attribute(m, HA_SYNC_CONFIG_NAME, peer_cfg->get_name(peer_cfg)); - if (local_vip) - { - m->add_attribute(m, HA_SYNC_LOCAL_VIP, local_vip); - } - if (remote_vip) - { - m->add_attribute(m, HA_SYNC_REMOTE_VIP, remote_vip); - } if (eap_id) { m->add_attribute(m, HA_SYNC_EAP_ID, eap_id); @@ -213,6 +195,54 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, } /** + * Implementation of listener_t.message + */ +static bool message_hook(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, + message_t *message, bool incoming) +{ + if (message->get_exchange_type(message) != IKE_SA_INIT && + message->get_request(message)) + { /* we sync on requests, but skip it on IKE_SA_INIT */ + ha_sync_message_t *m; + u_int32_t mid; + + m = ha_sync_message_create(HA_SYNC_IKE_UPDATE); + m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + mid = message->get_message_id(message) + 1; + if (incoming) + { + m->add_attribute(m, HA_SYNC_RESPOND_MID, mid); + } + else + { + m->add_attribute(m, HA_SYNC_INITIATE_MID, mid); + } + this->socket->push(this->socket, m); + m->destroy(m); + } + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + message->get_exchange_type(message) == IKE_AUTH && + !message->get_request(message)) + { /* After IKE_SA has been established, sync peers virtual IP. + * We cannot sync it in the state_change hook, it is installed later. + * TODO: where to sync local VIP? */ + ha_sync_message_t *m; + host_t *vip; + + vip = ike_sa->get_virtual_ip(ike_sa, FALSE); + if (vip) + { + m = ha_sync_message_create(HA_SYNC_IKE_UPDATE); + m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_SYNC_REMOTE_VIP, vip); + this->socket->push(this->socket, m); + m->destroy(m); + } + } + return TRUE; +} + +/** * Implementation of ha_sync_ike_t.destroy. */ static void destroy(private_ha_sync_ike_t *this) @@ -223,18 +253,17 @@ static void destroy(private_ha_sync_ike_t *this) /** * See header */ -ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache) +ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket) { private_ha_sync_ike_t *this = malloc_thing(private_ha_sync_ike_t); memset(&this->public.listener, 0, sizeof(listener_t)); this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys; this->public.listener.ike_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, ike_sa_state_t state))ike_state_change; + this->public.listener.message = (bool(*)(listener_t*, ike_sa_t *, message_t *,bool))message_hook; this->public.destroy = (void(*)(ha_sync_ike_t*))destroy; this->socket = socket; - this->cache = cache; return &this->public; } diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.h b/src/charon/plugins/ha_sync/ha_sync_ike.h index b47534ae9..0ffbbde8f 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.h +++ b/src/charon/plugins/ha_sync/ha_sync_ike.h @@ -24,7 +24,7 @@ #define HA_SYNC_IKE_H_ #include "ha_sync_socket.h" -#include "ha_sync_cache.h" +#include "ha_sync_segments.h" #include <daemon.h> @@ -50,10 +50,8 @@ struct ha_sync_ike_t { * Create a ha_sync_ike instance. * * @param socket socket to use for sending synchronization messages - * @param cache synced and cached SAs * @return IKE listener */ -ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket, - ha_sync_cache_t *cache); +ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket); #endif /* HA_SYNC_IKE_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_message.c b/src/charon/plugins/ha_sync/ha_sync_message.c index 3cf0a1011..314c20d3f 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.c +++ b/src/charon/plugins/ha_sync/ha_sync_message.c @@ -211,7 +211,7 @@ static void add_attribute(private_ha_sync_message_t *this, { u_int8_t val; - val = (u_int8_t)va_arg(args, u_int32_t); + val = va_arg(args, u_int); check_buf(this, sizeof(val)); this->buf.ptr[this->buf.len] = val; this->buf.len += sizeof(val); @@ -228,7 +228,7 @@ static void add_attribute(private_ha_sync_message_t *this, { u_int16_t val; - val = (u_int16_t)va_arg(args, u_int32_t); + val = va_arg(args, u_int); check_buf(this, sizeof(val)); *(u_int16_t*)(this->buf.ptr + this->buf.len) = htons(val); this->buf.len += sizeof(val); @@ -239,10 +239,12 @@ static void add_attribute(private_ha_sync_message_t *this, case HA_SYNC_EXTENSIONS: case HA_SYNC_INBOUND_SPI: case HA_SYNC_OUTBOUND_SPI: + case HA_SYNC_INITIATE_MID: + case HA_SYNC_RESPOND_MID: { u_int32_t val; - val = va_arg(args, u_int32_t); + val = va_arg(args, u_int); check_buf(this, sizeof(val)); *(u_int32_t*)(this->buf.ptr + this->buf.len) = htonl(val); this->buf.len += sizeof(val); @@ -453,6 +455,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this, case HA_SYNC_EXTENSIONS: case HA_SYNC_INBOUND_SPI: case HA_SYNC_OUTBOUND_SPI: + case HA_SYNC_INITIATE_MID: + case HA_SYNC_RESPOND_MID: { if (this->buf.len < sizeof(u_int32_t)) { diff --git a/src/charon/plugins/ha_sync/ha_sync_message.h b/src/charon/plugins/ha_sync/ha_sync_message.h index eec7b4f8e..8fe9610d6 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.h +++ b/src/charon/plugins/ha_sync/ha_sync_message.h @@ -119,6 +119,10 @@ enum ha_sync_message_attribute_t { HA_SYNC_LOCAL_TS, /** traffic_selector_t*, remote traffic selector */ HA_SYNC_REMOTE_TS, + /** u_int32_t, initiating message ID */ + HA_SYNC_INITIATE_MID, + /** u_int32_t, responding message ID */ + HA_SYNC_RESPOND_MID, }; /** diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.c b/src/charon/plugins/ha_sync/ha_sync_plugin.c index 2164a4b24..ce80eb13f 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -20,7 +20,7 @@ #include "ha_sync_child.h" #include "ha_sync_socket.h" #include "ha_sync_dispatcher.h" -#include "ha_sync_cache.h" +#include "ha_sync_segments.h" #include "ha_sync_ctl.h" #include <daemon.h> @@ -59,9 +59,9 @@ struct private_ha_sync_plugin_t { ha_sync_dispatcher_t *dispatcher; /** - * Local cache of a nodes synced SAs + * Active/Passive segment management */ - ha_sync_cache_t *cache; + ha_sync_segments_t *segments; /** * Segment control interface via FIFO @@ -80,7 +80,7 @@ static void destroy(private_ha_sync_plugin_t *this) this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); this->ctl->destroy(this->ctl); - this->cache->destroy(this->cache); + this->segments->destroy(this->segments); this->socket->destroy(this->socket); free(this); } @@ -100,11 +100,11 @@ plugin_t *plugin_create() free(this); return NULL; } - this->cache = ha_sync_cache_create(); - this->ctl = ha_sync_ctl_create(this->cache); - this->dispatcher = ha_sync_dispatcher_create(this->socket, this->cache); - this->ike = ha_sync_ike_create(this->socket, this->cache); - this->child = ha_sync_child_create(this->socket, this->cache); + this->segments = ha_sync_segments_create(); + this->ctl = ha_sync_ctl_create(this->segments); + this->dispatcher = ha_sync_dispatcher_create(this->socket); + this->ike = ha_sync_ike_create(this->socket); + this->child = ha_sync_child_create(this->socket); charon->bus->add_listener(charon->bus, &this->ike->listener); charon->bus->add_listener(charon->bus, &this->child->listener); diff --git a/src/charon/plugins/ha_sync/ha_sync_cache.c b/src/charon/plugins/ha_sync/ha_sync_segments.c index a36c8250c..6f9985bc1 100644 --- a/src/charon/plugins/ha_sync/ha_sync_cache.c +++ b/src/charon/plugins/ha_sync/ha_sync_segments.c @@ -15,7 +15,7 @@ * $Id$ */ -#include "ha_sync_cache.h" +#include "ha_sync_segments.h" #include <utils/linked_list.h> @@ -26,22 +26,17 @@ typedef u_int8_t u8; #define MAX_SEGMENTS 16 -typedef struct private_ha_sync_cache_t private_ha_sync_cache_t; +typedef struct private_ha_sync_segments_t private_ha_sync_segments_t; /** - * Private data of an ha_sync_cache_t object. + * Private data of an ha_sync_segments_t object. */ -struct private_ha_sync_cache_t { +struct private_ha_sync_segments_t { /** - * Public ha_sync_cache_t interface. + * Public ha_sync_segments_t interface. */ - ha_sync_cache_t public; - - /** - * Linked list of IKE_SAs, ike_sa_t - */ - linked_list_t *list; + ha_sync_segments_t public; /** * Init value for jhash @@ -60,79 +55,9 @@ struct private_ha_sync_cache_t { }; /** - * Implementation of ha_sync_cache_t.get_ike_sa - */ -static ike_sa_t* get_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id) -{ - enumerator_t *enumerator; - ike_sa_t *current, *found = NULL; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, ¤t)) - { - if (id->equals(id, current->get_id(current))) - { - found = current; - break; - } - } - enumerator->destroy(enumerator); - - if (!found) - { - found = ike_sa_create(id); - this->list->insert_first(this->list, found); - } - return found; -} - -/** - * Implementation of ha_sync_cache_t.has_ike_sa - */ -static bool has_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id) -{ - enumerator_t *enumerator; - ike_sa_t *ike_sa; - bool found = FALSE; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &ike_sa)) - { - if (id->equals(id, ike_sa->get_id(ike_sa))) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - return found; -} - -/** - * Implementation of ha_sync_cache_t.delete_ike_sa - */ -static void delete_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id) -{ - enumerator_t *enumerator; - ike_sa_t *ike_sa; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &ike_sa)) - { - if (id->equals(id, ike_sa->get_id(ike_sa))) - { - this->list->remove_at(this->list, enumerator); - ike_sa->destroy(ike_sa); - break; - } - } - enumerator->destroy(enumerator); -} - -/** * Check if a host address is in the CLUSTERIP segment */ -static bool in_segment(private_ha_sync_cache_t *this, +static bool in_segment(private_ha_sync_segments_t *this, host_t *host, u_int segment) { if (host->get_family(host) == AF_INET) @@ -154,7 +79,7 @@ static bool in_segment(private_ha_sync_cache_t *this, /** * Log currently active segments */ -static void log_segments(private_ha_sync_cache_t *this, bool activated, +static void log_segments(private_ha_sync_segments_t *this, bool activated, u_int segment) { char buf[64], *pos = buf; @@ -181,9 +106,9 @@ static void log_segments(private_ha_sync_cache_t *this, bool activated, } /** - * Implementation of ha_sync_cache_t.activate + * Implementation of ha_sync_segments_t.activate */ -static void activate(private_ha_sync_cache_t *this, u_int segment) +static void activate(private_ha_sync_segments_t *this, u_int segment) { ike_sa_t *ike_sa; enumerator_t *enumerator; @@ -195,63 +120,71 @@ static void activate(private_ha_sync_cache_t *this, u_int segment) { this->active |= mask; - enumerator = this->list->create_enumerator(this->list); + enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); while (enumerator->enumerate(enumerator, &ike_sa)) { - if (ike_sa->get_state(ike_sa) == IKE_CONNECTING && + if (ike_sa->get_state(ike_sa) == IKE_PASSIVE && in_segment(this, ike_sa->get_other_host(ike_sa), segment)) { - this->list->remove_at(this->list, enumerator); ike_sa->set_state(ike_sa, IKE_ESTABLISHED); - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } enumerator->destroy(enumerator); + log_segments(this, TRUE, segment); } } /** - * Implementation of ha_sync_cache_t.deactivate + * Implementation of ha_sync_segments_t.deactivate */ -static void deactivate(private_ha_sync_cache_t *this, u_int segment) +static void deactivate(private_ha_sync_segments_t *this, u_int segment) { + ike_sa_t *ike_sa; + enumerator_t *enumerator; u_int16_t mask = 0x01 << (segment - 1); if (segment > 0 && segment <= this->segment_count && (this->active & mask)) { this->active &= ~mask; + + enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + in_segment(this, ike_sa->get_other_host(ike_sa), segment)) + { + ike_sa->set_state(ike_sa, IKE_PASSIVE); + } + } + enumerator->destroy(enumerator); + log_segments(this, FALSE, segment); } } /** - * Implementation of ha_sync_cache_t.destroy. + * Implementation of ha_sync_segments_t.destroy. */ -static void destroy(private_ha_sync_cache_t *this) +static void destroy(private_ha_sync_segments_t *this) { - this->list->destroy_offset(this->list, offsetof(ike_sa_t, destroy)); free(this); } /** * See header */ -ha_sync_cache_t *ha_sync_cache_create() +ha_sync_segments_t *ha_sync_segments_create() { - private_ha_sync_cache_t *this = malloc_thing(private_ha_sync_cache_t); + private_ha_sync_segments_t *this = malloc_thing(private_ha_sync_segments_t); enumerator_t *enumerator; u_int segment; char *str; - this->public.get_ike_sa = (ike_sa_t*(*)(ha_sync_cache_t*, ike_sa_id_t *id))get_ike_sa; - this->public.has_ike_sa = (bool(*)(ha_sync_cache_t*, ike_sa_id_t *id))has_ike_sa; - this->public.delete_ike_sa = (void(*)(ha_sync_cache_t*, ike_sa_id_t *id))delete_ike_sa; - this->public.activate = (void(*)(ha_sync_cache_t*, u_int segment))activate; - this->public.deactivate = (void(*)(ha_sync_cache_t*, u_int segment))deactivate; - this->public.destroy = (void(*)(ha_sync_cache_t*))destroy; + this->public.activate = (void(*)(ha_sync_segments_t*, u_int segment))activate; + this->public.deactivate = (void(*)(ha_sync_segments_t*, u_int segment))deactivate; + this->public.destroy = (void(*)(ha_sync_segments_t*))destroy; - this->list = linked_list_create(); this->initval = 0; this->active = 0; this->segment_count = lib->settings->get_int(lib->settings, diff --git a/src/charon/plugins/ha_sync/ha_sync_segments.h b/src/charon/plugins/ha_sync/ha_sync_segments.h new file mode 100644 index 000000000..62908cf55 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_segments.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +/** + * @defgroup ha_sync_segments ha_sync_segments + * @{ @ingroup ha_sync + */ + +#ifndef HA_SYNC_SEGMENTS_H_ +#define HA_SYNC_SEGMENTS_H_ + +#include <daemon.h> + +typedef struct ha_sync_segments_t ha_sync_segments_t; + +/** + * Locally segmentsd HA state synced from other nodes. + */ +struct ha_sync_segments_t { + + /** + * Activate a set of IKE_SAs identified by a segments. + * + * Activating means do a takeover of SAs as the responsible node has failed. + * This involves moving all SAs to the daemons IKE_SA manager and handle + * them actively now. + * + * @param segments numerical segments to takeover + */ + void (*activate)(ha_sync_segments_t *this, u_int segments); + + /** + * Deactivate a set of IKE_SAs identified by a segments. + * + * @param segments numerical segments to takeover + */ + void (*deactivate)(ha_sync_segments_t *this, u_int segments); + + /** + * Destroy a ha_sync_segments_t. + */ + void (*destroy)(ha_sync_segments_t *this); +}; + +/** + * Create a ha_sync_segments instance. + */ +ha_sync_segments_t *ha_sync_segments_create(); + +#endif /* HA_SYNC_SEGMENTS_ @}*/ |
