mech: add support for ietf-syste:system/dns-resolver

This commit adds multi-nameserver support using openresolv (resolvconf)
and dnsmasq.  This means that a DHCP client (dhcpcd) or VPN client can
be providers of nameservers to the system.  Dnsmasq takes over as the
system resolver, except when the user has set up static configuration.

Static nameserver(s), as well as search and options, are always added
first by openresolv to /etc/resolv.conf.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2023-03-27 14:05:03 +02:00
parent a5258d7102
commit aec2514eae
11 changed files with 155 additions and 3 deletions
+14
View File
@@ -0,0 +1,14 @@
# dnsmasq is the system resolver, the file /etc/resolv.conf is
# managed by openresolv. DHCP lease, VPN tunnel establishment,
# and similar events feed servers and configuration to dnsmasq.
domain-needed
#interface=lo
listen-address=127.0.0.1
enable-dbus
# Generated by openresolv
resolv-file=/var/lib/misc/resolv.conf
# Include all files in a directory which end in .conf
conf-dir=/etc/dnsmasq.d/,*.conf
+10
View File
@@ -0,0 +1,10 @@
# dnsmasq is the system resolver
name_servers="127.0.0.1"
resolv_conf=/etc/resolv.conf
resolv_conf_options="edns0 trust-ad"
# dnsmasq specific settings and list of
# nameservers in non-standard locations
dnsmasq_conf=/etc/dnsmasq.d/resolvconf.conf
dnsmasq_resolv=/var/lib/misc/resolv.conf
@@ -0,0 +1 @@
lo
+1 -1
View File
@@ -7,7 +7,7 @@
# ... except for some core services
reserved()
{
for svc in clixon getty lldpd nginx sysklogd; do
for svc in clixon dnsmasq getty lldpd nginx sysklogd; do
[ "$1" = "${svc}.conf" ] && return 0
done
+1
View File
@@ -5,3 +5,4 @@ run if:<boot/netconf> name:clixon :boot log:prio:daemon.warning \
service if:<boot/netconf> name:clixon log:prio:daemon.warning \
[12345789] clixon_backend -F -l s -D 7 -s none -- Configuration daemon
task if:<boot/netconf> [12345789] resolvconf -u -- Update DNS configuration
+2 -1
View File
@@ -1 +1,2 @@
d /run/clixon - - -
d /run/clixon - - -
d /run/resolvconf/interfaces - - -
@@ -1 +1 @@
service [2345] dnsmasq -k -- DHCP/DNS proxy
service [S12345789] dnsmasq -k -u root -- DHCP/DNS proxy
@@ -0,0 +1,12 @@
diff -ru openresolv-3.12.0.orig/resolvconf.in openresolv-3.12.0/resolvconf.in
--- openresolv-3.12.0.orig/resolvconf.in 2020-12-27 19:05:10.000000000 +0100
+++ openresolv-3.12.0/resolvconf.in 2023-03-27 00:19:03.365164029 +0200
@@ -315,6 +315,8 @@
then
/usr/bin/systemctl restart $1.service
fi'
+ elif [ -x /sbin/initctl ]; then
+ RESTARTCMD="/sbin/initctl -bnq restart \$1"
elif [ -x /sbin/rc-service ] &&
{ [ -s /libexec/rc/init.d/softlevel ] ||
[ -s /run/openrc/softlevel ]; }
@@ -0,0 +1,16 @@
diff -ru openresolv-3.12.0.orig/resolvconf.in openresolv-3.12.0/resolvconf.in
--- openresolv-3.12.0.orig/resolvconf.in 2020-12-27 19:05:10.000000000 +0100
+++ openresolv-3.12.0/resolvconf.in 2023-03-27 00:19:03.365164029 +0200
@@ -315,6 +315,12 @@
then
/usr/bin/systemctl restart $1.service
fi'
+ elif [ -x /sbin/initctl ]; then
+ # Finit
+ RESTARTCMD='
+ if /sbin/initctl -bq status $1; then
+ /sbin/initctl -bnq restart $1
+ fi'
elif [ -x /sbin/rc-service ] &&
{ [ -s /libexec/rc/init.d/softlevel ] ||
[ -s /run/openrc/softlevel ]; }
+97
View File
@@ -89,6 +89,20 @@ static bool is_true(cxobj *xp, char *name)
return false;
}
static char *get_str(cxobj *xp, char *name)
{
cxobj *obj;
if (!xp || !name)
return NULL;
obj = xml_find(xp, name);
if (obj)
return xml_body(obj);
return NULL;
}
static int sys_reload_services(void)
{
return run("initctl -nbq touch sysklogd lldpd");
@@ -244,6 +258,83 @@ disable:
return run("initctl -nbq disable chronyd");
}
/*
* dnsmasq is the resolver, it gets its nameservers from various
* sources: static, dhcp, vpn, via the resolvconf wrapper.
*/
int ietf_sys_tr_commit_dns(cxobj *src, cxobj *tgt)
{
const char *fn = "/etc/resolv.conf.head";
cxobj *obj, *opt = NULL, *srv = NULL;
int first = 1, valid = 0;
FILE *fp;
clicon_log(LOG_ERR, "ietf-system: dns src %p tgt %p", src, tgt);
if (!tgt)
goto disable;
fp = fopen(fn, "w");
if (!fp) {
clicon_log(LOG_WARNING, "ietf-system: failed updating %s: %s", fn, strerror(errno));
return -1;
}
obj = xml_find(tgt, "options");
if (obj) {
char *str;
fprintf(fp, "options");
str = get_str(obj, "timeout");
if (str)
fprintf(fp, " timeout:%s", str);
str = get_str(obj, "attempts");
if (str)
fprintf(fp, " attempts:%s ", str);
fprintf(fp, "\n");
}
while ((opt = xml_child_each(tgt, opt, CX_ELMNT))) {
if (strcmp(xml_name(opt), "search"))
continue;
if (first) {
fprintf(fp, "search ");
first = 0;
}
fprintf(fp, "%s ", xml_body(opt));
}
if (!first)
fprintf(fp, "\n");
while ((srv = xml_child_each(tgt, srv, CX_ELMNT))) {
cxobj *tmp;
if (strcmp(xml_name(srv), "server"))
continue;
tmp = xml_find(srv, "udp-and-tcp");
if (tmp) {
obj = xml_find(tmp, "address");
if (obj) {
fprintf(fp, "nameserver %s\n", xml_body(obj));
valid++;
}
}
}
fclose(fp);
disable:
if (!valid)
remove(fn);
if (run("initctl cond get hook/sys/up")) {
clicon_log(LOG_ERR, "ietf-system: failed cond get hook/sys/up");
return 0;
}
clicon_log(LOG_ERR, "ietf-status: calling resolvconf -u");
return run("resolvconf -u");
}
int ietf_sys_tr_commit(clicon_handle h, transaction_data td)
{
cxobj *src = transaction_src(td), *tgt = transaction_target(td);
@@ -270,10 +361,16 @@ int ietf_sys_tr_commit(clicon_handle h, transaction_data td)
tlen ? xml_find(tsys[0], "clock") : NULL);
if (err)
goto err;
err = ietf_sys_tr_commit_ntp(slen ? xml_find(ssys[0], "ntp") : NULL,
tlen ? xml_find(tsys[0], "ntp") : NULL);
if (err)
goto err;
err = ietf_sys_tr_commit_dns(slen ? xml_find(ssys[0], "dns-resolver") : NULL,
tlen ? xml_find(tsys[0], "dns-resolver") : NULL);
if (err)
goto err;
err:
err = err ? : aug_save(aug);
return err;