Skip to content

Commit 17fd304

Browse files
committedDec 19, 2022
resolve: Don't install individual servers via resolvconf
The resolvconf implementation provided by systemd via resolvectl strips everything after the interface name, so each additional server that's installed replaces the previous one. And even for other resolvconf implementations installing them individually doesn't seem necessary as we track and refcount them anyway. Closes strongswan#1353
1 parent bd6014a commit 17fd304

File tree

2 files changed

+50
-56
lines changed

2 files changed

+50
-56
lines changed
 

‎conf/plugins/resolve.opt

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
charon.plugins.resolve.file = /etc/resolv.conf
22
File where to add DNS server entries if not using resolvconf(8).
33

4-
charon.plugins.resolve.resolvconf.iface_prefix = lo.ipsec
5-
Prefix used for interface names sent to resolvconf(8).
4+
charon.plugins.resolve.resolvconf.iface = lo.ipsec
5+
Interface name/protocol sent to resolvconf(8).
66

7-
Prefix used for interface names sent to **resolvconf**(8). The nameserver
8-
address is appended to this prefix to make it unique. The result has to be
9-
a valid interface name according to the rules defined by resolvconf. Also,
10-
it should have a high priority according to the order defined in
11-
**interface-order**(5).
7+
The interface name and protocol sent to **resolvconf**(8). This has to be a
8+
valid interface name according to the rules defined by resolvconf. Also, it
9+
should have a high priority according to the order defined in
10+
**interface-order**(5) if relevant on the system.
1211

1312
charon.plugins.resolve.resolvconf.path = /sbin/resolvconf
1413
Path/command for resolvconf(8).

‎src/libcharon/plugins/resolve/resolve_handler.c

+44-49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2012-2016 Tobias Brunner
2+
* Copyright (C) 2012-2022 Tobias Brunner
33
* Copyright (C) 2009 Martin Willi
44
*
55
* Copyright (C) secunet Security Networks AG
@@ -29,8 +29,8 @@
2929
/* path to resolvconf executable */
3030
#define RESOLVCONF_EXEC "/sbin/resolvconf"
3131

32-
/* default prefix used for resolvconf interfaces (should have high prio) */
33-
#define RESOLVCONF_PREFIX "lo.ipsec"
32+
/* default interface/protocol used for resolvconf (should have high prio) */
33+
#define RESOLVCONF_IFACE "lo.ipsec"
3434

3535
typedef struct private_resolve_handler_t private_resolve_handler_t;
3636

