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
+++ /dev/null
-/*
- * 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_ @}*/
* socket we use for syncing
*/
ha_sync_socket_t *socket;
-
- /**
- * synced and cached IKE_SA state
- */
- ha_sync_cache_t *cache;
};
/**
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));
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;
}
/**
* 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);
this->public.destroy = (void(*)(ha_sync_child_t*))destroy;
this->socket = socket;
- this->cache = cache;
return &this->public;
}
#define HA_SYNC_CHILD_H_
#include "ha_sync_socket.h"
-#include "ha_sync_cache.h"
+#include "ha_sync_segments.h"
#include <daemon.h>
* 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_ @}*/
ha_sync_ctl_t public;
/**
- * Cache to control
+ * Segments to control
*/
- ha_sync_cache_t *cache;
+ ha_sync_segments_t *segments;
/**
* FIFO reader thread
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;
/**
* 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);
}
}
- 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);
#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;
/**
* 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_ @}*/
*/
ha_sync_socket_t *socket;
- /**
- * Synced SA state cache
- */
- ha_sync_cache_t *cache;
-
/**
* Dispatcher job
*/
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;
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);
}
}
{
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));
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);
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);
}
}
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))
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;
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);
if (streq(current->get_name(current), name))
{
found = current;
- found->get_ref(found);
break;
}
}
enumerator->destroy(enumerator);
- peer_cfg->destroy(peer_cfg);
}
return found;
}
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;
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;
}
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);
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);
{
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;
}
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);
}
/**
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,
}
break;
}
+ if (ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
enumerator->destroy(enumerator);
}
/**
* 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);
#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;
* 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_ @}*/
* socket we use for syncing
*/
ha_sync_socket_t *socket;
-
- /**
- * Synced and cached SAs
- */
- ha_sync_cache_t *cache;
};
/**
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;
{
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;
}
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);
| 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));
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);
return TRUE;
}
+/**
+ * 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.
*/
/**
* 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;
}
#define HA_SYNC_IKE_H_
#include "ha_sync_socket.h"
-#include "ha_sync_cache.h"
+#include "ha_sync_segments.h"
#include <daemon.h>
* 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_ @}*/
{
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);
{
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);
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);
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))
{
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,
};
/**
#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>
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
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);
}
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);
* $Id$
*/
-#include "ha_sync_cache.h"
+#include "ha_sync_segments.h"
#include <utils/linked_list.h>
#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
u_int16_t active;
};
-/**
- * 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)
/**
* 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;
}
/**
- * 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;
{
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,
--- /dev/null
+/*
+ * 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_ @}*/
};
/**
- * Constructor to create a new child_sa_t.
+ * Constructor to create a child SA negotiated with IKE.
*
* @param me own address
* @param other remote address