resolve: Maintain order of DNS servers also when installing in resolv.conf

This always writes the complete set of DNS servers to make modifications
simpler.
This commit is contained in:
Tobias Brunner 2023-06-16 13:46:17 +02:00
parent 6440975bb4
commit 8238ad480a

View File

@ -32,6 +32,9 @@
/* default interface/protocol used for resolvconf (should have high prio) */ /* default interface/protocol used for resolvconf (should have high prio) */
#define RESOLVCONF_IFACE "lo.ipsec" #define RESOLVCONF_IFACE "lo.ipsec"
/* suffix added to lines in resolv.conf */
#define RESOLV_CONF_SUFFIX " # by strongSwan"
typedef struct private_resolve_handler_t private_resolve_handler_t; typedef struct private_resolve_handler_t private_resolve_handler_t;
/** /**
@ -106,13 +109,15 @@ static bool dns_server_equals(const void *a, const void *b)
} }
/** /**
* Writes the given nameserver to resolv.conf * Writes the given nameservers to resolv.conf
*/ */
static bool write_nameserver(private_resolve_handler_t *this, host_t *addr) static bool write_nameservers(private_resolve_handler_t *this,
hashtable_t *servers)
{ {
FILE *in, *out; FILE *in, *out;
char buf[1024]; enumerator_t *enumerator;
size_t len; dns_server_t *dns;
char line[1024];
bool handled = FALSE; bool handled = FALSE;
in = fopen(this->file, "r"); in = fopen(this->file, "r");
@ -121,18 +126,28 @@ static bool write_nameserver(private_resolve_handler_t *this, host_t *addr)
out = fopen(this->file, "w"); out = fopen(this->file, "w");
if (out) if (out)
{ {
fprintf(out, "nameserver %H # by strongSwan\n", addr); /* write our current set of servers */
DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file); enumerator = servers->create_enumerator(servers);
handled = TRUE; while (enumerator->enumerate(enumerator, NULL, &dns))
{
fprintf(out, "nameserver %H" RESOLV_CONF_SUFFIX "\n", dns->server);
}
enumerator->destroy(enumerator);
/* copy rest of the file */
if (in) if (in)
{ {
while ((len = fread(buf, 1, sizeof(buf), in))) /* copy the rest of the file, except our previous servers */
while (fgets(line, sizeof(line), in))
{ {
ignore_result(fwrite(buf, 1, len, out)); if (!strstr(line, RESOLV_CONF_SUFFIX "\n"))
{
fputs(line, out);
}
} }
} }
handled = TRUE;
fclose(out); fclose(out);
} }
if (in) if (in)
@ -142,44 +157,6 @@ static bool write_nameserver(private_resolve_handler_t *this, host_t *addr)
return handled; return handled;
} }
/**
* Removes the given nameserver from resolv.conf
*/
static void remove_nameserver(private_resolve_handler_t *this, host_t *addr)
{
FILE *in, *out;
char line[1024], matcher[512];
in = fopen(this->file, "r");
if (in)
{
/* allows us to stream from in to out */
unlink(this->file);
out = fopen(this->file, "w");
if (out)
{
snprintf(matcher, sizeof(matcher),
"nameserver %H # by strongSwan\n", addr);
/* copy all, but matching line */
while (fgets(line, sizeof(line), in))
{
if (strpfx(line, matcher))
{
DBG1(DBG_IKE, "removing DNS server %H from %s",
addr, this->file);
}
else
{
fputs(line, out);
}
}
fclose(out);
}
fclose(in);
}
}
/** /**
* Install the given nameservers by invoking resolvconf. If the table is empty, * Install the given nameservers by invoking resolvconf. If the table is empty,
* remove the config. * remove the config.
@ -303,7 +280,8 @@ METHOD(attribute_handler_t, handle, bool,
} }
else else
{ {
handled = write_nameserver(this, addr); DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
handled = write_nameservers(this, this->servers);
} }
if (!handled) if (!handled)
{ {
@ -372,7 +350,9 @@ METHOD(attribute_handler_t, release, void,
} }
else else
{ {
remove_nameserver(this, addr); DBG1(DBG_IKE, "removing DNS server %H from %s", addr,
this->file);
write_nameservers(this, this->servers);
} }
} }
} }