summaryrefslogtreecommitdiff
path: root/src/libhydra/plugins/resolve/resolve_handler.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
committerYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
commitb34738ed08c2227300d554b139e2495ca5da97d6 (patch)
tree62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libhydra/plugins/resolve/resolve_handler.c
parent0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff)
downloadvyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz
vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libhydra/plugins/resolve/resolve_handler.c')
-rw-r--r--src/libhydra/plugins/resolve/resolve_handler.c245
1 files changed, 172 insertions, 73 deletions
diff --git a/src/libhydra/plugins/resolve/resolve_handler.c b/src/libhydra/plugins/resolve/resolve_handler.c
index feb2fd05a..011ebbaaf 100644
--- a/src/libhydra/plugins/resolve/resolve_handler.c
+++ b/src/libhydra/plugins/resolve/resolve_handler.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -15,12 +16,20 @@
#include "resolve_handler.h"
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <hydra.h>
#include <debug.h>
#include <threading/mutex.h>
+/* path to resolvconf executable */
+#define RESOLVCONF_EXEC "/sbin/resolvconf"
+
+/* default prefix used for resolvconf interfaces (should have high prio) */
+#define RESOLVCONF_PREFIX "lo.inet.ipsec."
+
typedef struct private_resolve_handler_t private_resolve_handler_t;
/**
@@ -39,49 +48,40 @@ struct private_resolve_handler_t {
char *file;
/**
+ * use resolvconf instead of writing directly to resolv.conf
+ */
+ bool use_resolvconf;
+
+ /**
+ * prefix to be used for interface names sent to resolvconf
+ */
+ char *iface_prefix;
+
+ /**
* Mutex to access file exclusively
*/
mutex_t *mutex;
};
/**
- * Implementation of attribute_handler_t.handle
+ * Writes the given nameserver to resolv.conf
*/
-static bool handle(private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
+static bool write_nameserver(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr)
{
FILE *in, *out;
char buf[1024];
- host_t *addr;
size_t len;
bool handled = FALSE;
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- addr = host_create_from_chunk(AF_INET, data, 0);
- break;
- case INTERNAL_IP6_DNS:
- addr = host_create_from_chunk(AF_INET6, data, 0);
- break;
- default:
- return FALSE;
- }
-
- if (!addr || addr->is_anyaddr(addr))
- {
- DESTROY_IF(addr);
- return FALSE;
- }
- this->mutex->lock(this->mutex);
-
in = fopen(this->file, "r");
/* allows us to stream from in to out */
unlink(this->file);
out = fopen(this->file, "w");
if (out)
{
- fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server);
+ fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr,
+ server);
DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
handled = TRUE;
@@ -99,40 +99,17 @@ static bool handle(private_resolve_handler_t *this, identification_t *server,
{
fclose(in);
}
- this->mutex->unlock(this->mutex);
- addr->destroy(addr);
-
- if (!handled)
- {
- DBG1(DBG_IKE, "adding DNS server failed", this->file);
- }
return handled;
}
/**
- * Implementation of attribute_handler_t.release
+ * Removes the given nameserver from resolv.conf
*/
-static void release(private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
+static void remove_nameserver(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr)
{
FILE *in, *out;
char line[1024], matcher[512];
- host_t *addr;
- int family;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- family = AF_INET;
- break;
- case INTERNAL_IP6_DNS:
- family = AF_INET6;
- break;
- default:
- return;
- }
-
- this->mutex->lock(this->mutex);
in = fopen(this->file, "r");
if (in)
@@ -142,7 +119,6 @@ static void release(private_resolve_handler_t *this, identification_t *server,
out = fopen(this->file, "w");
if (out)
{
- addr = host_create_from_chunk(family, data, 0);
snprintf(matcher, sizeof(matcher),
"nameserver %H # by strongSwan, from %Y\n",
addr, server);
@@ -160,13 +136,129 @@ static void release(private_resolve_handler_t *this, identification_t *server,
fputs(line, out);
}
}
- addr->destroy(addr);
fclose(out);
}
fclose(in);
}
+}
+/**
+ * Add or remove the given nameserver by invoking resolvconf.
+ */
+static bool invoke_resolvconf(private_resolve_handler_t *this,
+ identification_t *server, host_t *addr,
+ bool install)
+{
+ char cmd[128];
+
+ /* we use the nameserver's IP address as part of the interface name to
+ * make them unique */
+ if (snprintf(cmd, sizeof(cmd), "%s %s %s%H", RESOLVCONF_EXEC,
+ install ? "-a" : "-d", this->iface_prefix, addr) >= sizeof(cmd))
+ {
+ return FALSE;
+ }
+
+ if (install)
+ {
+ FILE *out;
+
+ out = popen(cmd, "w");
+ if (!out)
+ {
+ return FALSE;
+ }
+ DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
+ fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr,
+ server);
+ if (ferror(out) || pclose(out))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ ignore_result(system(cmd));
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ host_t *addr;
+ bool handled;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ addr = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ addr = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!addr || addr->is_anyaddr(addr))
+ {
+ DESTROY_IF(addr);
+ return FALSE;
+ }
+
+ this->mutex->lock(this->mutex);
+ if (this->use_resolvconf)
+ {
+ handled = invoke_resolvconf(this, server, addr, TRUE);
+ }
+ else
+ {
+ handled = write_nameserver(this, server, addr);
+ }
this->mutex->unlock(this->mutex);
+ addr->destroy(addr);
+
+ if (!handled)
+ {
+ DBG1(DBG_IKE, "adding DNS server failed");
+ }
+ return handled;
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_resolve_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ host_t *addr;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+ addr = host_create_from_chunk(family, data, 0);
+
+ this->mutex->lock(this->mutex);
+ if (this->use_resolvconf)
+ {
+ invoke_resolvconf(this, server, addr, FALSE);
+ }
+ else
+ {
+ remove_nameserver(this, server, addr);
+ }
+ this->mutex->unlock(this->mutex);
+
+ addr->destroy(addr);
}
/**
@@ -179,11 +271,9 @@ typedef struct {
host_t *vip;
} attribute_enumerator_t;
-/**
- * Implementation of create_attribute_enumerator().enumerate()
- */
static bool attribute_enumerate(attribute_enumerator_t *this,
- configuration_attribute_type_t *type, chunk_t *data)
+ configuration_attribute_type_t *type,
+ chunk_t *data)
{
switch (this->vip->get_family(this->vip))
{
@@ -202,11 +292,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
return TRUE;
}
-/**
- * Implementation of attribute_handler_t.create_attribute_enumerator
- */
-static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this,
- identification_t *server, host_t *vip)
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_resolve_handler_t *this, identification_t *server, host_t *vip)
{
if (vip)
{
@@ -222,10 +309,8 @@ static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this
return enumerator_create_empty();
}
-/**
- * Implementation of resolve_handler_t.destroy.
- */
-static void destroy(private_resolve_handler_t *this)
+METHOD(resolve_handler_t, destroy, void,
+ private_resolve_handler_t *this)
{
this->mutex->destroy(this->mutex);
free(this);
@@ -236,16 +321,30 @@ static void destroy(private_resolve_handler_t *this)
*/
resolve_handler_t *resolve_handler_create()
{
- private_resolve_handler_t *this = malloc_thing(private_resolve_handler_t);
+ private_resolve_handler_t *this;
+ struct stat st;
- this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
- this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
- this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
- this->public.destroy = (void(*)(resolve_handler_t*))destroy;
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .destroy = _destroy,
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .file = lib->settings->get_str(lib->settings, "%s.plugins.resolve.file",
+ RESOLV_CONF, hydra->daemon),
+ );
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
- this->file = lib->settings->get_str(lib->settings,
- "%s.plugins.resolve.file", RESOLV_CONF, hydra->daemon);
+ if (stat(RESOLVCONF_EXEC, &st) == 0)
+ {
+ this->use_resolvconf = TRUE;
+ this->iface_prefix = lib->settings->get_str(lib->settings,
+ "%s.plugins.resolve.resolvconf.iface_prefix",
+ RESOLVCONF_PREFIX, hydra->daemon);
+ }
return &this->public;
}