IKE_SA activation/deactivation magic using a fifo socket
This commit is contained in:
committed by
Martin Willi
parent
c94fe198e9
commit
aa98188af5
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
|
INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
|
||||||
|
|
||||||
AM_CFLAGS = -rdynamic
|
AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\"
|
||||||
|
|
||||||
plugin_LTLIBRARIES = libstrongswan-ha-sync.la
|
plugin_LTLIBRARIES = libstrongswan-ha-sync.la
|
||||||
libstrongswan_ha_sync_la_SOURCES = \
|
libstrongswan_ha_sync_la_SOURCES = \
|
||||||
@@ -9,7 +9,8 @@ libstrongswan_ha_sync_la_SOURCES = \
|
|||||||
ha_sync_message.h ha_sync_message.c \
|
ha_sync_message.h ha_sync_message.c \
|
||||||
ha_sync_socket.h ha_sync_socket.c \
|
ha_sync_socket.h ha_sync_socket.c \
|
||||||
ha_sync_dispatcher.h ha_sync_dispatcher.c \
|
ha_sync_dispatcher.h ha_sync_dispatcher.c \
|
||||||
ha_sync_dispatcher.h ha_sync_cache.c \
|
ha_sync_cache.h ha_sync_cache.c \
|
||||||
|
ha_sync_ctl.h ha_sync_ctl.c \
|
||||||
ha_sync_ike.h ha_sync_ike.c \
|
ha_sync_ike.h ha_sync_ike.c \
|
||||||
ha_sync_child.h ha_sync_child.c
|
ha_sync_child.h ha_sync_child.c
|
||||||
libstrongswan_ha_sync_la_LDFLAGS = -module
|
libstrongswan_ha_sync_la_LDFLAGS = -module
|
||||||
|
|||||||
@@ -19,6 +19,13 @@
|
|||||||
|
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
|
typedef u_int32_t u32;
|
||||||
|
typedef u_int8_t u8;
|
||||||
|
|
||||||
|
#include <linux/jhash.h>
|
||||||
|
|
||||||
|
#define MAX_SEGMENTS 16
|
||||||
|
|
||||||
typedef struct private_ha_sync_cache_t private_ha_sync_cache_t;
|
typedef struct private_ha_sync_cache_t private_ha_sync_cache_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +42,21 @@ struct private_ha_sync_cache_t {
|
|||||||
* Linked list of IKE_SAs, ike_sa_t
|
* Linked list of IKE_SAs, ike_sa_t
|
||||||
*/
|
*/
|
||||||
linked_list_t *list;
|
linked_list_t *list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init value for jhash
|
||||||
|
*/
|
||||||
|
u_int initval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of ClusterIP segments
|
||||||
|
*/
|
||||||
|
u_int segment_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mask of active segments
|
||||||
|
*/
|
||||||
|
u_int16_t active;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,18 +130,98 @@ static void delete_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ha_sync_cache_t.activate_segment
|
* Check if a host address is in the CLUSTERIP segment
|
||||||
*/
|
*/
|
||||||
static void activate_segment(private_ha_sync_cache_t *this, u_int segment)
|
static bool in_segment(private_ha_sync_cache_t *this,
|
||||||
|
host_t *host, u_int segment)
|
||||||
|
{
|
||||||
|
if (host->get_family(host) == AF_INET)
|
||||||
|
{
|
||||||
|
unsigned long hash;
|
||||||
|
u_int32_t addr;
|
||||||
|
|
||||||
|
addr = *(u_int32_t*)host->get_address(host).ptr;
|
||||||
|
hash = jhash_1word(ntohl(addr), this->initval);
|
||||||
|
|
||||||
|
if ((((u_int64_t)hash * this->segment_count) >> 32) + 1 == segment)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log currently active segments
|
||||||
|
*/
|
||||||
|
static void log_segments(private_ha_sync_cache_t *this, bool activated,
|
||||||
|
u_int segment)
|
||||||
|
{
|
||||||
|
char buf[64], *pos = buf;
|
||||||
|
int i;
|
||||||
|
bool first = TRUE;
|
||||||
|
|
||||||
|
for (i = 0; i < this->segment_count; i++)
|
||||||
|
{
|
||||||
|
if (this->active & 0x01 << i)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos += snprintf(pos, buf + sizeof(buf) - pos, ",");
|
||||||
|
}
|
||||||
|
pos += snprintf(pos, buf + sizeof(buf) - pos, "%d", i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBG1(DBG_CFG, "HA sync segments %d %sactivated, now active: %s",
|
||||||
|
segment, activated ? "" : "de", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ha_sync_cache_t.activate
|
||||||
|
*/
|
||||||
|
static void activate(private_ha_sync_cache_t *this, u_int segment)
|
||||||
{
|
{
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
u_int16_t mask = 0x01 << (segment - 1);
|
||||||
|
|
||||||
/* TODO: activate only segment, not all */
|
DBG1(DBG_CFG, "activating segment %d", segment);
|
||||||
while (this->list->remove_last(this->list, (void**)&ike_sa) == SUCCESS)
|
|
||||||
|
if (segment > 0 && segment <= this->segment_count && !(this->active & mask))
|
||||||
{
|
{
|
||||||
/* TODO: fix checkin of inexisting IKE_SA in manager */
|
this->active |= mask;
|
||||||
/* TODO: do not activate SAs not in state CONNECTING */
|
|
||||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
enumerator = this->list->create_enumerator(this->list);
|
||||||
|
while (enumerator->enumerate(enumerator, &ike_sa))
|
||||||
|
{
|
||||||
|
if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
static void deactivate(private_ha_sync_cache_t *this, u_int segment)
|
||||||
|
{
|
||||||
|
u_int16_t mask = 0x01 << (segment - 1);
|
||||||
|
|
||||||
|
if (segment > 0 && segment <= this->segment_count && (this->active & mask))
|
||||||
|
{
|
||||||
|
this->active &= ~mask;
|
||||||
|
log_segments(this, FALSE, segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,14 +240,35 @@ static void destroy(private_ha_sync_cache_t *this)
|
|||||||
ha_sync_cache_t *ha_sync_cache_create()
|
ha_sync_cache_t *ha_sync_cache_create()
|
||||||
{
|
{
|
||||||
private_ha_sync_cache_t *this = malloc_thing(private_ha_sync_cache_t);
|
private_ha_sync_cache_t *this = malloc_thing(private_ha_sync_cache_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.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.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.delete_ike_sa = (void(*)(ha_sync_cache_t*, ike_sa_id_t *id))delete_ike_sa;
|
||||||
this->public.activate_segment = (void(*)(ha_sync_cache_t*, u_int segment))activate_segment;
|
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.destroy = (void(*)(ha_sync_cache_t*))destroy;
|
||||||
|
|
||||||
this->list = linked_list_create();
|
this->list = linked_list_create();
|
||||||
|
this->initval = 0;
|
||||||
|
this->active = 0;
|
||||||
|
this->segment_count = lib->settings->get_int(lib->settings,
|
||||||
|
"charon.plugins.ha_sync.segment_count", 1);
|
||||||
|
this->segment_count = min(this->segment_count, MAX_SEGMENTS);
|
||||||
|
str = lib->settings->get_str(lib->settings,
|
||||||
|
"charon.plugins.ha_sync.active_segments", "1");
|
||||||
|
enumerator = enumerator_create_token(str, ",", " ");
|
||||||
|
while (enumerator->enumerate(enumerator, &str))
|
||||||
|
{
|
||||||
|
segment = atoi(str);
|
||||||
|
if (segment && segment < MAX_SEGMENTS)
|
||||||
|
{
|
||||||
|
this->active |= 0x01 << (segment - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,14 @@ struct ha_sync_cache_t {
|
|||||||
*
|
*
|
||||||
* @param segment numerical segment to takeover
|
* @param segment numerical segment to takeover
|
||||||
*/
|
*/
|
||||||
void (*activate_segment)(ha_sync_cache_t *this, u_int segment);
|
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.
|
* Destroy a ha_sync_cache_t.
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ha_sync_ctl.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
|
#define HA_SYNC_FIFO IPSEC_PIDDIR "/charon.ha"
|
||||||
|
|
||||||
|
typedef struct private_ha_sync_ctl_t private_ha_sync_ctl_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an ha_sync_ctl_t object.
|
||||||
|
*/
|
||||||
|
struct private_ha_sync_ctl_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public ha_sync_ctl_t interface.
|
||||||
|
*/
|
||||||
|
ha_sync_ctl_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache to control
|
||||||
|
*/
|
||||||
|
ha_sync_cache_t *cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIFO reader thread
|
||||||
|
*/
|
||||||
|
callback_job_t *job;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIFO dispatching function
|
||||||
|
*/
|
||||||
|
static job_requeue_t dispatch_fifo(private_ha_sync_ctl_t *this)
|
||||||
|
{
|
||||||
|
int fifo, old;
|
||||||
|
char buf[8];
|
||||||
|
u_int segment;
|
||||||
|
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
|
||||||
|
fifo = open(HA_SYNC_FIFO, O_RDONLY);
|
||||||
|
pthread_setcancelstate(old, NULL);
|
||||||
|
if (fifo == -1)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "opening HA sync fifo failed: %s", strerror(errno));
|
||||||
|
sleep(1);
|
||||||
|
return JOB_REQUEUE_FAIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
if (read(fifo, buf, sizeof(buf)-1) > 1)
|
||||||
|
{
|
||||||
|
segment = atoi(&buf[1]);
|
||||||
|
if (segment)
|
||||||
|
{
|
||||||
|
switch (buf[0])
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
this->cache->activate(this->cache, segment);
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
this->cache->deactivate(this->cache, segment);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fifo);
|
||||||
|
|
||||||
|
return JOB_REQUEUE_DIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ha_sync_ctl_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_ha_sync_ctl_t *this)
|
||||||
|
{
|
||||||
|
this->job->cancel(this->job);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_cache_t *cache)
|
||||||
|
{
|
||||||
|
private_ha_sync_ctl_t *this = malloc_thing(private_ha_sync_ctl_t);
|
||||||
|
|
||||||
|
this->public.destroy = (void(*)(ha_sync_ctl_t*))destroy;
|
||||||
|
|
||||||
|
if (access(HA_SYNC_FIFO, R_OK|W_OK) != 0)
|
||||||
|
{
|
||||||
|
if (mkfifo(HA_SYNC_FIFO, 600) != 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "creating HA sync FIFO %s failed: %s",
|
||||||
|
HA_SYNC_FIFO, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->cache = cache;
|
||||||
|
this->job = callback_job_create((callback_job_cb_t)dispatch_fifo,
|
||||||
|
this, NULL, NULL);
|
||||||
|
charon->processor->queue_job(charon->processor, (job_t*)this->job);
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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_ctl ha_sync_ctl
|
||||||
|
* @{ @ingroup ha_sync
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HA_SYNC_CTL_H_
|
||||||
|
#define HA_SYNC_CTL_H_
|
||||||
|
|
||||||
|
#include "ha_sync_cache.h"
|
||||||
|
|
||||||
|
typedef struct ha_sync_ctl_t ha_sync_ctl_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HA Sync control interface using a FIFO.
|
||||||
|
*/
|
||||||
|
struct ha_sync_ctl_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a ha_sync_ctl_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(ha_sync_ctl_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ha_sync_ctl instance.
|
||||||
|
*
|
||||||
|
* @param cache cache to control in this socket
|
||||||
|
* @return HA sync control interface
|
||||||
|
*/
|
||||||
|
ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_cache_t *cache);
|
||||||
|
|
||||||
|
#endif /* HA_SYNC_CTL_ @}*/
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "ha_sync_socket.h"
|
#include "ha_sync_socket.h"
|
||||||
#include "ha_sync_dispatcher.h"
|
#include "ha_sync_dispatcher.h"
|
||||||
#include "ha_sync_cache.h"
|
#include "ha_sync_cache.h"
|
||||||
|
#include "ha_sync_ctl.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <config/child_cfg.h>
|
#include <config/child_cfg.h>
|
||||||
@@ -61,6 +62,11 @@ struct private_ha_sync_plugin_t {
|
|||||||
* Local cache of a nodes synced SAs
|
* Local cache of a nodes synced SAs
|
||||||
*/
|
*/
|
||||||
ha_sync_cache_t *cache;
|
ha_sync_cache_t *cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Segment control interface via FIFO
|
||||||
|
*/
|
||||||
|
ha_sync_ctl_t *ctl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,6 +79,7 @@ static void destroy(private_ha_sync_plugin_t *this)
|
|||||||
this->ike->destroy(this->ike);
|
this->ike->destroy(this->ike);
|
||||||
this->child->destroy(this->child);
|
this->child->destroy(this->child);
|
||||||
this->dispatcher->destroy(this->dispatcher);
|
this->dispatcher->destroy(this->dispatcher);
|
||||||
|
this->ctl->destroy(this->ctl);
|
||||||
this->cache->destroy(this->cache);
|
this->cache->destroy(this->cache);
|
||||||
this->socket->destroy(this->socket);
|
this->socket->destroy(this->socket);
|
||||||
free(this);
|
free(this);
|
||||||
@@ -94,6 +101,7 @@ plugin_t *plugin_create()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
this->cache = ha_sync_cache_create();
|
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->dispatcher = ha_sync_dispatcher_create(this->socket, this->cache);
|
||||||
this->ike = ha_sync_ike_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->child = ha_sync_child_create(this->socket, this->cache);
|
||||||
|
|||||||
Reference in New Issue
Block a user