@@ -55,9 +55,9 @@ struct private_resolve_handler_t {
5555
char *resolvconf;
5656

5757
/**
58-
* Prefix to be used for interface names sent to resolvconf
58+
* Interface name sent to resolvconf
5959
*/
60-
char *iface_prefix;
60+
char *iface;
6161

6262
/**
6363
* Mutex to access file exclusively
@@ -184,39 +184,33 @@ static void remove_nameserver(private_resolve_handler_t *this, host_t *addr)
184184
}
185185

186186
/**
187-
* Add or remove the given nameserver by invoking resolvconf.
187+
* Install the given nameservers by invoking resolvconf. If the array is empty,
188+
* remove the config.
188189
*/
189-
static bool invoke_resolvconf(private_resolve_handler_t *this, host_t *addr,
190-
bool install)
190+
static bool invoke_resolvconf(private_resolve_handler_t *this, array_t *servers)
191191
{
192192
process_t *process;
193+
dns_server_t *dns;
193194
FILE *shell;
194-
char buf[BUF_LEN];
195-
int in, out, retval;
196-
197-
if (snprintf(buf, sizeof(buf), "%H", addr) >= sizeof(buf))
198-
{
199-
return FALSE;
200-
}
201-
translate(buf, ".:", "__");
202-
203-
/* we use the nameserver's IP address as part of the interface name to
204-
* make them unique */
205-
process = process_start_shell(NULL, install ? &in : NULL, &out, NULL,
206-
"2>&1 %s %s %s%s", this->resolvconf,
207-
install ? "-a" : "-d", this->iface_prefix, buf);
195+
int in, out, retval, i;
208196

197+
process = process_start_shell(NULL, array_count(servers) ? &in : NULL, &out,
198+
NULL, "2>&1 %s %s %s", this->resolvconf,
199+
array_count(servers) ? "-a" : "-d", this->iface);
209200
if (!process)
210201
{
211202
return FALSE;
212203
}
213-
if (install)
204+
if (array_count(servers))
214205
{
215206
shell = fdopen(in, "w");
216207
if (shell)
217208
{
218-
DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
219-
fprintf(shell, "nameserver %H\n", addr);
209+
for (i = 0; i < array_count(servers); i++)
210+
{
211+
array_get(servers, i, &dns);
212+
fprintf(shell, "nameserver %H\n", dns->server);
213+
}
220214
fclose(shell);
221215
}
222216
else
@@ -229,7 +223,7 @@ static bool invoke_resolvconf(private_resolve_handler_t *this, host_t *addr,
229223
}
230224
else
231225
{
232-
DBG1(DBG_IKE, "removing DNS server %H via resolvconf", addr);
226+
DBG1(DBG_IKE, "removing DNS servers via resolvconf");
233227
}
234228
shell = fdopen(out, "r");
235229
if (shell)
@@ -262,15 +256,7 @@ static bool invoke_resolvconf(private_resolve_handler_t *this, host_t *addr,
262256
{
263257
close(out);
264258
}
265-
if (!process->wait(process, &retval) || retval != EXIT_SUCCESS)
266-
{
267-
if (install)
268-
{ /* revert changes when installing fails */
269-
invoke_resolvconf(this, addr, FALSE);
270-
return FALSE;
271-
}
272-
}
273-
return TRUE;
259+
return process->wait(process, &retval) && retval == EXIT_SUCCESS;
274260
}
275261

276262
METHOD(attribute_handler_t, handle, bool,
@@ -302,22 +288,27 @@ METHOD(attribute_handler_t, handle, bool,
302288
this->mutex->lock(this->mutex);
303289
if (array_bsearch(this->servers, addr, dns_server_find, &found) == -1)
304290
{
291+
INIT(found,
292+
.server = addr->clone(addr),
293+
.refcount = 1,
294+
);
295+
array_insert_create(&this->servers, ARRAY_TAIL, found);
296+
array_sort(this->servers, dns_server_sort, NULL);
297+
305298
if (this->resolvconf)
306299
{
307-
handled = invoke_resolvconf(this, addr, TRUE);
300+
DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr);
301+
handled = invoke_resolvconf(this, this->servers);
308302
}
309303
else
310304
{
311305
handled = write_nameserver(this, addr);
312306
}
313-
if (handled)
307+
if (!handled)
314308
{
315-
INIT(found,
316-
.server = addr->clone(addr),
317-
.refcount = 1,
318-
);
319-
array_insert_create(&this->servers, ARRAY_TAIL, found);
320-
array_sort(this->servers, dns_server_sort, NULL);
309+
array_remove(this->servers, ARRAY_TAIL, NULL);
310+
found->server->destroy(found->server);
311+
free(found);
321312
}
322313
}
323314
else
@@ -369,17 +360,19 @@ METHOD(attribute_handler_t, release, void,
369360
}
370361
else
371362
{
363+
array_remove(this->servers, idx, NULL);
364+
found->server->destroy(found->server);
365+
free(found);
366+
372367
if (this->resolvconf)
373368
{
374-
invoke_resolvconf(this, addr, FALSE);
369+
DBG1(DBG_IKE, "removing DNS server %H via resolvconf", addr);
370+
invoke_resolvconf(this, this->servers);
375371
}
376372
else
377373
{
378374
remove_nameserver(this, addr);
379375
}
380-
array_remove(this->servers, idx, NULL);
381-
found->server->destroy(found->server);
382-
free(found);
383376
}
384377
}
385378
this->mutex->unlock(this->mutex);
@@ -495,9 +488,11 @@ resolve_handler_t *resolve_handler_create()
495488
.resolvconf = lib->settings->get_str(lib->settings,
496489
"%s.plugins.resolve.resolvconf.path",
497490
NULL, lib->ns),
498-
.iface_prefix = lib->settings->get_str(lib->settings,
491+
.iface = lib->settings->get_str(lib->settings,
492+
"%s.plugins.resolve.resolvconf.iface",
493+
lib->settings->get_str(lib->settings,
499494
"%s.plugins.resolve.resolvconf.iface_prefix",
500-
RESOLVCONF_PREFIX, lib->ns),
495+
RESOLVCONF_IFACE, lib->ns), lib->ns),
501496
);
502497

503498
if (!this->resolvconf && stat(RESOLVCONF_EXEC, &st) == 0)

0 commit comments

Comments
 (0)