summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/ha
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-10-22 11:43:58 +0200
committerYves-Alexis Perez <corsac@debian.org>2015-10-22 11:43:58 +0200
commit5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (patch)
tree037f1ec5bb860846938ddcf29771c24e9c529be0 /src/libcharon/plugins/ha
parentb238cf34df3fe4476ae6b7012e7cb3e9769d4d51 (diff)
downloadvyos-strongswan-5dca9ea0e2931f0e2a056c7964d311bcc30a01b8.tar.gz
vyos-strongswan-5dca9ea0e2931f0e2a056c7964d311bcc30a01b8.zip
Imported Upstream version 5.3.3
Diffstat (limited to 'src/libcharon/plugins/ha')
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c85
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c12
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c1
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c21
4 files changed, 103 insertions, 16 deletions
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
index a95499742..54302e852 100644
--- a/src/libcharon/plugins/ha/ha_ctl.c
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -51,6 +52,41 @@ struct private_ha_ctl_t {
};
/**
+ * Change the permissions of the control FIFO, returns TRUE on success
+ */
+static bool change_fifo_permissions()
+{
+ if (chown(HA_FIFO, lib->caps->get_uid(lib->caps),
+ lib->caps->get_gid(lib->caps)) != 0)
+ {
+ DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Deletes and creates the control FIFO, returns TRUE on success
+ */
+static bool recreate_fifo()
+{
+ mode_t old;
+ bool success = TRUE;
+
+ unlink(HA_FIFO);
+ old = umask(S_IRWXO);
+ if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
+ {
+ DBG1(DBG_CFG, "creating HA FIFO %s failed: %s", HA_FIFO,
+ strerror(errno));
+ success = FALSE;
+ }
+ umask(old);
+ return success && change_fifo_permissions();
+}
+
+/**
* FIFO dispatching function
*/
static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
@@ -59,13 +95,26 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
bool oldstate;
char buf[8];
u_int segment;
+ struct stat sb;
oldstate = thread_cancelability(TRUE);
fifo = open(HA_FIFO, O_RDONLY);
thread_cancelability(oldstate);
- if (fifo == -1)
+ if (fifo == -1 || fstat(fifo, &sb) != 0 || !S_ISFIFO(sb.st_mode))
{
- DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno));
+ if (fifo == -1 && errno != ENOENT)
+ {
+ DBG1(DBG_CFG, "opening HA FIFO failed: %s", strerror(errno));
+ }
+ else
+ {
+ DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ if (fifo != -1)
+ {
+ close(fifo);
+ }
sleep(1);
return JOB_REQUEUE_FAIR;
}
@@ -100,6 +149,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
METHOD(ha_ctl_t, destroy, void,
private_ha_ctl_t *this)
{
+ unlink(HA_FIFO);
free(this);
}
@@ -109,7 +159,7 @@ METHOD(ha_ctl_t, destroy, void,
ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
{
private_ha_ctl_t *this;
- mode_t old;
+ struct stat sb;
INIT(this,
.public = {
@@ -119,20 +169,30 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
.cache = cache,
);
- if (access(HA_FIFO, R_OK|W_OK) != 0)
+ if (stat(HA_FIFO, &sb) == 0)
{
- old = umask(S_IRWXO);
- if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
+ if (!S_ISFIFO(sb.st_mode))
{
- DBG1(DBG_CFG, "creating HA FIFO %s failed: %s",
- HA_FIFO, strerror(errno));
+ DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ else if (access(HA_FIFO, R_OK|W_OK) != 0)
+ {
+ DBG1(DBG_CFG, "accessing HA FIFO %s denied, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ else
+ {
+ change_fifo_permissions();
}
- umask(old);
}
- if (chown(HA_FIFO, lib->caps->get_uid(lib->caps),
- lib->caps->get_gid(lib->caps)) != 0)
+ else if (errno == ENOENT)
{
- DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
+ recreate_fifo();
+ }
+ else
+ {
+ DBG1(DBG_CFG, "accessing HA FIFO %s failed: %s", HA_FIFO,
strerror(errno));
}
@@ -141,4 +201,3 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
-
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 31eeb934e..afa099309 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -135,6 +135,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
chunk_t secret = chunk_empty, old_skd = chunk_empty;
chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
+ host_t *other = NULL;
bool ok = FALSE;
enumerator = message->create_attribute_enumerator(message);
@@ -150,6 +151,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
value.ike_sa_id);
break;
+ case HA_REMOTE_ADDR:
+ other = value.host->clone(value.host);
+ break;
case HA_IKE_VERSION:
version = value.u8;
break;
@@ -252,6 +256,11 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
charon->ike_sa_manager, old_sa);
old_sa = NULL;
}
+ if (other)
+ {
+ ike_sa->set_other_host(ike_sa, other);
+ other = NULL;
+ }
ike_sa->set_state(ike_sa, IKE_CONNECTING);
ike_sa->set_proposal(ike_sa, proposal);
this->cache->cache(this->cache, ike_sa, message);
@@ -270,6 +279,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(other);
DESTROY_IF(message);
}
@@ -637,7 +647,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
u_int32_t inbound_spi = 0, outbound_spi = 0;
u_int16_t inbound_cpi = 0, outbound_cpi = 0;
u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
- u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ u_int16_t encr = 0, integ = 0, len = 0;
u_int16_t esn = NO_EXT_SEQ_NUMBERS;
u_int seg_i, seg_o;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index 6b4b53c9c..7492dd06e 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -138,6 +138,7 @@ METHOD(listener_t, ike_keys, bool,
m->add_attribute(m, HA_PSK, shared->get_key(shared));
}
}
+ m->add_attribute(m, HA_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
this->socket->push(this->socket, m);
this->cache->cache(this->cache, ike_sa, m);
diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c
index eed89e0bf..bd43dc351 100644
--- a/src/libcharon/plugins/ha/ha_kernel.c
+++ b/src/libcharon/plugins/ha/ha_kernel.c
@@ -36,6 +36,8 @@ typedef enum {
JHASH_LOOKUP2,
/* new variant, http://burtleburtle.net/bob/c/lookup3.c, since 2.6.37 */
JHASH_LOOKUP3,
+ /* variant with different init values, since 4.1 */
+ JHASH_LOOKUP3_1,
} jhash_version_t;
typedef struct private_ha_kernel_t private_ha_kernel_t;
@@ -88,8 +90,15 @@ static jhash_version_t get_jhash_version()
}
/* FALL */
case 2:
- DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash", a, b);
- return JHASH_LOOKUP3;
+ if (a < 4 || (a == 4 && b == 0))
+ {
+ DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash",
+ a, b);
+ return JHASH_LOOKUP3;
+ }
+ DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash with "
+ "updated init values", a, b);
+ return JHASH_LOOKUP3_1;
default:
break;
}
@@ -126,6 +135,14 @@ static u_int32_t jhash(jhash_version_t version, u_int32_t a, u_int32_t b)
b -= c; b -= a; b ^= (a << 10);
c -= a; c -= b; c ^= (b >> 15);
break;
+ case JHASH_LOOKUP3_1:
+ /* changed with 4.1: # of 32-bit words shifted by 2 and c is
+ * initialized. we only use the two word variant with SPIs, so it's
+ * unlikely that b is 0 in that case */
+ c += ((b ? 2 : 1) << 2) + 0xdeadbeef;
+ a += ((b ? 2 : 1) << 2);
+ b += ((b ? 2 : 1) << 2);
+ /* FALL */
case JHASH_LOOKUP3:
a += 0xdeadbeef;
b += 0xdeadbeef;