Use a sync message cache to resynchronize IKE_SAs without rekeying
This commit is contained in:
parent
2031002d42
commit
aa334daa9b
|
@ -17,6 +17,7 @@ libstrongswan_ha_la_SOURCES = \
|
|||
ha_tunnel.h ha_tunnel.c \
|
||||
ha_dispatcher.h ha_dispatcher.c \
|
||||
ha_segments.h ha_segments.c \
|
||||
ha_cache.h ha_cache.c \
|
||||
ha_kernel.h ha_kernel.c \
|
||||
ha_ctl.h ha_ctl.c \
|
||||
ha_ike.h ha_ike.c \
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Martin Willi
|
||||
* Copyright (C) 2010 revosec AG
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ha_cache.h"
|
||||
|
||||
#include <utils/hashtable.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <threading/mutex.h>
|
||||
#include <processing/jobs/callback_job.h>
|
||||
|
||||
typedef struct private_ha_cache_t private_ha_cache_t;
|
||||
|
||||
/**
|
||||
* Private data of an ha_cache_t object.
|
||||
*/
|
||||
struct private_ha_cache_t {
|
||||
|
||||
/**
|
||||
* Public ha_cache_t interface.
|
||||
*/
|
||||
ha_cache_t public;
|
||||
|
||||
/**
|
||||
* Kernel helper functions
|
||||
*/
|
||||
ha_kernel_t *kernel;
|
||||
|
||||
/**
|
||||
* Socket to send sync messages over
|
||||
*/
|
||||
ha_socket_t *socket;
|
||||
|
||||
/**
|
||||
* Total number of segments
|
||||
*/
|
||||
u_int count;
|
||||
|
||||
/**
|
||||
* cached entries (ike_sa_t, entry_t)
|
||||
*/
|
||||
hashtable_t *cache;
|
||||
|
||||
/**
|
||||
* Mutex to lock cache
|
||||
*/
|
||||
mutex_t *mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hashtable hash function
|
||||
*/
|
||||
static u_int hash(void *key)
|
||||
{
|
||||
return (uintptr_t)key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable equals function
|
||||
*/
|
||||
static bool equals(void *a, void *b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache entry for an IKE_SA
|
||||
*/
|
||||
typedef struct {
|
||||
/* segment this entry is associate to */
|
||||
u_int segment;
|
||||
/* ADD message */
|
||||
ha_message_t *add;
|
||||
/* list of updates UPDATE message */
|
||||
linked_list_t *updates;
|
||||
/* last initiator mid */
|
||||
ha_message_t *midi;
|
||||
/* last responder mid */
|
||||
ha_message_t *midr;
|
||||
} entry_t;
|
||||
|
||||
/**
|
||||
* Create a entry with an add message
|
||||
*/
|
||||
static entry_t *entry_create(ha_message_t *add)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
INIT(entry,
|
||||
.add = add,
|
||||
.updates = linked_list_create(),
|
||||
);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* clean up a entry
|
||||
*/
|
||||
static void entry_destroy(entry_t *entry)
|
||||
{
|
||||
entry->updates->destroy_offset(entry->updates,
|
||||
offsetof(ha_message_t, destroy));
|
||||
entry->add->destroy(entry->add);
|
||||
DESTROY_IF(entry->midi);
|
||||
DESTROY_IF(entry->midr);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
METHOD(ha_cache_t, cache, void,
|
||||
private_ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
switch (message->get_type(message))
|
||||
{
|
||||
case HA_IKE_ADD:
|
||||
entry = entry_create(message);
|
||||
entry = this->cache->put(this->cache, ike_sa, entry);
|
||||
if (entry)
|
||||
{
|
||||
entry_destroy(entry);
|
||||
}
|
||||
break;
|
||||
case HA_IKE_UPDATE:
|
||||
entry = this->cache->get(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
entry->segment = this->kernel->get_segment(this->kernel,
|
||||
ike_sa->get_other_host(ike_sa));
|
||||
entry->updates->insert_last(entry->updates, message);
|
||||
break;
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
case HA_IKE_MID_INITIATOR:
|
||||
entry = this->cache->get(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
DESTROY_IF(entry->midi);
|
||||
entry->midi = message;
|
||||
break;
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
case HA_IKE_MID_RESPONDER:
|
||||
entry = this->cache->get(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
DESTROY_IF(entry->midr);
|
||||
entry->midr = message;
|
||||
break;
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
case HA_IKE_DELETE:
|
||||
entry = this->cache->remove(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
entry_destroy(entry);
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
default:
|
||||
message->destroy(message);
|
||||
break;
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
}
|
||||
|
||||
METHOD(ha_cache_t, delete_, void,
|
||||
private_ha_cache_t *this, ike_sa_t *ike_sa)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
entry = this->cache->remove(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rekey all children of an IKE_SA
|
||||
*/
|
||||
static status_t rekey_children(ike_sa_t *ike_sa)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
child_sa_t *child_sa;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
iterator = ike_sa->create_child_sa_iterator(ike_sa);
|
||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||
{
|
||||
DBG1(DBG_CFG, "resyncing CHILD_SA");
|
||||
status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
|
||||
child_sa->get_spi(child_sa, TRUE));
|
||||
if (status == DESTROY_ME)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger rekeying of CHILD_SA in segment
|
||||
*/
|
||||
static void rekey_segment(private_ha_cache_t *this, u_int segment)
|
||||
{
|
||||
ike_sa_t *ike_sa;
|
||||
enumerator_t *enumerator;
|
||||
linked_list_t *list;
|
||||
ike_sa_id_t *id;
|
||||
|
||||
list = linked_list_create();
|
||||
|
||||
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 &&
|
||||
this->kernel->get_segment(this->kernel,
|
||||
ike_sa->get_other_host(ike_sa)) == segment)
|
||||
{
|
||||
id = ike_sa->get_id(ike_sa);
|
||||
list->insert_last(list, id->clone(id));
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
while (list->remove_last(list, (void**)&id) == SUCCESS)
|
||||
{
|
||||
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
||||
if (ike_sa)
|
||||
{
|
||||
if (rekey_children(ike_sa) != DESTROY_ME)
|
||||
{
|
||||
charon->ike_sa_manager->checkin(
|
||||
charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
charon->ike_sa_manager->checkin_and_destroy(
|
||||
charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
}
|
||||
id->destroy(id);
|
||||
}
|
||||
list->destroy(list);
|
||||
}
|
||||
|
||||
METHOD(ha_cache_t, resync, void,
|
||||
private_ha_cache_t *this, u_int segment)
|
||||
{
|
||||
enumerator_t *enumerator, *updates;
|
||||
ike_sa_t *ike_sa;
|
||||
entry_t *entry;
|
||||
ha_message_t *message;
|
||||
|
||||
DBG1(DBG_CFG, "resyncing HA segment %d", segment);
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
enumerator = this->cache->create_enumerator(this->cache);
|
||||
while (enumerator->enumerate(enumerator, &ike_sa, &entry))
|
||||
{
|
||||
if (entry->segment == segment)
|
||||
{
|
||||
this->socket->push(this->socket, entry->add);
|
||||
updates = entry->updates->create_enumerator(entry->updates);
|
||||
while (updates->enumerate(updates, &message))
|
||||
{
|
||||
this->socket->push(this->socket, message);
|
||||
}
|
||||
updates->destroy(updates);
|
||||
if (entry->midi)
|
||||
{
|
||||
this->socket->push(this->socket, entry->midi);
|
||||
}
|
||||
if (entry->midr)
|
||||
{
|
||||
this->socket->push(this->socket, entry->midr);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
rekey_segment(this, segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a resync of all segments
|
||||
*/
|
||||
static job_requeue_t request_resync(private_ha_cache_t *this)
|
||||
{
|
||||
ha_message_t *message;
|
||||
int i;
|
||||
|
||||
DBG1(DBG_CFG, "requesting HA resynchronization");
|
||||
|
||||
message = ha_message_create(HA_RESYNC);
|
||||
for (i = 1; i <= this->count; i++)
|
||||
{
|
||||
message->add_attribute(message, HA_SEGMENT, i);
|
||||
}
|
||||
this->socket->push(this->socket, message);
|
||||
message->destroy(message);
|
||||
return JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
METHOD(ha_cache_t, destroy, void,
|
||||
private_ha_cache_t *this)
|
||||
{
|
||||
this->cache->destroy(this->cache);
|
||||
this->mutex->destroy(this->mutex);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
|
||||
bool sync, u_int count)
|
||||
{
|
||||
private_ha_cache_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.cache = _cache,
|
||||
.delete = _delete_,
|
||||
.resync = _resync,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.count = count,
|
||||
.kernel = kernel,
|
||||
.socket = socket,
|
||||
.cache = hashtable_create(hash, equals, 8),
|
||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||
);
|
||||
|
||||
if (sync)
|
||||
{
|
||||
/* request a resync as soon as we are up */
|
||||
charon->scheduler->schedule_job(charon->scheduler, (job_t*)
|
||||
callback_job_create((callback_job_cb_t)request_resync,
|
||||
this, NULL, NULL), 1);
|
||||
}
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Martin Willi
|
||||
* Copyright (C) 2010 revosec AG
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ha_cache ha_cache
|
||||
* @{ @ingroup ha
|
||||
*/
|
||||
|
||||
#ifndef HA_CACHE_H_
|
||||
#define HA_CACHE_H_
|
||||
|
||||
typedef struct ha_cache_t ha_cache_t;
|
||||
|
||||
#include "ha_message.h"
|
||||
#include "ha_kernel.h"
|
||||
#include "ha_socket.h"
|
||||
|
||||
#include <utils/enumerator.h>
|
||||
|
||||
#include <sa/ike_sa.h>
|
||||
|
||||
/**
|
||||
* HA message caching facility, allows reintegration of new nodes.
|
||||
*/
|
||||
struct ha_cache_t {
|
||||
|
||||
/**
|
||||
* Cache an IKE specific message.
|
||||
*
|
||||
* @param ike_sa associated IKE_SA
|
||||
* @param message message to cache
|
||||
*/
|
||||
void (*cache)(ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message);
|
||||
|
||||
/**
|
||||
* Delete a cache entry for an IKE_SA.
|
||||
*
|
||||
* @param ike_sa cache entry to delete
|
||||
*/
|
||||
void (*delete)(ha_cache_t *this, ike_sa_t *ike_sa);
|
||||
|
||||
/**
|
||||
* Resync a segment to the node using the cached messages.
|
||||
*
|
||||
* @param segment segment to resync
|
||||
*/
|
||||
void (*resync)(ha_cache_t *this, u_int segment);
|
||||
|
||||
/**
|
||||
* Destroy a ha_cache_t.
|
||||
*/
|
||||
void (*destroy)(ha_cache_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a ha_cache instance.
|
||||
*
|
||||
* @param kernel kernel helper
|
||||
* @param socket socket to send resync messages
|
||||
* @param resync request a resync during startup?
|
||||
* @param count total number of segments
|
||||
*/
|
||||
ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
|
||||
bool resync, u_int count);
|
||||
|
||||
#endif /** HA_CACHE_H_ @}*/
|
|
@ -36,6 +36,11 @@ struct private_ha_child_t {
|
|||
* tunnel securing sync messages
|
||||
*/
|
||||
ha_tunnel_t *tunnel;
|
||||
|
||||
/**
|
||||
* message cache
|
||||
*/
|
||||
ha_cache_t *cache;
|
||||
};
|
||||
|
||||
METHOD(listener_t, child_keys, bool,
|
||||
|
@ -103,6 +108,7 @@ METHOD(listener_t, child_keys, bool,
|
|||
enumerator->destroy(enumerator);
|
||||
|
||||
this->socket->push(this->socket, m);
|
||||
m->destroy(m);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -133,6 +139,7 @@ METHOD(listener_t, child_state_change, bool,
|
|||
m->add_attribute(m, HA_INBOUND_SPI,
|
||||
child_sa->get_spi(child_sa, TRUE));
|
||||
this->socket->push(this->socket, m);
|
||||
m->destroy(m);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -146,7 +153,8 @@ METHOD(ha_child_t, destroy, void,
|
|||
/**
|
||||
* See header
|
||||
*/
|
||||
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
|
||||
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
|
||||
ha_cache_t *cache)
|
||||
{
|
||||
private_ha_child_t *this;
|
||||
|
||||
|
@ -160,6 +168,7 @@ ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
|
|||
},
|
||||
.socket = socket,
|
||||
.tunnel = tunnel,
|
||||
.cache = cache,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
|
|
|
@ -21,14 +21,15 @@
|
|||
#ifndef HA_CHILD_H_
|
||||
#define HA_CHILD_H_
|
||||
|
||||
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 <daemon.h>
|
||||
|
||||
typedef struct ha_child_t ha_child_t;
|
||||
|
||||
/**
|
||||
* Listener to synchronize CHILD_SAs.
|
||||
*/
|
||||
|
@ -50,8 +51,10 @@ 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
|
||||
* @return CHILD listener
|
||||
*/
|
||||
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
|
||||
ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
|
||||
ha_cache_t *cache);
|
||||
|
||||
#endif /** HA_CHILD_ @}*/
|
||||
|
|
|
@ -44,6 +44,11 @@ struct private_ha_ctl_t {
|
|||
*/
|
||||
ha_segments_t *segments;
|
||||
|
||||
/**
|
||||
* Resynchronization message cache
|
||||
*/
|
||||
ha_cache_t *cache;
|
||||
|
||||
/**
|
||||
* FIFO reader thread
|
||||
*/
|
||||
|
@ -84,7 +89,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
|
|||
this->segments->deactivate(this->segments, segment, TRUE);
|
||||
break;
|
||||
case '*':
|
||||
this->segments->resync(this->segments, segment);
|
||||
this->cache->resync(this->cache, segment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -106,7 +111,7 @@ METHOD(ha_ctl_t, destroy, void,
|
|||
/**
|
||||
* See header
|
||||
*/
|
||||
ha_ctl_t *ha_ctl_create(ha_segments_t *segments)
|
||||
ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
|
||||
{
|
||||
private_ha_ctl_t *this;
|
||||
|
||||
|
@ -115,6 +120,7 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments)
|
|||
.destroy = _destroy,
|
||||
},
|
||||
.segments = segments,
|
||||
.cache = cache,
|
||||
);
|
||||
|
||||
if (access(HA_FIFO, R_OK|W_OK) != 0)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define HA_CTL_H_
|
||||
|
||||
#include "ha_segments.h"
|
||||
#include "ha_cache.h"
|
||||
|
||||
typedef struct ha_ctl_t ha_ctl_t;
|
||||
|
||||
|
@ -40,8 +41,9 @@ struct ha_ctl_t {
|
|||
* Create a ha_ctl instance.
|
||||
*
|
||||
* @param segments segments to control
|
||||
* @param cache message cache for resynchronization
|
||||
* @return HA control interface
|
||||
*/
|
||||
ha_ctl_t *ha_ctl_create(ha_segments_t *segments);
|
||||
ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache);
|
||||
|
||||
#endif /** HA_CTL_ @}*/
|
||||
|
|
|
@ -40,6 +40,11 @@ struct private_ha_dispatcher_t {
|
|||
*/
|
||||
ha_segments_t *segments;
|
||||
|
||||
/**
|
||||
* Cache for resync
|
||||
*/
|
||||
ha_cache_t *cache;
|
||||
|
||||
/**
|
||||
* Dispatcher job
|
||||
*/
|
||||
|
@ -153,6 +158,8 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
|||
old_sa = NULL;
|
||||
}
|
||||
ike_sa->set_state(ike_sa, IKE_CONNECTING);
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
message = NULL;
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
|
@ -167,6 +174,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
|||
{
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
|
||||
}
|
||||
DESTROY_IF(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,10 +284,20 @@ static void process_ike_update(private_ha_dispatcher_t *this,
|
|||
if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
|
||||
ike_sa->get_peer_cfg(ike_sa))
|
||||
{
|
||||
DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
|
||||
ike_sa->get_name(ike_sa),
|
||||
ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
|
||||
ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
|
||||
ike_sa->set_state(ike_sa, IKE_PASSIVE);
|
||||
}
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_CFG, "passive HA IKE_SA to update not found");
|
||||
message->destroy(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,8 +336,13 @@ static void process_ike_mid(private_ha_dispatcher_t *this,
|
|||
{
|
||||
ike_sa->set_message_id(ike_sa, initiator, mid);
|
||||
}
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
message->destroy(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,7 +354,7 @@ static void process_ike_delete(private_ha_dispatcher_t *this,
|
|||
ha_message_attribute_t attribute;
|
||||
ha_message_value_t value;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa;
|
||||
ike_sa_t *ike_sa = NULL;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
|
@ -341,17 +364,22 @@ static void process_ike_delete(private_ha_dispatcher_t *this,
|
|||
case HA_IKE_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);
|
||||
if (ike_sa)
|
||||
{
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
charon->ike_sa_manager->checkin_and_destroy(
|
||||
charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
message->destroy(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,6 +493,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
|||
if (!ike_sa)
|
||||
{
|
||||
DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found");
|
||||
message->destroy(message);
|
||||
return;
|
||||
}
|
||||
config = find_child_cfg(ike_sa, config_name);
|
||||
|
@ -472,6 +501,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
|||
{
|
||||
DBG1(DBG_CHD, "HA is missing nodes child configuration");
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
message->destroy(message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -558,15 +588,19 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
|||
local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
|
||||
remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
message->destroy(message);
|
||||
return;
|
||||
}
|
||||
|
||||
DBG1(DBG_CFG, "installed HA CHILD_SA '%s' %#R=== %#R",
|
||||
child_sa->get_name(child_sa), local_ts, remote_ts);
|
||||
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));
|
||||
|
||||
child_sa->set_state(child_sa, CHILD_INSTALLED);
|
||||
ike_sa->add_child_sa(ike_sa, child_sa);
|
||||
message->destroy(message);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
|
||||
|
@ -580,6 +614,8 @@ static void process_child_delete(private_ha_dispatcher_t *this,
|
|||
ha_message_value_t value;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa = NULL;
|
||||
child_sa_t *child_sa;
|
||||
u_int32_t spi = 0;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
|
@ -591,20 +627,24 @@ static void process_child_delete(private_ha_dispatcher_t *this,
|
|||
value.ike_sa_id);
|
||||
break;
|
||||
case HA_INBOUND_SPI:
|
||||
if (ike_sa)
|
||||
{
|
||||
ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, value.u32);
|
||||
}
|
||||
spi = value.u32;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (ike_sa)
|
||||
{
|
||||
child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE);
|
||||
if (child_sa)
|
||||
{
|
||||
ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi);
|
||||
}
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -639,6 +679,7 @@ static void process_segment(private_ha_dispatcher_t *this,
|
|||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -667,6 +708,7 @@ static void process_status(private_ha_dispatcher_t *this,
|
|||
enumerator->destroy(enumerator);
|
||||
|
||||
this->segments->handle_status(this->segments, mask);
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -685,13 +727,14 @@ static void process_resync(private_ha_dispatcher_t *this,
|
|||
switch (attribute)
|
||||
{
|
||||
case HA_SEGMENT:
|
||||
this->segments->resync(this->segments, value.u16);
|
||||
this->cache->resync(this->cache, value.u16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -746,10 +789,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
|
|||
break;
|
||||
default:
|
||||
DBG1(DBG_CFG, "received unknown HA message type %d", type);
|
||||
message->destroy(message);
|
||||
break;
|
||||
}
|
||||
message->destroy(message);
|
||||
|
||||
return JOB_REQUEUE_DIRECT;
|
||||
}
|
||||
|
||||
|
@ -764,7 +806,7 @@ METHOD(ha_dispatcher_t, destroy, void,
|
|||
* See header
|
||||
*/
|
||||
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
|
||||
ha_segments_t *segments)
|
||||
ha_segments_t *segments, ha_cache_t *cache)
|
||||
{
|
||||
private_ha_dispatcher_t *this;
|
||||
|
||||
|
@ -775,6 +817,7 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
|
|||
},
|
||||
.socket = socket,
|
||||
.segments = segments,
|
||||
.cache = cache,
|
||||
);
|
||||
this->job = callback_job_create((callback_job_cb_t)dispatch,
|
||||
this, NULL, NULL);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "ha_socket.h"
|
||||
#include "ha_segments.h"
|
||||
#include "ha_cache.h"
|
||||
|
||||
typedef struct ha_dispatcher_t ha_dispatcher_t;
|
||||
|
||||
|
@ -42,9 +43,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
|
||||
* @return dispatcher object
|
||||
*/
|
||||
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
|
||||
ha_segments_t *segments);
|
||||
ha_segments_t *segments, ha_cache_t *cache);
|
||||
|
||||
#endif /** HA_DISPATCHER_ @}*/
|
||||
|
|
|
@ -36,6 +36,11 @@ struct private_ha_ike_t {
|
|||
* tunnel securing sync messages
|
||||
*/
|
||||
ha_tunnel_t *tunnel;
|
||||
|
||||
/**
|
||||
* message cache
|
||||
*/
|
||||
ha_cache_t *cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -117,6 +122,7 @@ METHOD(listener_t, ike_keys, bool,
|
|||
chunk_clear(&secret);
|
||||
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -181,6 +187,7 @@ METHOD(listener_t, ike_updown, bool,
|
|||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
}
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -192,6 +199,17 @@ METHOD(listener_t, ike_rekey, bool,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(listener_t, ike_state_change, bool,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, ike_sa_state_t new)
|
||||
{
|
||||
/* clean up cache if a passive IKE_SA goes away */
|
||||
if (ike_sa->get_state(ike_sa) == IKE_PASSIVE && new == IKE_DESTROYING)
|
||||
{
|
||||
this->cache->delete(this->cache, ike_sa);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(listener_t, message_hook, bool,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming)
|
||||
{
|
||||
|
@ -216,6 +234,7 @@ METHOD(listener_t, message_hook, bool,
|
|||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
message->get_exchange_type(message) == IKE_AUTH &&
|
||||
|
@ -233,6 +252,7 @@ METHOD(listener_t, message_hook, bool,
|
|||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_REMOTE_VIP, vip);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -247,7 +267,8 @@ METHOD(ha_ike_t, destroy, void,
|
|||
/**
|
||||
* See header
|
||||
*/
|
||||
ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
|
||||
ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
|
||||
ha_cache_t *cache)
|
||||
{
|
||||
private_ha_ike_t *this;
|
||||
|
||||
|
@ -257,12 +278,14 @@ ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
|
|||
.ike_keys = _ike_keys,
|
||||
.ike_updown = _ike_updown,
|
||||
.ike_rekey = _ike_rekey,
|
||||
.ike_state_change = _ike_state_change,
|
||||
.message = _message_hook,
|
||||
},
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.socket = socket,
|
||||
.tunnel = tunnel,
|
||||
.cache = cache,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
|
|
|
@ -21,14 +21,15 @@
|
|||
#ifndef HA_IKE_H_
|
||||
#define HA_IKE_H_
|
||||
|
||||
typedef struct ha_ike_t ha_ike_t;
|
||||
|
||||
#include "ha_socket.h"
|
||||
#include "ha_tunnel.h"
|
||||
#include "ha_segments.h"
|
||||
#include "ha_cache.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct ha_ike_t ha_ike_t;
|
||||
|
||||
/**
|
||||
* Listener to synchronize IKE_SAs.
|
||||
*/
|
||||
|
@ -50,8 +51,10 @@ struct ha_ike_t {
|
|||
*
|
||||
* @param socket socket to use for sending synchronization messages
|
||||
* @param tunnel tunnel securing sync messages, if any
|
||||
* @param cache message cache
|
||||
* @return IKE listener
|
||||
*/
|
||||
ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
|
||||
ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
|
||||
ha_cache_t *cache);
|
||||
|
||||
#endif /** HA_IKE_ @}*/
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "ha_dispatcher.h"
|
||||
#include "ha_segments.h"
|
||||
#include "ha_ctl.h"
|
||||
#include "ha_cache.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <config/child_cfg.h>
|
||||
|
@ -76,6 +77,11 @@ struct private_ha_plugin_t {
|
|||
* Segment control interface via FIFO
|
||||
*/
|
||||
ha_ctl_t *ctl;
|
||||
|
||||
/**
|
||||
* Message cache for resynchronization
|
||||
*/
|
||||
ha_cache_t *cache;
|
||||
};
|
||||
|
||||
METHOD(plugin_t, destroy, void,
|
||||
|
@ -88,6 +94,7 @@ METHOD(plugin_t, destroy, void,
|
|||
this->ike->destroy(this->ike);
|
||||
this->child->destroy(this->child);
|
||||
this->dispatcher->destroy(this->dispatcher);
|
||||
this->cache->destroy(this->cache);
|
||||
this->segments->destroy(this->segments);
|
||||
this->kernel->destroy(this->kernel);
|
||||
this->socket->destroy(this->socket);
|
||||
|
@ -142,14 +149,16 @@ plugin_t *ha_plugin_create()
|
|||
}
|
||||
this->kernel = ha_kernel_create(count);
|
||||
this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
|
||||
count, strcmp(local, remote) > 0, monitor, resync);
|
||||
count, strcmp(local, remote) > 0, monitor);
|
||||
this->cache = ha_cache_create(this->kernel, this->socket, resync, count);
|
||||
if (fifo)
|
||||
{
|
||||
this->ctl = ha_ctl_create(this->segments);
|
||||
this->ctl = ha_ctl_create(this->segments, this->cache);
|
||||
}
|
||||
this->dispatcher = ha_dispatcher_create(this->socket, this->segments);
|
||||
this->ike = ha_ike_create(this->socket, this->tunnel);
|
||||
this->child = ha_child_create(this->socket, this->tunnel);
|
||||
this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
|
||||
this->cache);
|
||||
this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
|
||||
this->child = ha_child_create(this->socket, this->tunnel, this->cache);
|
||||
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);
|
||||
|
|
|
@ -183,6 +183,7 @@ static void enable_disable(private_ha_segments_t *this, u_int segment,
|
|||
message = ha_message_create(type);
|
||||
message->add_attribute(message, HA_SEGMENT, segment);
|
||||
this->socket->push(this->socket, message);
|
||||
message->destroy(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,115 +222,24 @@ METHOD(ha_segments_t, deactivate, void,
|
|||
enable_disable_all(this, segment, FALSE, notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rekey all children of an IKE_SA
|
||||
*/
|
||||
static status_t rekey_children(ike_sa_t *ike_sa)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
child_sa_t *child_sa;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
iterator = ike_sa->create_child_sa_iterator(ike_sa);
|
||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||
{
|
||||
DBG1(DBG_CFG, "resyncing CHILD_SA");
|
||||
status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
|
||||
child_sa->get_spi(child_sa, TRUE));
|
||||
if (status == DESTROY_ME)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(ha_segments_t, resync, void,
|
||||
private_ha_segments_t *this, u_int segment)
|
||||
{
|
||||
ike_sa_t *ike_sa;
|
||||
enumerator_t *enumerator;
|
||||
linked_list_t *list;
|
||||
ike_sa_id_t *id;
|
||||
|
||||
list = linked_list_create();
|
||||
this->mutex->lock(this->mutex);
|
||||
|
||||
if (segment > 0 && segment <= this->count)
|
||||
{
|
||||
DBG1(DBG_CFG, "resyncing HA segment %d", segment);
|
||||
|
||||
/* we do the actual rekeying in a seperate loop to avoid rekeying
|
||||
* an SA twice. */
|
||||
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 &&
|
||||
this->kernel->get_segment(this->kernel,
|
||||
ike_sa->get_other_host(ike_sa)) == segment)
|
||||
{
|
||||
id = ike_sa->get_id(ike_sa);
|
||||
list->insert_last(list, id->clone(id));
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
while (list->remove_last(list, (void**)&id) == SUCCESS)
|
||||
{
|
||||
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
||||
id->destroy(id);
|
||||
if (ike_sa)
|
||||
{
|
||||
DBG1(DBG_CFG, "resyncing IKE_SA");
|
||||
if (ike_sa->rekey(ike_sa) != DESTROY_ME)
|
||||
{
|
||||
if (rekey_children(ike_sa) != DESTROY_ME)
|
||||
{
|
||||
charon->ike_sa_manager->checkin(
|
||||
charon->ike_sa_manager, ike_sa);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
charon->ike_sa_manager->checkin_and_destroy(
|
||||
charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
}
|
||||
list->destroy(list);
|
||||
}
|
||||
|
||||
METHOD(listener_t, alert_hook, bool,
|
||||
private_ha_segments_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args)
|
||||
{
|
||||
if (alert == ALERT_SHUTDOWN_SIGNAL)
|
||||
{
|
||||
deactivate(this, 0, TRUE);
|
||||
if (this->job)
|
||||
{
|
||||
DBG1(DBG_CFG, "HA heartbeat active, dropping all segments");
|
||||
deactivate(this, 0, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_CFG, "no HA heartbeat active, closing IKE_SAs");
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a resync of all segments
|
||||
*/
|
||||
static job_requeue_t request_resync(private_ha_segments_t *this)
|
||||
{
|
||||
ha_message_t *message;
|
||||
int i;
|
||||
|
||||
DBG1(DBG_CFG, "requesting HA resynchronization");
|
||||
|
||||
message = ha_message_create(HA_RESYNC);
|
||||
for (i = 1; i <= this->count; i++)
|
||||
{
|
||||
message->add_attribute(message, HA_SEGMENT, i);
|
||||
}
|
||||
this->socket->push(this->socket, message);
|
||||
return JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitor heartbeat activity of remote node
|
||||
*/
|
||||
|
@ -422,6 +332,7 @@ static job_requeue_t send_status(private_ha_segments_t *this)
|
|||
}
|
||||
|
||||
this->socket->push(this->socket, message);
|
||||
message->destroy(message);
|
||||
|
||||
/* schedule next invocation */
|
||||
charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
|
||||
|
@ -449,7 +360,7 @@ METHOD(ha_segments_t, destroy, void,
|
|||
*/
|
||||
ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
|
||||
ha_tunnel_t *tunnel, u_int count, u_int node,
|
||||
bool monitor, bool sync)
|
||||
bool monitor)
|
||||
{
|
||||
private_ha_segments_t *this;
|
||||
|
||||
|
@ -458,7 +369,6 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
|
|||
.listener.alert = _alert_hook,
|
||||
.activate = _activate,
|
||||
.deactivate = _deactivate,
|
||||
.resync = _resync,
|
||||
.handle_status = _handle_status,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
|
@ -477,14 +387,6 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
|
|||
start_watchdog(this);
|
||||
}
|
||||
|
||||
if (sync)
|
||||
{
|
||||
/* request a resync as soon as we are up */
|
||||
charon->scheduler->schedule_job(charon->scheduler, (job_t*)
|
||||
callback_job_create((callback_job_cb_t)request_resync,
|
||||
this, NULL, NULL), 2);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,18 +67,6 @@ struct ha_segments_t {
|
|||
*/
|
||||
void (*deactivate)(ha_segments_t *this, u_int segment, bool notify);
|
||||
|
||||
/**
|
||||
* Resync an active segment.
|
||||
*
|
||||
* To reintegrade a node into the cluster, resynchronization is reqired.
|
||||
* IKE_SAs and CHILD_SAs are synced automatically during rekeying. A call
|
||||
* to this method enforces a rekeying immediately sync all state of a
|
||||
* segment.
|
||||
*
|
||||
* @param segment segment to resync
|
||||
*/
|
||||
void (*resync)(ha_segments_t *this, u_int segment);
|
||||
|
||||
/**
|
||||
* Handle a status message from the remote node.
|
||||
*
|
||||
|
@ -101,11 +89,10 @@ struct ha_segments_t {
|
|||
* @param count number of segments the cluster uses
|
||||
* @param node node, currently 1 or 0
|
||||
* @param monitor should we use monitoring functionality
|
||||
* @param resync request a complete resync on startup
|
||||
* @return segment object
|
||||
*/
|
||||
ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
|
||||
ha_tunnel_t *tunnel, u_int count, u_int node,
|
||||
bool monitor, bool resync);
|
||||
bool monitor);
|
||||
|
||||
#endif /** HA_SEGMENTS_ @}*/
|
||||
|
|
|
@ -58,8 +58,8 @@ struct private_ha_socket_t {
|
|||
* Data to pass to the send_message() callback job
|
||||
*/
|
||||
typedef struct {
|
||||
ha_message_t *message;
|
||||
private_ha_socket_t *this;
|
||||
chunk_t chunk;
|
||||
int fd;
|
||||
} job_data_t;
|
||||
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ typedef struct {
|
|||
*/
|
||||
static void job_data_destroy(job_data_t *this)
|
||||
{
|
||||
this->message->destroy(this->message);
|
||||
free(this->chunk.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
@ -76,12 +76,7 @@ static void job_data_destroy(job_data_t *this)
|
|||
*/
|
||||
static job_requeue_t send_message(job_data_t *data)
|
||||
{
|
||||
private_ha_socket_t *this;
|
||||
chunk_t chunk;
|
||||
|
||||
this = data->this;
|
||||
chunk = data->message->get_encoding(data->message);
|
||||
if (send(this->fd, chunk.ptr, chunk.len, 0) < chunk.len)
|
||||
if (send(data->fd, data->chunk.ptr, data->chunk.len, 0) < data->chunk.len)
|
||||
{
|
||||
DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
|
||||
}
|
||||
|
@ -105,9 +100,10 @@ METHOD(ha_socket_t, push, void,
|
|||
/* Fallback to asynchronous transmission. This is required, as sendto()
|
||||
* is a blocking call if it acquires a policy. We could end up in a
|
||||
* deadlock, as we own an IKE_SA. */
|
||||
data = malloc_thing(job_data_t);
|
||||
data->message = message;
|
||||
data->this = this;
|
||||
INIT(data,
|
||||
.chunk = chunk_clone(chunk),
|
||||
.fd = this->fd,
|
||||
);
|
||||
|
||||
job = callback_job_create((callback_job_cb_t)send_message,
|
||||
data, (void*)job_data_destroy, NULL);
|
||||
|
@ -116,7 +112,6 @@ METHOD(ha_socket_t, push, void,
|
|||
}
|
||||
DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
|
||||
}
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
METHOD(ha_socket_t, pull, ha_message_t*,
|
||||
|
|
|
@ -35,7 +35,7 @@ struct ha_socket_t {
|
|||
/**
|
||||
* Push synchronization information to the responsible node.
|
||||
*
|
||||
* @param message message to send, gets destroyed by push()
|
||||
* @param message message to send
|
||||
*/
|
||||
void (*push)(ha_socket_t *this, ha_message_t *message);
|
||||
|
||||
|
|
Loading…
Reference in New Issue