/*
- * Copyright (C) 2012-2016 Tobias Brunner
+ * Copyright (C) 2012-2022 Tobias Brunner
* Copyright (C) 2009 Martin Willi
*
* Copyright (C) secunet Security Networks AG
/* path to resolvconf executable */
#define RESOLVCONF_EXEC "/sbin/resolvconf"
-/* default prefix used for resolvconf interfaces (should have high prio) */
-#define RESOLVCONF_PREFIX "lo.ipsec"
+/* default interface/protocol used for resolvconf (should have high prio) */
+#define RESOLVCONF_IFACE "lo.ipsec"
typedef struct private_resolve_handler_t private_resolve_handler_t;
char *resolvconf;
/**
- * Prefix to be used for interface names sent to resolvconf
+ * Interface name sent to resolvconf
*/
- char *iface_prefix;
+ char *iface;
/**
* Mutex to access file exclusively
}
/**
- * Add or remove the given nameserver by invoking resolvconf.
+ * Install the given nameservers by invoking resolvconf. If the array is empty,
+ * remove the config.
*/
-static bool invoke_resolvconf(private_resolve_handler_t *this, host_t *addr,
- bool install)
+static bool invoke_resolvconf(private_resolve_handler_t *this, array_t *servers)
{
process_t *process;
+ dns_server_t *dns;
FILE *shell;
- char buf[BUF_LEN];
- int in, out, retval;
-
- if (snprintf(buf, sizeof(buf), "%H", addr) >= sizeof(buf))
- {
- return FALSE;
- }
- translate(buf, ".:", "__");
-
- /* we use the nameserver's IP address as part of the interface name to
- * make them unique */
- process = process_start_shell(NULL, install ? &in : NULL, &out, NULL,
- "2>&1 %s %s %s%s", this->resolvconf,
- install ? "-a" : "-d", this->iface_prefix, buf);
+ int in, out, retval, i;
+ process = process_start_shell(NULL, array_count(servers) ? &in : NULL, &out,
+ NULL, "2>&1 %s %s %s", this->resolvconf,
+ array_count(servers) ? "-a" : "-d", this->iface);
if (!process)
{
return FALSE;
}
- if (install)
+ if (array_count(servers))
{
shell = fdopen(in, "w");
if (shell)
{
- DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
- fprintf(shell, "nameserver %H\n", addr);
+ for (i = 0; i < array_count(servers); i++)
+ {
+ array_get(servers, i, &dns);
+ fprintf(shell, "nameserver %H\n", dns->server);
+ }
fclose(shell);
}
else
}
else
{
- DBG1(DBG_IKE, "removing DNS server %H via resolvconf", addr);
+ DBG1(DBG_IKE, "removing DNS servers via resolvconf");
}
shell = fdopen(out, "r");
if (shell)
{
close(out);
}
- if (!process->wait(process, &retval) || retval != EXIT_SUCCESS)
- {
- if (install)
- { /* revert changes when installing fails */
- invoke_resolvconf(this, addr, FALSE);
- return FALSE;
- }
- }
- return TRUE;
+ return process->wait(process, &retval) && retval == EXIT_SUCCESS;
}
METHOD(attribute_handler_t, handle, bool,
this->mutex->lock(this->mutex);
if (array_bsearch(this->servers, addr, dns_server_find, &found) == -1)
{
+ INIT(found,
+ .server = addr->clone(addr),
+ .refcount = 1,
+ );
+ array_insert_create(&this->servers, ARRAY_TAIL, found);
+ array_sort(this->servers, dns_server_sort, NULL);
+
if (this->resolvconf)
{
- handled = invoke_resolvconf(this, addr, TRUE);
+ DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
+ handled = invoke_resolvconf(this, this->servers);
}
else
{
handled = write_nameserver(this, addr);
}
- if (handled)
+ if (!handled)
{
- INIT(found,
- .server = addr->clone(addr),
- .refcount = 1,
- );
- array_insert_create(&this->servers, ARRAY_TAIL, found);
- array_sort(this->servers, dns_server_sort, NULL);
+ array_remove(this->servers, ARRAY_TAIL, NULL);
+ found->server->destroy(found->server);
+ free(found);
}
}
else
}
else
{
+ array_remove(this->servers, idx, NULL);
+ found->server->destroy(found->server);
+ free(found);
+
if (this->resolvconf)
{
- invoke_resolvconf(this, addr, FALSE);
+ DBG1(DBG_IKE, "removing DNS server %H via resolvconf", addr);
+ invoke_resolvconf(this, this->servers);
}
else
{
remove_nameserver(this, addr);
}
- array_remove(this->servers, idx, NULL);
- found->server->destroy(found->server);
- free(found);
}
}
this->mutex->unlock(this->mutex);
.resolvconf = lib->settings->get_str(lib->settings,
"%s.plugins.resolve.resolvconf.path",
NULL, lib->ns),
- .iface_prefix = lib->settings->get_str(lib->settings,
+ .iface = lib->settings->get_str(lib->settings,
+ "%s.plugins.resolve.resolvconf.iface",
+ lib->settings->get_str(lib->settings,
"%s.plugins.resolve.resolvconf.iface_prefix",
- RESOLVCONF_PREFIX, lib->ns),
+ RESOLVCONF_IFACE, lib->ns), lib->ns),
);
if (!this->resolvconf && stat(RESOLVCONF_EXEC, &st) == 0)