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
|
||||
libstrongswan_ha_sync_la_SOURCES = \
|
||||
@@ -9,7 +9,8 @@ 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_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_child.h ha_sync_child.c
|
||||
libstrongswan_ha_sync_la_LDFLAGS = -module
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
|
||||
#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;
|
||||
|
||||
/**
|
||||
@@ -35,6 +42,21 @@ struct private_ha_sync_cache_t {
|
||||
* Linked list of IKE_SAs, ike_sa_t
|
||||
*/
|
||||
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;
|
||||
enumerator_t *enumerator;
|
||||
u_int16_t mask = 0x01 << (segment - 1);
|
||||
|
||||
/* TODO: activate only segment, not all */
|
||||
while (this->list->remove_last(this->list, (void**)&ike_sa) == SUCCESS)
|
||||
DBG1(DBG_CFG, "activating segment %d", segment);
|
||||
|
||||
if (segment > 0 && segment <= this->segment_count && !(this->active & mask))
|
||||
{
|
||||
/* TODO: fix checkin of inexisting IKE_SA in manager */
|
||||
/* TODO: do not activate SAs not in state CONNECTING */
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
this->active |= mask;
|
||||
|
||||
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()
|
||||
{
|
||||
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.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_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->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;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,14 @@ struct ha_sync_cache_t {
|
||||
*
|
||||
* @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.
|
||||
|
||||
@@ -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_dispatcher.h"
|
||||
#include "ha_sync_cache.h"
|
||||
#include "ha_sync_ctl.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <config/child_cfg.h>
|
||||
@@ -61,6 +62,11 @@ struct private_ha_sync_plugin_t {
|
||||
* Local cache of a nodes synced SAs
|
||||
*/
|
||||
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->child->destroy(this->child);
|
||||
this->dispatcher->destroy(this->dispatcher);
|
||||
this->ctl->destroy(this->ctl);
|
||||
this->cache->destroy(this->cache);
|
||||
this->socket->destroy(this->socket);
|
||||
free(this);
|
||||
@@ -94,6 +101,7 @@ plugin_t *plugin_create()
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user