Page MenuHomeFreeBSD

D56269.diff
No OneTemporary

D56269.diff

diff --git a/contrib/openresolv/LICENSE b/contrib/openresolv/LICENSE
--- a/contrib/openresolv/LICENSE
+++ b/contrib/openresolv/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2007-2019 Roy Marples <roy@marples.name>
+Copyright (c) 2007-2020 Roy Marples <roy@marples.name>
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/contrib/openresolv/Makefile b/contrib/openresolv/Makefile
--- a/contrib/openresolv/Makefile
+++ b/contrib/openresolv/Makefile
@@ -5,6 +5,9 @@
CONFIG_MK?= ${_CONFIG_MK}
include ${CONFIG_MK}
+DIST!= if test -d .git; then echo "dist-git"; \
+ else echo "dist-inst"; fi
+
SBINDIR?= /sbin
SYSCONFDIR?= /etc
LIBEXECDIR?= /libexec/resolvconf
@@ -20,9 +23,11 @@
DOCMODE?= 0644
MANMODE?= 0444
-RESOLVCONF= resolvconf resolvconf.8 resolvconf.conf.5
-SUBSCRIBERS= libc dnsmasq named pdnsd pdns_recursor unbound
-TARGET= ${RESOLVCONF} ${SUBSCRIBERS}
+RESOLVCONF= resolvconf resolvconf.8 resolvconf.conf.5
+SUBSCRIBERS= libc dnsmasq named pdnsd pdns_recursor unbound
+SUBSCRIBERS+= systemd-resolved resolvectl
+LIBC_SUBSCRIBERS= avahi-daemon mdnsd
+TARGET= ${RESOLVCONF} ${SUBSCRIBERS} ${LIBC_SUBSCRIBERS}
SRCS= ${TARGET:C,$,.in,} # pmake
SRCS:= ${TARGET:=.in} # gmake
@@ -36,12 +41,12 @@
SED_STATUSARG= -e 's:@STATUSARG@:${STATUSARG}:g'
DISTPREFIX?= ${PKG}-${VERSION}
-DISTFILEGZ?= ${DISTPREFIX}.tar.gz
DISTFILE?= ${DISTPREFIX}.tar.xz
DISTINFO= ${DISTFILE}.distinfo
-DISTINFOSIGN= ${DISTINFO}.asc
-CKSUM?= cksum -a SHA256
-PGP?= netpgp
+DISTINFOMD= ${DISTINFO}.md
+DISTSIGN= ${DISTFILE}.asc
+SHA256?= sha256
+PGP?= gpg2
GITREF?= HEAD
@@ -59,7 +64,7 @@
rm -f ${TARGET}
distclean: clean
- rm -f config.mk ${DISTFILE} ${DISTINFO} ${DISTINFOSIGN}
+ rm -f config.mk ${DISTFILE} ${DISTINFO} ${DISTINFOMD} ${DISTSIGN}
installdirs:
@@ -71,6 +76,9 @@
${INSTALL} -m ${DOCMODE} resolvconf.conf ${DESTDIR}${SYSCONFDIR}
${INSTALL} -d ${DESTDIR}${LIBEXECDIR}
${INSTALL} -m ${DOCMODE} ${SUBSCRIBERS} ${DESTDIR}${LIBEXECDIR}
+ ${INSTALL} -d ${DESTDIR}${LIBEXECDIR}/libc.d
+ ${INSTALL} -m ${DOCMODE} ${LIBC_SUBSCRIBERS} \
+ ${DESTDIR}${LIBEXECDIR}/libc.d
maninstall:
${INSTALL} -d ${DESTDIR}${MANDIR}/man8
@@ -87,18 +95,30 @@
mkdir /tmp/${DISTPREFIX}
cp -RPp * /tmp/${DISTPREFIX}
(cd /tmp/${DISTPREFIX}; make clean)
- tar -cvjpf ${DISTFILE} -C /tmp ${DISTPREFIX}
+ tar -cvJpf ${DISTFILE} -C /tmp ${DISTPREFIX}
rm -rf /tmp/${DISTPREFIX}
-dist: dist-git
+dist: ${DIST}
distinfo: dist
- rm -f ${DISTINFO} ${DISTINFOSIGN}
- ${CKSUM} ${DISTFILE} >${DISTINFO}
- #printf "SIZE (${DISTFILE}) = %s\n" $$(wc -c <${DISTFILE}) >>${DISTINFO}
- ${PGP} --clearsign --output=${DISTINFOSIGN} ${DISTINFO}
- chmod 644 ${DISTINFOSIGN}
- ls -l ${DISTFILE} ${DISTINFO} ${DISTINFOSIGN}
+ rm -f ${DISTINFO} ${DISTSIGN}
+ ${SHA256} ${DISTFILE} >${DISTINFO}
+ wc -c <${DISTFILE} \
+ | xargs printf 'Size (${DISTFILE}) = %s\n' >>${DISTINFO}
+ ${PGP} --sign --armour --detach ${DISTFILE}
+ chmod 644 ${DISTSIGN}
+ ls -l ${DISTFILE} ${DISTINFO} ${DISTSIGN}
+
+${DISTINFOMD}: ${DISTINFO}
+ echo '```' >${DISTINFOMD}
+ cat ${DISTINFO} >>${DISTINFOMD}
+ echo '```' >>${DISTINFOMD}
+
+release: distinfo ${DISTINFOMD}
+ gh release create v${VERSION} \
+ --title "openresolv ${VERSION}" --draft --generate-notes \
+ --notes-file ${DISTINFOMD} \
+ ${DISTFILE} ${DISTSIGN}
import: dist
rm -rf /tmp/${DISTPREFIX}
@@ -115,4 +135,4 @@
@${ECHO} "openresolv-${VERSION} imported to ${DESTDIR}"
import-src:
- ${MAKE} _import-src DESTDIR=`if [ -n "${DESTDIR}" ]; then echo "${DESTDIR}"; else echo /tmp/${DISTPREFIX}; fi`
+ ${MAKE} _import-src DESTDIR=`if [ -n "${DESTDIR}" ]; then echo "${DESTDIR}"; else echo /tmp/${DISTPREFIX}; fi`
diff --git a/contrib/openresolv/README.md b/contrib/openresolv/README.md
--- a/contrib/openresolv/README.md
+++ b/contrib/openresolv/README.md
@@ -37,7 +37,7 @@
The last point is quite important, especially when running VPN systems.
Take the following resolv.conf files which have been generated by a
-[DHCP client](../dhcpcd) and sent to resolvconf:
+[DHCP client](https://github.com/NetworkConfiguration/dhcpcd) and sent to resolvconf:
```
# resolv.conf from bge0
@@ -58,7 +58,12 @@
* [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html)
* [ISC BIND](http://www.isc.org/software/bind)
* [PowerDNS Recursor](http://wiki.powerdns.com/trac)
+ * [systemd-resolved](https://www.freedesktop.org/software/systemd/man/latest/systemd-resolved.service.html)
See the
-[configuration section](https://roy.marples.name/projects/openresolv/config)
+[configuration section](https://roy.marples.name/projects/openresolv/configuration)
for more details.
+
+If openresolv updates `/etc/resolv.conf` it can notify the following of this:
+ * [Bonjour (mdnsd)](https://developer.apple.com/bonjour/)
+ * [avahi](http://www.avahi.org/)
diff --git a/contrib/openresolv/pdns_recursor.in b/contrib/openresolv/avahi-daemon.in
copy from contrib/openresolv/pdns_recursor.in
copy to contrib/openresolv/avahi-daemon.in
--- a/contrib/openresolv/pdns_recursor.in
+++ b/contrib/openresolv/avahi-daemon.in
@@ -1,8 +1,8 @@
#!/bin/sh
-# Copyright (c) 2009-2019 Roy Marples
+# Copyright (c) 2007-2023 Roy Marples
# All rights reserved
-# PowerDNS Recursor subscriber for resolvconf
+# avahi-daemon notifier for resolvconf libc subscriber
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -26,50 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
-. "@SYSCONFDIR@/resolvconf.conf" || exit 1
-[ -z "$pdns_zones" ] && exit 0
-[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
-NL="
-"
-
-: ${pdns_service:=pdns-recursor}
-
-newzones=
-
-for n in $NAMESERVERS; do
- newzones="$newzones${newzones:+,}$n"
-done
-[ -n "$newzones" ] && newzones="+.=$newzones$NL"
-
-for d in $DOMAINS; do
- newns=
- ns="${d#*:}"
- while [ -n "$ns" ]; do
- newns="$newns${newns:+,}${ns%%,*}"
- [ "$ns" = "${ns#*,}" ] && break
- ns="${ns#*,}"
- done
- [ -n "$newns" ] && newzones="$newzones${d%%:*}=$newns$NL"
-done
-
-# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
- config_mkdirs "$pdnsd_zones"
-else
- @SBINDIR@/resolvconf -D "$pdnsd_zones"
-fi
-
-if [ ! -f "$pdns_zones" ] || \
- [ "$(cat "$pdns_zones")" != "$(printf %s "$newzones")" ]
-then
- printf %s "$newzones" >"$pdns_zones"
- if [ -n "$pdns_restart" ]; then
- eval $pdns_restart
- elif [ -n "$RESTARTCMD" ]; then
- set -- ${pdns_service}
- eval "$RESTARTCMD"
- else
- @SBINDIR@/resolvconf -r ${pdns_service}
- fi
+: ${avahi_daemon_pidfile:=/var/run/avahi-daemon/pid}
+if [ -s "$avahi_daemon_pidfile" ]; then
+ kill -HUP $(cat "$avahi_daemon_pidfile")
fi
diff --git a/contrib/openresolv/configure b/contrib/openresolv/configure
old mode 100644
new mode 100755
--- a/contrib/openresolv/configure
+++ b/contrib/openresolv/configure
@@ -39,7 +39,7 @@
--includedir) eval INCLUDEDIR="$INCLUDEDIR${INCLUDEDIR:+ }$var";;
--datadir|--infodir) ;; # ignore autotools
--disable-maintainer-mode|--disable-dependency-tracking) ;;
- --help) echo "See the README file for available options"; exit 0;;
+ --help) echo "See the source for available options"; exit 0;;
*) echo "$0: WARNING: unknown option $opt" >&2;;
esac
done
@@ -92,7 +92,7 @@
: ${LIBEXECDIR:=${PREFIX:-/usr}/libexec/resolvconf}
;;
linux*)
- # cksum does't support -a and netpgp is rare
+ # cksum doesn't support -a and netpgp is rare
echo "CKSUM= sha256sum --tag" >>$CONFIG_MK
echo "PGP= gpg2" >>$CONFIG_MK
;;
diff --git a/contrib/openresolv/dnsmasq.in b/contrib/openresolv/dnsmasq.in
--- a/contrib/openresolv/dnsmasq.in
+++ b/contrib/openresolv/dnsmasq.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2007-2019 Roy Marples
+# Copyright (c) 2007-2023 Roy Marples
# All rights reserved
# dnsmasq subscriber for resolvconf
@@ -105,7 +105,7 @@
empty=true
continue
fi
- i=$(($i + 1))
+ i=$((i + 1))
while [ ${#addr} -lt 4 ]; do
addr="0${addr}"
done
@@ -118,7 +118,7 @@
fi
done
while [ $i != 8 ]; do
- i=$(($i + 1))
+ i=$((i + 1))
front="$front byte:0 byte:0"
done
front="${front}$back"
@@ -151,7 +151,7 @@
fi
# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
+if command -v config_mkdirs >/dev/null 2>&1; then
config_mkdirs "$dnsmasq_conf" "$dnsmasq_resolv"
else
@SBINDIR@/resolvconf -D "$dnsmasq_conf" "$dnsmasq_resolv"
diff --git a/contrib/openresolv/libc.in b/contrib/openresolv/libc.in
--- a/contrib/openresolv/libc.in
+++ b/contrib/openresolv/libc.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2007-2019 Roy Marples
+# Copyright (c) 2007-2025 Roy Marples
# All rights reserved
# libc subscriber for resolvconf
@@ -29,10 +29,23 @@
SYSCONFDIR=@SYSCONFDIR@
LIBEXECDIR=@LIBEXECDIR@
VARDIR=@VARDIR@
-IFACEDIR="$VARDIR/interfaces"
+KEYDIR="$VARDIR/keys"
+# Compat
+if [ ! -d "$KEYDIR" ] && [ -d "$VARDIR/interfaces" ]; then
+ KEYDIR="$VARDIR/interfaces"
+fi
+
+CMD="$1"
+KEY="$2"
+
NL="
"
+warn()
+{
+ echo "${0##*/}: $*" >&2
+}
+
# sed may not be available, and this is faster on small files
key_get_value()
{
@@ -94,8 +107,12 @@
fi
fi
: ${resolv_conf:=/etc/resolv.conf}
+if [ "$resolv_conf" = "/dev/null" ]; then
+ exit 0
+fi
+: ${resolv_conf_tmp:="$resolv_conf.$$.openresolv"}
: ${libc_service:=nscd}
-: ${list_resolv:=@SBINDIR@/resolvconf -l}
+: ${list_resolv:=@SBINDIR@/resolvconf -L}
if [ "${resolv_conf_head-x}" = x ] && [ -f "$SYSCONFDIR"/resolv.conf.head ]
then
resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.head)"
@@ -105,9 +122,8 @@
resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.tail)"
fi
-backup=true
signature="# Generated by resolvconf"
-
+
uniqify()
{
result=
@@ -123,15 +139,14 @@
case "${resolv_conf_passthrough:-NO}" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
- backup=false
newest=
- for conf in "$IFACEDIR"/*; do
+ for conf in "$KEYDIR"/*; do
if [ -z "$newest" ] || [ "$conf" -nt "$newest" ]; then
newest="$conf"
fi
done
[ -z "$newest" ] && exit 0
- newconf="$(cat "$newest")$NL"
+ newconf="$signature$NL$(cat "$newest")$NL"
;;
/dev/null|[Nn][Uu][Ll][Ll])
: ${resolv_conf_local_only:=NO}
@@ -207,27 +222,44 @@
# Check if the file has actually changed or not
if [ -e "$resolv_conf" ]; then
- [ "$(cat "$resolv_conf")" = "$(printf %s "$newconf")" ] && exit 0
-fi
-
-# Change is good.
-# If the old file does not have our signature, back it up.
-# If the new file just has our signature, restore the backup.
-if $backup; then
- if [ "$newconf" = "$signature$NL" ]; then
- if [ -e "$resolv_conf.bak" ]; then
- newconf="$(cat "$resolv_conf.bak")$NL"
- fi
- elif [ -e "$resolv_conf" ]; then
- read line <"$resolv_conf"
- if [ "$line" != "$signature" ]; then
- cp "$resolv_conf" "$resolv_conf.bak"
+ if [ "$CMD" != u ] && \
+ [ "$(cat "$resolv_conf")" = "$(printf %s "$newconf")" ]
+ then
+ exit 0
+ fi
+ read line <"$resolv_conf"
+ if [ "$line" != "$signature" ]; then
+ if [ "$CMD" != u ]; then
+ warn "signature mismatch: $resolv_conf"
+ warn "run \`resolvconf -u\` to update"
+ exit 1
fi
+ cp "$resolv_conf" "$resolv_conf.bak"
fi
fi
-# Create our resolv.conf now
-(umask 022; echo "$newconf" >"$resolv_conf")
+# There are pros and cons for writing directly to resolv.conf
+# instead of a temporary file and then moving it over.
+# The default is to write to resolv.conf as it has the least
+# issues and has been the long standing default behaviour.
+# resolv.conf could also be bind mounted for network namespaces
+# so we cannot move in this instance.
+case "${resolv_conf_mv:-NO}" in
+[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ # Protect against symlink attack, ensure new file does not exist
+ rm -f "$resolv_conf_tmp"
+ # Keep original file owner, group and mode
+ [ -r "$resolv_conf" ] && cp -p "$resolv_conf" "$resolv_conf_tmp"
+ # Create our resolv.conf now
+ if (umask 022; printf %s "$newconf" >"$resolv_conf_tmp"); then
+ mv "$resolv_conf_tmp" "$resolv_conf"
+ fi
+ ;;
+*)
+ (umask 022; printf %s "$newconf" >"$resolv_conf")
+ ;;
+esac
+
if [ -n "$libc_restart" ]; then
eval $libc_restart
elif [ -n "$RESTARTCMD" ]; then
diff --git a/contrib/openresolv/pdns_recursor.in b/contrib/openresolv/mdnsd.in
copy from contrib/openresolv/pdns_recursor.in
copy to contrib/openresolv/mdnsd.in
--- a/contrib/openresolv/pdns_recursor.in
+++ b/contrib/openresolv/mdnsd.in
@@ -1,8 +1,8 @@
#!/bin/sh
-# Copyright (c) 2009-2019 Roy Marples
+# Copyright (c) 2007-2023 Roy Marples
# All rights reserved
-# PowerDNS Recursor subscriber for resolvconf
+# mdnsd notifier for resolvconf libc subscriber
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -26,50 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
-. "@SYSCONFDIR@/resolvconf.conf" || exit 1
-[ -z "$pdns_zones" ] && exit 0
-[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
-NL="
-"
-
-: ${pdns_service:=pdns-recursor}
-
-newzones=
-
-for n in $NAMESERVERS; do
- newzones="$newzones${newzones:+,}$n"
-done
-[ -n "$newzones" ] && newzones="+.=$newzones$NL"
-
-for d in $DOMAINS; do
- newns=
- ns="${d#*:}"
- while [ -n "$ns" ]; do
- newns="$newns${newns:+,}${ns%%,*}"
- [ "$ns" = "${ns#*,}" ] && break
- ns="${ns#*,}"
- done
- [ -n "$newns" ] && newzones="$newzones${d%%:*}=$newns$NL"
-done
-
-# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
- config_mkdirs "$pdnsd_zones"
-else
- @SBINDIR@/resolvconf -D "$pdnsd_zones"
-fi
-
-if [ ! -f "$pdns_zones" ] || \
- [ "$(cat "$pdns_zones")" != "$(printf %s "$newzones")" ]
-then
- printf %s "$newzones" >"$pdns_zones"
- if [ -n "$pdns_restart" ]; then
- eval $pdns_restart
- elif [ -n "$RESTARTCMD" ]; then
- set -- ${pdns_service}
- eval "$RESTARTCMD"
- else
- @SBINDIR@/resolvconf -r ${pdns_service}
- fi
+: ${mdnsd_pidfile:=/var/run/mdnsd/mdnsd.pid}
+if [ -s "$mdnsd_pidfile" ]; then
+ kill -HUP $(cat "$mdnsd_pidfile")
fi
diff --git a/contrib/openresolv/named.in b/contrib/openresolv/named.in
--- a/contrib/openresolv/named.in
+++ b/contrib/openresolv/named.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2007-2016 Roy Marples
+# Copyright (c) 2007-2023 Roy Marples
# All rights reserved
# named subscriber for resolvconf
@@ -79,7 +79,7 @@
done
# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
+if command -v config_mkdirs >/dev/null 2>&1; then
config_mkdirs "$named_options" "$named_zones"
else
@SBINDIR@/resolvconf -D "$named_options" "$named_zones"
diff --git a/contrib/openresolv/pdns_recursor.in b/contrib/openresolv/pdns_recursor.in
--- a/contrib/openresolv/pdns_recursor.in
+++ b/contrib/openresolv/pdns_recursor.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2009-2019 Roy Marples
+# Copyright (c) 2009-2023 Roy Marples
# All rights reserved
# PowerDNS Recursor subscriber for resolvconf
@@ -54,7 +54,7 @@
done
# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
+if command -v config_mkdirs >/dev/null 2>&1; then
config_mkdirs "$pdnsd_zones"
else
@SBINDIR@/resolvconf -D "$pdnsd_zones"
diff --git a/contrib/openresolv/pdnsd.in b/contrib/openresolv/pdnsd.in
--- a/contrib/openresolv/pdnsd.in
+++ b/contrib/openresolv/pdnsd.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2010-2018 Roy Marples
+# Copyright (c) 2010-2023 Roy Marples
# All rights reserved
# pdnsd subscriber for resolvconf
@@ -46,7 +46,7 @@
in_marker=0
shift; shift
- if type sed >/dev/null 2>&1; then
+ if command -v sed >/dev/null 2>&1; then
sed "/^$m1/,/^$m2/d" $@
else
for x do
@@ -66,9 +66,9 @@
change_file()
{
if [ -e "$1" ]; then
- if type cmp >/dev/null 2>&1; then
+ if command -v cmp >/dev/null 2>&1; then
cmp -s "$1" "$2"
- elif type diff >/dev/null 2>&1; then
+ elif command -v diff >/dev/null 2>&1; then
diff -q "$1" "$2" >/dev/null
else
# Hopefully we're only working on small text files ...
@@ -88,7 +88,7 @@
changed=false
# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
+if command -v config_mkdirs >/dev/null 2>&1; then
config_mkdirs "$pdnsd_resolv" "$pdnsd_conf"
else
@SBINDIR@/resolvconf -D "$pdnsd_resolv" "$pdnsd_conf"
diff --git a/contrib/openresolv/resolvconf.8.in b/contrib/openresolv/resolvconf.8.in
--- a/contrib/openresolv/resolvconf.8.in
+++ b/contrib/openresolv/resolvconf.8.in
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2007-2016 Roy Marples
+.\" Copyright (c) 2007-2025 Roy Marples
.\" All rights reserved
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd November 29, 2016
+.Dd June 26, 2025
.Dt RESOLVCONF 8
.Os
.Sh NAME
@@ -35,14 +35,18 @@
.Op Fl m Ar metric
.Op Fl p
.Op Fl x
-.Fl a Ar interface Ns Op Ar .protocol
+.Fl a Ar key
.No < Ns Pa file
.Nm
+.Fl C Ar pattern
+.Nm
+.Fl c Ar pattern
+.Nm
.Op Fl f
-.Fl d Ar interface Ns Op Ar .protocol
+.Fl d Ar key
.Nm
.Op Fl x
-.Fl il Ar pattern
+.Fl iLlp Ar pattern
.Nm
.Fl u
.Nm
@@ -68,12 +72,20 @@
via
.Xr stdin 4
with the argument
-.Fl a Ar interface Ns Op Ar .protocol
+.Fl a Ar key
instead of the filesystem.
.Nm
then updates
.Pa /etc/resolv.conf
as it thinks best.
+If
+.Pa /etc/resolv.conf
+already exists and the top line does not match the expected signature,
+then
+.Nm
+will refuse to update it unless the
+.Fl u
+update command is given.
When a local resolver other than libc is installed, such as
.Xr dnsmasq 8
or
@@ -82,27 +94,40 @@
.Nm
will supply files that the resolver should be configured to include.
.Pp
+At it's heart,
.Nm
-assumes it has a job to do.
-In some situations
+is a key/value store for
+.Pa resolv.conf
+files.
+Each entry must have a unique
+.Ar key
+and should be expressed as
+.Sy interface.protocol
+so that it's easy to tell from where the
+.Pa resolv.conf
+file came from.
+This also allows using pattern matching such as
+.Sy interface.*
+to match all protocols running on the interface.
+For example, a modern system will likely run DHCP, RA and DHCPv6
+which could be from separate programs or one program running
+many protocols.
+However, this is not a fixed requirement,
.Nm
-needs to act as a deterrent to writing to
-.Pa /etc/resolv.conf .
-Where this file cannot be made immutable or you just need to toggle this
-behaviour,
-.Nm
-can be disabled by adding
-.Sy resolvconf Ns = Ns NO
-to
-.Xr resolvconf.conf 5 .
+will work with any key name and it should be treated as an opaque value
+outside of
+.Nm .
.Pp
.Nm
-can mark an interfaces
+can mark a
.Pa resolv.conf
-as private.
+as private and optionally non-searchable.
This means that the name servers listed in that
.Pa resolv.conf
-are only used for queries against the domain/search listed in the same file.
+are only used for queries against the domain/search listed in the same file
+and if non-searchable then the domain/search listed are
+excluded from the global search list defined in
+.Pa /etc/resolv.conf .
This only works when a local resolver other than libc is installed.
See
.Xr resolvconf.conf 5
@@ -111,57 +136,97 @@
to use a local name server and how to remove the private marking.
.Pp
.Nm
-can mark an interfaces
+can mark a
.Pa resolv.conf
as exclusive.
-Only the latest exclusive interface is used for processing, otherwise all are.
+Only the latest exclusive key is used for processing, otherwise all are.
.Pp
-When an interface goes down, it should then call
+When a configuration source goes away,
+such as an interface going down or a VPN stopping,
+it should then call
.Nm
with
-.Fl d Ar interface.*
-arguments to delete the
+.Fl d Ar key
+arguments to clean up the
.Pa resolv.conf
-file(s) for all the
-.Ar protocols
-on the
-.Ar interface .
+it added previously.
+For systems that support the concept of persisting configuration when
+the source is suspended,
+such as the carrier going down,
+then it should instead call
+.Nm
+with
+.Fl C Ar key
+arguments to deprecate the entry
+.Fl c Ar key
+to activate the entry when it comes back again.
+This only affects the order in which the
+.Pa resolv.conf
+entries are processed.
.Pp
-Here are some options for the above commands:-
+Here are some options for the above commands:
.Bl -tag -width pattern_opt
.It Fl f
-Ignore non existent interfaces.
-Only really useful for deleting interfaces.
+Ignore non existent
+.Pa resolv.conf
+entries.
+Only really useful for deleting.
.It Fl m Ar metric
-Set the metric of the interface when adding it, default of 0.
+Set the metric of the
+.Pa resolv.conf
+entry when adding it, default of 0.
Lower metrics take precedence.
-This affects the default order of interfaces when listed.
-.It Fl p
-Marks the interface
+This affects the default order of entires when listed.
+.It Fl p Op Ar pattern
+Marks the
.Pa resolv.conf
-as private.
+as private if the
+.Fl a
+command is given, otherwise
+.Pa resolv.conf
+entries having their key matching
+.Ar pattern
+are listed.
+If an extra
+.Fl p
+is given then the
+.Pa resolv.conf
+is marked as non-searchable as well.
.It Fl x
-Mark the interface
+Mark the
.Pa resolv.conf
-as exclusive when adding, otherwise only use the latest exclusive interface.
+as exclusive when adding, otherwise only use the latest exclusive key.
.El
.Pp
.Nm
-has some more commands for general usage:-
+has some more commands for general usage:
.Bl -tag -width pattern_opt
-.It Fl i Ar pattern
-List the interfaces and protocols, optionally matching
+.It Fl i Op Ar pattern
+List the keys stored, optionally matching
.Ar pattern ,
we have
.Pa resolv.conf
files for.
-.It Fl l Ar pattern
+If the
+.Fl L
+option is given first, then the keys will be list post-processed.
+.It Fl L Op Ar pattern
+List the
+.Pa resolv.conf
+files we have,
+post-processed by the
+.Xr resolvconf.conf 5
+configuration.
+If
+.Ar pattern
+is specified then we list the files for the keys which match it.
+.It Fl l Op Ar pattern
List the
.Pa resolv.conf
files we have.
If
.Ar pattern
-is specified then we list the files for the interfaces and protocols
+is specified then we list the files for the keys which match it.
that match it.
.It Fl u
Force
@@ -169,27 +234,23 @@
to update all its subscribers.
.Nm
does not update the subscribers when adding a resolv.conf that matches
-what it already has for that interface.
+what it already has for that key.
.It Fl Fl version
Echo the resolvconf version to
.Em stdout .
.El
.Pp
.Nm
-also has some commands designed to be used by it's subscribers and
-system startup:-
+also has some commands designed to be used by its subscribers and
+system startup:
.Bl -tag -width pattern_opt
.It Fl I
Initialise the state directory
.Pa @VARDIR@ .
-This only needs to be called if the initial system boot sequence does not
-automatically clean it out; for example the state directory is moved
-somewhere other than
-.Pa /var/run .
-If used, it should only be called once as early in the system boot sequence
-as possible and before
-.Nm
-is used to add interfaces.
+This should be called after the base state directory has either been
+cleaned out or mounted as a memory backed filesystem during the
+initial boot sequence before any daemon has the chance to call
+.Nm .
.It Fl R
Echo the command used to restart a service.
.It Fl r Ar service
@@ -208,17 +269,18 @@
.Xr resolvconf.conf 5
is set.
.El
-.Sh INTERFACE ORDERING
+.Sh RESOLV.CONF ORDERING
For
.Nm
-to work effectively, it has to process the resolv.confs for the interfaces
-in the correct order.
+to work effectively, it has to process the
+.Pa resolv.conf
+entries in the correct order.
.Nm
-first processes interfaces from the
-.Sy interface_order
-list, then interfaces without a metic and that match the
+first processes keys from the
+.Sy key_order
+list, then entries without a metric and that match the
.Sy dynamic_order
-list, then interfaces with a metric in order and finally the rest in
+list, then entries with a metric in order and finally the rest in
the operating systems lexical order.
See
.Xr resolvconf.conf 5
@@ -226,19 +288,9 @@
.Sh PROTOCOLS
Here are some suggested protocol tags to use for each
.Pa resolv.conf
-file registered on an
-.Ar interface Ns No :-
.Bl -tag -width pattern_opt
.It dhcp
Dynamic Host Configuration Protocol.
-Initial versions of
-.Nm
-did not recommend a
-.Ar protocol
-tag be appended to the
-.Ar interface
-name.
-When the protocol is absent, it is assumed to be the DHCP protocol.
.It ppp
Point-to-Point Protocol.
.It ra
@@ -270,11 +322,15 @@
.Va IF_METRIC
for the metric.
.It Va IF_PRIVATE
-Marks the interface
+Marks the
.Pa resolv.conf
as private.
+.It Va IF_NOSEARCH
+Marks the
+.Pa resolv.conf
+as non-searchable.
.It Va IF_EXCLUSIVE
-Marks the interface
+Marks the
.Pa resolv.conf
as exclusive.
.El
@@ -295,6 +351,17 @@
State directory for
.Nm .
.El
+.Sh NOTES
+Domain labels are assumed to be in ASCII and are converted to lower case
+to avoid duplicate zones when given differing case from different sources.
+.Pp
+When running a local resolver other than libc, you will need to configure it
+to include files that
+.Nm
+will generate.
+You should consult
+.Xr resolvconf.conf 5
+for instructions on how to configure your resolver.
.Sh SEE ALSO
.Xr resolver 3 ,
.Xr stdin 4 ,
@@ -310,14 +377,3 @@
.Sh BUGS
Please report them to
.Lk http://roy.marples.name/projects/openresolv
-.Pp
-.Nm
-does not validate any of the files given to it.
-.Pp
-When running a local resolver other than libc, you will need to configure it
-to include files that
-.Nm
-will generate.
-You should consult
-.Xr resolvconf.conf 5
-for instructions on how to configure your resolver.
diff --git a/contrib/openresolv/resolvconf.conf.5.in b/contrib/openresolv/resolvconf.conf.5.in
--- a/contrib/openresolv/resolvconf.conf.5.in
+++ b/contrib/openresolv/resolvconf.conf.5.in
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2009-2016 Roy Marples
+.\" Copyright (c) 2009-2025 Roy Marples
.\" All rights reserved
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 8, 2019
+.Dd May 15, 2025
.Dt RESOLVCONF.CONF 5
.Os
.Sh NAME
@@ -61,26 +61,44 @@
.Nm resolvconf
from running any subscribers.
Defaults to YES.
-.It Sy interface_order
-These interfaces will always be processed first.
-If unset, defaults to the following:-
-.Bd -compact -literal -offset indent
+.It Sy allow_keys
+If set, only these keys will be processed.
+.It Sy deny_keys
+If set, these keys will not be processed.
+.It Sy exclude
+Is a space separated list of key/value pairs to match.
+If all key/value pairs in one element can be found in the file,
+then the whole file will be excluded from processing.
+The syntax is this:
+.Va $keyword Ns / Ns Va $match Ns Op / Ns Va $keyword Ns / Ns Va $match
+.Pp
+For example given this configuration:
+.Bd -literal -compact -offset indent
+exclude="search/foo*/nameserver/1.2.3.4 search/bar.org"
+.Ed
+.Pp
+Then any resolv.conf with both a search option starting with foo with a nameserver of 1.2.3.4
+OR a search option of bar.org would be excluded.
+.It Sy key_order
+These keys will always be processed first.
+If unset, defaults to the following:
+.Bd -literal -compact -offset indent
lo lo[0-9]*
.Ed
.It Sy dynamic_order
-These interfaces will be processed next, unless they have a metric.
-If unset, defaults to the following:-
-.Bd -compact -literal -offset indent
-tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]*
+These keys will be processed next, unless they have a metric.
+If unset, defaults to the following:
+.Bd -literal -compact -offset indent
+tap[0-9]* tun[0-9]* vpn vpn[0-9]* wg[0-9]* ppp[0-9]* ippp[0-9]*
.Ed
-.It Sy inclusive_interfaces
-Ignore any exclusive marking for these interfaces.
+.It Sy inclusive_keys
+Ignore any exclusive marking for these keys.
This is handy when 3rd party integrations force the
.Nm resolvconf -x
option and you want to disable it easily.
.It Sy local_nameservers
-If unset, defaults to the following:-
-.Bd -compact -literal -offset indent
+If unset, defaults to the following:
+.Bd -literal -compact -offset indent
127.* 0.0.0.0 255.255.255.255 ::1
.Ed
.It Sy search_domains
@@ -101,20 +119,25 @@
A list of name servers to be removed from consideration.
The default is 0.0.0.0 as some faulty routers send it via DHCP.
To remove a block, you can use 192.168.*
-.It Sy private_interfaces
-These interfaces name servers will only be queried for the domains listed
+.It Sy private_keys
+These keys name servers will only be queried for the domains listed
in their resolv.conf.
Useful for VPN domains.
Setting
-.Sy private_interfaces Ns ="*"
+.Sy private_keys Ns ="*"
will stop the forwarding of the root zone and allows the local resolver to
recursively query the root servers directly.
Requires a local nameserver other than libc.
This is equivalent to the
.Nm resolvconf -p
option.
-.It Sy public_interfaces
-Force these interface to be public, overriding the private marking.
+.It Sy nosearch_keys
+These keys domains/search won't be added to the global search list
+in
+.Pa /etc/resolv.conf .
+.It Sy public_keys
+Force these keys to be public, overriding the private and nosearch
+markings.
This is handy when 3rd party integrations force the
.Nm resolvconf -p
option and you want to disable it easily.
@@ -124,24 +147,27 @@
.Va $keyword Ns / Ns Va $match Ns / Ns Va $replacement
.Pp
Example, given this resolv.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
domain foo.org
search foo.org dead.beef
nameserver 1.2.3.4
nameserver 2.3.4.5
.Ed
-and this configuaration:
-.Bd -compact -literal -offset indent
+.Pp
+and this configuration:
+.Bd -literal -compact -offset indent
replace="search/foo*/bar.com"
replace="$replace nameserver/1.2.3.4/5.6.7.8"
replace="$replace nameserver/2.3.4.5/"
.Ed
+.Pp
you would get this resolv.conf instead:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
domain foo.org
search bar.com
nameserver 5.6.7.8
.Ed
+.Pp
.It Sy replace_sub
Works the same way as
.Sy replace
@@ -152,11 +178,12 @@
to
.Sy replace_sub ,
you would get this resolv.conf instead:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
domain foo.org
search bar.com dead.beef
nameserver 5.6.7.8
.Ed
+.Pp
.It Sy state_dir
Override the default state directory of
.Pa @VARDIR@ .
@@ -167,12 +194,17 @@
.Sh LIBC OPTIONS
The following variables affect
.Xr resolv.conf 5
-directly:-
+directly:
.Bl -tag -width indent
.It Sy resolv_conf
Defaults to
.Pa /etc/resolv.conf
if not set.
+Set to
+.Pa /dev/null
+to stop
+.Xr resolvconf 8
+from changing it.
.It Sy resolv_conf_options
A list of libc resolver options, as specified in
.Xr resolv.conf 5 .
@@ -188,6 +220,14 @@
.Nm
is written to
.Sy resolv_conf .
+.It Sy resolv_conf_restore
+When set to YES and
+and an empty
+.Pa resolv.conf
+would be written, restore
+.Pa resolv.conf.bak
+instead if it exists.
+Defaults to YES if not set.
.It Sy resolv_conf_sortlist
A libc resolver sortlist, as specified in
.Xr resolv.conf 5 .
@@ -206,21 +246,28 @@
Append search domains to the dynamically generated list.
.It Sy prepend_search
Prepend search domains to the dynamically generated list.
+.It Sy resolv_conf_mv
+Defaults to NO.
+Defines if
+.Pa /etc/resolv.conf
+is updated by writing to a temporary file and then moving it
+vs writing directly to it.
.El
.Sh SUBSCRIBER OPTIONS
openresolv ships with subscribers for the name servers
.Xr dnsmasq 8 ,
.Xr named 8 ,
.Xr pdnsd 8 ,
-.Xr pdns_recursor 8 ,
+.Xr pdns_recursor 1 ,
and
.Xr unbound 8 .
Each subscriber can create configuration files which should be included in
-in the subscribers main configuration file.
+the subscribers main configuration file.
.Pp
-To disable a subscriber, simply set it's name to NO.
+To disable a subscriber, simply set its name to NO.
+If the subscriber name has a dash in it, then replace it with an underscore.
For example, to disable the libc subscriber you would set:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
libc=NO
.Ed
.Bl -tag -width indent
@@ -230,14 +277,14 @@
This file tells dnsmasq which name servers to use for global lookups.
.Pp
Example resolvconf.conf for dnsmasq:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
name_servers=127.0.0.1
dnsmasq_conf=/etc/dnsmasq-conf.conf
dnsmasq_resolv=/etc/dnsmasq-resolv.conf
.Ed
.Pp
Example dnsmasq.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
listen-address=127.0.0.1
# If dnsmasq is compiled for DBus then we can take
# advantage of not having to restart dnsmasq.
@@ -253,14 +300,14 @@
This file tells named which name servers to use for specific domains.
.Pp
Example resolvconf.conf for named:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
name_servers=127.0.0.1
named_options=/etc/named-options.conf
named_zones=/etc/named-zones.conf
.Ed
.Pp
Example named.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
options {
listen-on { 127.0.0.1; };
include "/etc/named-options.conf";
@@ -281,14 +328,14 @@
.Pa pdnsd_conf .
.Pp
Example resolvconf.conf for pdnsd:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
name_servers=127.0.0.1
pdnsd_conf=/etc/pdnsd.conf
# pdnsd_resolv=/etc/pdnsd-resolv.conf
.Ed
.Pp
Example pdnsd.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
global {
server_ip = 127.0.0.1;
status_ctl = on;
@@ -304,29 +351,76 @@
This file tells pdns_recursor about specific and global name servers.
.Pp
Example resolvconf.conf for pdns_recursor:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
name_servers=127.0.0.1
pdns_zones=/etc/pdns/recursor-zones.conf
.Ed
.Pp
Example recursor.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
allow-from=127.0.0.0/8, ::1/128
forward-zones-file=/etc/pdns/recursor-zones.conf
.Ed
+.It Sy resolvectl
+When set to YES,
+.Xr resolvectl 1
+will be used to write per interface entries from
+.Xr resolvconf 8
+to
+.Xr systemd-resolved 8 .
+A warning is emitted for any entry that cannot be matched to an
+interface.
+.Pp
+This subscriber should only be used if your systemd-resolved does
+not support DNS delegates and you need private or non searchable
+.Xr resolvconf 8
+entries, or you're really beholden to seeing DNS setup per interface via
+.Xr resolvectl 1 .
+The systemd-resolved subscriber documented below is the better option.
+.Pp
+Example resolvconf.conf for resolvectl:
+.Bd -literal -compact -offset indent
+# Keep /etc/resolv.conf as systemd-resolved wants it
+libc=NO
+resolvectl=YES
+.Ed
+.It Sy systemd_resolved
+When set to YES, global DNS will be written to the
+.Sy systemd_resolved_conf
+configuration file and DNS delegates will be written to the
+.Sy systemd_delegate_dir
+directory.
+.It Sy systemd_resolved_conf
+Defaults to
+.Pa /run/systemd/resolved.conf.d/60-resolvconf.conf .
+.It Sy systemd_delegate_dir
+Defaults to
+.Pa /run/systemd/dns-delegate.d .
+.Pp
+Example resolvconf.conf for systemd-resolved:
+.Bd -literal -compact -offset indent
+# Keep /etc/resolv.conf as systemd-resolved wants it
+libc=NO
+systemd_resolved=YES
+.Ed
.It Sy unbound_conf
This file tells unbound about specific and global name servers.
.It Sy unbound_insecure
When set to YES, unbound marks the domains as insecure, thus ignoring DNSSEC.
+.It Sy unbound_private
+When set to YES, unbound marks the domains as private, allowing it and its subdomains to contain private addresses.
+.It Sy unbound_forward_zone_options
+Options appended to each forward zone.
+Each option should be separated by an embedded new line.
.Pp
Example resolvconf.conf for unbound:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
name_servers=127.0.0.1
unbound_conf=/etc/unbound-resolvconf.conf
.Ed
.Pp
Example unbound.conf:
-.Bd -compact -literal -offset indent
+.Bd -literal -compact -offset indent
include: /etc/unbound-resolvconf.conf
.Ed
.El
@@ -380,5 +474,13 @@
Each distribution is a special snowflake and likes to name the same thing
differently, namely the named service script.
.Pp
+Swapping between resolvectl and systemd-resolved subscribers at runtime
+is not supported.
+Files referenced by systemd_resolved_conf and systemd_delegate_dir
+need to be removed by hand.
+A reboot is recommended so that stale data is removed.
+While you could run them both at the same time, only using one is the
+recommended approach.
+.Pp
Please report them to
-.Lk http://roy.marples.name/projects/openresolv
+.Lk https://roy.marples.name/projects/openresolv
diff --git a/contrib/openresolv/resolvconf.in b/contrib/openresolv/resolvconf.in
--- a/contrib/openresolv/resolvconf.in
+++ b/contrib/openresolv/resolvconf.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2007-2019 Roy Marples
+# Copyright (c) 2007-2025 Roy Marples
# All rights reserved
# Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
RESOLVCONF="$0"
-OPENRESOLV_VERSION="3.9.2"
+OPENRESOLV_VERSION="3.17.4"
SYSCONFDIR=@SYSCONFDIR@
LIBEXECDIR=@LIBEXECDIR@
VARDIR=@VARDIR@
@@ -34,7 +34,7 @@
if [ "$1" = "--version" ]; then
echo "openresolv $OPENRESOLV_VERSION"
- echo "Copyright (c) 2007-2016 Roy Marples"
+ echo "Copyright (c) 2007-2025 Roy Marples"
exit 0
fi
@@ -44,10 +44,31 @@
# If you change this, change the test in VFLAG and libc.in as well
local_nameservers="127.* 0.0.0.0 255.255.255.255 ::1"
-dynamic_order="tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]*"
+dynamic_order="tap[0-9]* tun[0-9]* vpn vpn[0-9]* wg[0-9]* ppp[0-9]* ippp[0-9]*"
interface_order="lo lo[0-9]*"
name_server_blacklist="0.0.0.0"
+# Poor mans cat
+# /usr might not be available
+cat()
+{
+ OIFS="$IFS"
+ IFS=''
+ if [ -n "$1" ]; then
+ while read -r line; do
+ printf "%s\n" "$line"
+ done < "$1"
+ else
+ while read -r line; do
+ printf "%s\n" "$line"
+ done
+ fi
+ retval=$?
+ IFS="$OIFS"
+ return $retval
+}
+
+
# Support original resolvconf configuration layout
# as well as the openresolv config file
if [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
@@ -59,21 +80,36 @@
interface_order="$(cat "$SYSCONFDIR"/interface-order)"
fi
fi
-IFACEDIR="$VARDIR/interfaces"
+
+KEYDIR="$VARDIR/keys"
METRICDIR="$VARDIR/metrics"
PRIVATEDIR="$VARDIR/private"
+NOSEARCHDIR="$VARDIR/nosearch"
EXCLUSIVEDIR="$VARDIR/exclusive"
+DEPRECATEDDIR="$VARDIR/deprecated"
LOCKDIR="$VARDIR/lock"
_PWD="$PWD"
+# Compat
+if [ ! -d "$KEYDIR" ] && [ -d "$VARDIR/interfaces" ]; then
+ KEYDIR="$VARDIR/interfaces"
+fi
+: ${allow_keys:="$allow_interfaces"}
+: ${deny_keys:="$deny_interfaces"}
+: ${key_order:="$interface_order"}
+: ${inclusive_keys:="$inclusive_interfaces"}
+: ${exclusive_keys:="$exclusive_interfaces"}
+: ${private_keys:="$private_interfaces"}
+: ${public_keys:="$public_interfaces"}
+
warn()
{
- echo "$*" >&2
+ echo "${RESOLVCONF##*/}: $*" >&2
}
error_exit()
{
- echo "$*" >&2
+ warn "$*"
exit 1
}
@@ -85,24 +121,27 @@
Inform the system about any DNS updates.
Commands:
- -a \$INTERFACE Add DNS information to the specified interface
+ -a \$KEY Add DNS information to the specified key
(DNS supplied via stdin in resolv.conf format)
- -d \$INTERFACE Delete DNS information from the specified interface
+ -C \$PATTERN Deprecate DNS information for matched key
+ -c \$PATTERN Configure DNS information for matched key
+ -d \$PATTERN Delete DNS information from the matched key
-h Show this help cruft
- -i [\$PATTERN] Show interfaces that have supplied DNS information
- optionally from interfaces that match the specified
+ -i [\$PATTERN] Show keys that have supplied DNS information
+ optionally from keys that match the specified
pattern
- -l [\$PATTERN] Show DNS information, optionally from interfaces
+ -l [\$PATTERN] Show DNS information, optionally from keys
that match the specified pattern
+ -L [\$PATTERN] Same as -l, but adjusted by our config
-u Run updates from our current DNS information
--version Echo the ${RESOLVCONF##*/} version
Options:
- -f Ignore non existent interfaces
+ -f Ignore non existent keys
-m metric Give the added DNS information a metric
- -p Mark the interface as private
- -x Mark the interface as exclusive
+ -p Mark the resolv.conf as private
+ -x Mark the resolv.conf as exclusive
Subscriber and System Init Commands:
-I Init the state dir
@@ -117,56 +156,111 @@
EOF
[ -z "$1" ] && exit 0
echo
- error_exit "$*"
+ error_exit "$@"
}
-# Strip any trailing dot from each name as a FQDN does not belong
-# in resolv.conf(5)
-# If you think otherwise, capture a DNS trace and you'll see libc
-# will strip it regardless.
-# This also solves setting up duplicate zones in our subscribers.
-# Also strip any comments denoted by #.
-resolv_strip()
-{
- space=
- for word; do
- case "$word" in
- \#*) break;;
- esac
- printf "%s%s" "$space${word%.}"
- space=" "
- done
- printf "\n"
-}
+public_key() {
+ key="$1"
-private_iface()
-{
# Allow expansion
- cd "$IFACEDIR"
+ cd "$KEYDIR"
- # Public interfaces override private ones.
- for p in $public_interfaces; do
- case "$iface" in
- "$p"|"$p":*) return 1;;
- esac
- done
-
- if [ -e "$PRIVATEDIR/$iface" ]; then
- return 0
- fi
-
- for p in $private_interfaces; do
- case "$iface" in
+ # Public keys override private ones.
+ for p in $public_keys; do
+ case "$key" in
"$p"|"$p":*) return 0;;
esac
done
- # Not a private interface
return 1
}
+private_key()
+{
+ key="$1"
+
+ if public_key "$key"; then
+ return 1
+ fi
+
+ if [ -e "$PRIVATEDIR/$key" ]; then
+ return 0
+ fi
+
+ for p in $private_keys; do
+ case "$key" in
+ "$p"|"$p":*) return 0;;
+ esac
+ done
+
+ # Not a private key
+ return 1
+}
+
+nosearch_key()
+{
+ key="$1"
+
+ if public_key "$key"; then
+ return 1
+ fi
+
+ if [ -e "$NOSEARCHDIR/$key" ]; then
+ return 0
+ fi
+
+ for p in $nosearch_keys; do
+ case "$key" in
+ "$p"|"$p":*) return 0;;
+ esac
+ done
+
+ # Not a non searchable key
+ return 1
+}
+
+exclusive_key()
+{
+ key="$1"
+
+ for x in "$EXCLUSIVEDIR/"*" $key"; do
+ if [ -f "$x" ]; then
+ return 0
+ fi
+ done
+
+ # Not an exclusive key
+ return 1
+}
+
+# Quote input so it can be safely used for variable assignment via eval
+quote()
+{
+ if [ -z "$1" ]; then
+ R="''"
+ else
+ R=
+ for W; do
+ while [ -n "$W" ]; do
+ case "$W" in
+ \'*) R="$R\\'"; W=${W#?};;
+ ?\'*) R="$R\\${W%%\'*}"; W="${W#?}";;
+ *\'*) R="$R'${W%%\'*}'"; W="'${W#*\'}";;
+ ?) R="$R\\$W"; W=;;
+ *) R="$R'$W'"; W=;;
+ esac
+ done
+ done
+ fi
+
+ printf '%s\n' "$R"
+ return 0
+}
+
# Parse resolv.conf's and make variables
# for domain name servers, search name servers and global nameservers
+# Important! Each printf here should use the above quote function
+# to ensure that user input is quoted for eval.
parse_resolv()
{
domain=
@@ -174,26 +268,32 @@
newns=
ns=
private=false
+ nosearch=false
search=
while read -r line; do
- stripped_line="$(resolv_strip ${line#* })"
+ value="${line#* }"
case "$line" in
"# resolv.conf from "*)
if ${new}; then
- iface="${line#\# resolv.conf from *}"
+ key="${line#\# resolv.conf from *}"
new=false
- if private_iface "$iface"; then
+ if nosearch_key "$key"; then
private=true
+ nosearch=true
+ elif private_key "$key"; then
+ private=true
+ nosearch=false
else
private=false
+ nosearch=false
fi
fi
;;
"nameserver "*)
islocal=false
for l in $local_nameservers; do
- case "$stripped_line" in
+ case "$value" in
$l)
islocal=true
break
@@ -201,20 +301,22 @@
esac
done
if $islocal; then
- echo "LOCALNAMESERVERS=\"\$LOCALNAMESERVERS $stripped_line\""
+ printf 'LOCALNAMESERVERS="$LOCALNAMESERVERS "%s\n' "$(quote "$value")"
else
- ns="$ns$stripped_line "
+ ns="$ns${ns:+ }$value"
fi
;;
"domain "*)
- search="$stripped_line"
+ search="$value"
if [ -z "$domain" ]; then
domain="$search"
- echo "DOMAIN=\"$domain\""
+ if ! $nosearch; then
+ printf 'DOMAIN=%s\n' "$(quote "$domain")"
+ fi
fi
;;
"search "*)
- search="$stripped_line"
+ search="$value"
;;
*)
[ -n "$line" ] && continue
@@ -227,11 +329,13 @@
for d in $search; do
ds="$ds${ds:+ }$d:$newns"
done
- echo "DOMAINS=\"\$DOMAINS $ds\""
+ printf 'DOMAINS="$DOMAINS "%s\n' "$(quote "$ds")"
+ fi
+ if ! $nosearch; then
+ printf 'SEARCH="$SEARCH "%s\n' "$(quote "$search")"
fi
- echo "SEARCH=\"\$SEARCH $search\""
if ! $private; then
- echo "NAMESERVERS=\"\$NAMESERVERS $ns\""
+ printf 'NAMESERVERS="$NAMESERVERS "%s\n' "$(quote "$ns")"
fi
ns=
search=
@@ -274,26 +378,21 @@
config_mkdirs()
{
- e=0
for f; do
[ -n "$f" ] || continue
d="$(dirname "$f")"
if [ ! -d "$d" ]; then
- if type install >/dev/null 2>&1; then
- install -d "$d" || e=$?
- else
- mkdir "$d" || e=$?
- fi
+ mkdir -p "$d" || return $?
fi
done
- return $e
+ return 0
}
# With the advent of alternative init systems, it's possible to have
# more than one installed. So we need to try and guess what one we're
-# using unless overriden by configure.
+# using unless overridden by configure.
# Note that restarting a service is a last resort - the subscribers
-# should make a reasonable attempt to reconfigre the service via some
+# should make a reasonable attempt to reconfigure the service via some
# method, normally SIGHUP.
detect_init()
{
@@ -328,6 +427,12 @@
then
/usr/sbin/invoke-rc.d $1 restart
fi'
+ elif [ -x /usr/bin/s6-rc ] && [ -x /usr/bin/s6-svc ]; then
+ RESTARTCMD='
+ if s6-rc -a list 2>/dev/null | grep -qFx $1-srv
+ then
+ s6-svc -r /run/service/$1-srv
+ fi'
elif [ -x /sbin/service ]; then
# Old RedHat
RCDIR=/etc/init.d
@@ -368,6 +473,8 @@
then
/etc/rc.d/$1 restart
fi'
+ elif [ -d /etc/dinit.d ] && command -v dinitctl >/dev/null 2>&1; then
+ RESTARTCMD='dinitctl --quiet restart --ignore-unstarted $1'
else
for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do
[ -d $x ] || continue
@@ -395,9 +502,9 @@
{
OIFS="$IFS"
- [ -n "$1" ] && [ -f "$IFACEDIR/$1" ] || return 1
+ [ -n "$1" ] && [ -f "$KEYDIR/$1" ] || return 1
echo "# resolv.conf from $1"
- # Our variable maker works of the fact each resolv.conf per interface
+ # Our variable maker works of the fact each resolv.conf per key
# is separated by blank lines.
# So we remove them when echoing them.
while read -r line; do
@@ -407,103 +514,296 @@
IFS=''
printf "%s\n" "$line"
fi
- done < "$IFACEDIR/$1"
+ done < "$KEYDIR/$1"
IFS="$OIFS"
}
+deprecated_key()
+{
+ [ -d "$DEPRECATEDDIR" ] || return 1
+
+ cd "$DEPRECATEDDIR"
+ for da; do
+ for daf in *; do
+ [ -f "$daf" ] || continue
+ case "$da" in
+ $daf) return 0;;
+ esac
+ done
+ done
+ return 1
+}
+
+match()
+{
+ match="$1"
+ file="$2"
+ retval=1
+ count=0
+
+ while read -r keyword value; do
+ new_match=
+ for om in $match; do
+ m="$om"
+ keep=
+ while [ -n "$m" ]; do
+ k="${m%%/*}"
+ r="${m#*/}"
+ f="${r%%/*}"
+ r="${r#*/}"
+ # If the length of m is the same as k/f then
+ # we know that we are done
+ if [ ${#m} = $((${#k} + 1 + ${#f})) ]; then
+ r=
+ fi
+ m="$r"
+ matched=false
+ case "$keyword" in
+ $k)
+ case "$value" in
+ $f)
+ matched=true
+ ;;
+ esac
+ ;;
+ esac
+ if ! $matched; then
+ keep="$keep${keep:+/}$k/$f"
+ fi
+ done
+ if [ -n "$om" ] && [ -z "$keep" ]; then
+ retval=0
+ break 2
+ fi
+ new_match="${new_match}${new_match:+ }${keep}"
+ done
+ match="${new_match}"
+ done < "$file"
+ return $retval
+}
+
+list_keys() {
+ list_cmd="$1"
+ shift
+
+ [ -d "$KEYDIR" ] || return 0
+ cd "$KEYDIR"
+
+ [ -n "$1" ] || set -- "*"
+ list=
+ retval=0
+ if [ "$list_cmd" = -i ] || [ "$list_cmd" = -l ]; then
+ for i in $@; do
+ if [ ! -f "$i" ]; then
+ if ! $force && [ "$i" != "*" ]; then
+ echo "No resolv.conf for key $i" >&2
+ fi
+ retval=2
+ continue
+ fi
+ list="$list $i"
+ done
+ [ -z "$list" ] || uniqify $list
+ return $retval
+ fi
+
+ if [ "$list_cmd" != -I ] && [ "$list_cmd" != -L ]; then
+ echo "list_keys: unknown command $list_cmd" >&2
+ return 1
+ fi
+
+ if [ -d "$EXCLUSIVEDIR" ]; then
+ cd "$EXCLUSIVEDIR"
+ for i in $EXCLUSIVEDIR/*; do
+ if [ -f "$i" ]; then
+ cd "$KEYDIR"
+ for ii in $inclusive_keys; do
+ if [ -f "$ii" ] && [ "${i#* }" = "$ii" ]; then
+ continue 2
+ fi
+ done
+ list="${i#* }"
+ break
+ fi
+ done
+ cd "$KEYDIR"
+ if [ -n "$list" ]; then
+ for i in $@; do
+ # list will be one item due to the above
+ if [ -f "$i" ] && [ "$i" = "$list" ]; then
+ echo "$i"
+ return 0
+ fi
+ done
+ return 0
+ fi
+ fi
+
+ for i in $key_order; do
+ for ii in "$i" "$i":* "$i".*; do
+ [ -f "$ii" ] && list="$list $ii"
+ done
+ done
+
+ for i in $dynamic_order; do
+ for ii in "$i" "$i":* "$i".*; do
+ if [ -f "$ii" ] && ! [ -e "$METRICDIR/"*" $ii" ]
+ then
+ list="$list $ii"
+ fi
+ done
+ done
+
+ # Interfaces have an implicit metric of 0 if not specified.
+ for i in *; do
+ if [ -f "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then
+ list="$list $i"
+ fi
+ done
+
+ if [ -d "$METRICDIR" ]; then
+ cd "$METRICDIR"
+ for i in *; do
+ [ -f "$i" ] && list="$list ${i#* }"
+ done
+ cd "$KEYDIR"
+ fi
+
+ # Move deprecated keys to the back
+ active=
+ deprecated=
+ for i in $list; do
+ if deprecated_key "$i"; then
+ deprecated="$deprecated $i"
+ else
+ active="$active $i"
+ fi
+ done
+ list="$active $deprecated"
+
+ retval=0
+ if [ "$1" != "*" ]; then
+ cd "$KEYDIR"
+ matched=
+ for i in $@; do
+ if ! [ -f "$i" ]; then
+ if ! $force; then
+ echo "No resolv.conf for key $i" >&2
+ fi
+ retval=2
+ continue
+ fi
+ for ii in $list; do
+ if [ "$i" = "$ii" ]; then
+ matched="$matched${matched:+ }$i"
+ break
+ fi
+ done
+ done
+ if [ -z "$matched" ]; then
+ return $retval
+ fi
+ list="$matched"
+ fi
+
+ allowed=
+ for i in $(uniqify $list); do
+ if [ -n "$allow_keys" ]; then
+ x=false
+ for ii in $allow_keys; do
+ if [ "$i" = "$ii" ]; then
+ x=true
+ break
+ fi
+ done
+ $x || continue
+ fi
+ for ii in $deny_keys; do
+ if [ "$i" = "$ii" ]; then
+ continue 2
+ fi
+ done
+
+ if [ -n "$exclude" ] && match "$exclude" "$i"; then
+ continue
+ fi
+ allowed="$allowed${allowed:+ }$i"
+ done
+
+ cd "$KEYDIR"
+ for i in $exclusive_keys; do
+ for ii in $allowed; do
+ if [ "$i" = "$ii" ]; then
+ echo "$i"
+ return
+ fi
+ done
+ done
+ [ -z "$allowed" ] || echo "$allowed"
+}
+
list_resolv()
{
- [ -d "$IFACEDIR" ] || return 0
-
- cmd="$1"
- shift
- excl=false
- list=
- report=false
- retval=0
-
- case "$IF_EXCLUSIVE" in
- [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
- excl=true
- if [ -d "$EXCLUSIVEDIR" ]; then
- cd "$EXCLUSIVEDIR"
- for i in *; do
- if [ -f "$i" ]; then
- list="${i#* }"
- break
- fi
- done
- fi
- cd "$IFACEDIR"
- for i in $inclusive_interfaces; do
- if [ -f "$i" ] && [ "$list" = "$i" ]; then
- list=
- excl=false
- break
- fi
- done
- ;;
- esac
-
- # If we have an interface ordering list, then use that.
- # It works by just using pathname expansion in the interface directory.
- if [ -n "$1" ]; then
- list="$*"
- $force || report=true
- elif ! $excl; then
- cd "$IFACEDIR"
- for i in $interface_order; do
- [ -f "$i" ] && list="$list $i"
- for ii in "$i":* "$i".*; do
- [ -f "$ii" ] && list="$list $ii"
- done
- done
- for i in $dynamic_order; do
- if [ -e "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then
- list="$list $i"
- fi
- for ii in "$i":* "$i".*; do
- if [ -f "$ii" ] && ! [ -e "$METRICDIR/"*" $ii" ]
- then
- list="$list $ii"
- fi
- done
- done
- # Interfaces have an implicit metric of 0 if not specified.
- for i in *; do
- if [ -f "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then
- list="$list $i"
- fi
- done
- if [ -d "$METRICDIR" ]; then
- cd "$METRICDIR"
- for i in *; do
- [ -f "$i" ] && list="$list ${i#* }"
- done
- fi
+ keys="$(list_keys "$@")"
+ retval=$?
+ if [ "$retval" != 0 ]; then
+ return $retval
fi
-
- cd "$IFACEDIR"
- retval=1
- for i in $(uniqify $list); do
- # Only list interfaces which we really have
- if ! [ -f "$i" ]; then
- if $report; then
- echo "No resolv.conf for interface $i" >&2
- retval=2
- fi
- continue
- fi
-
- if [ "$cmd" = i ] || [ "$cmd" = "-i" ]; then
- printf %s "$i "
- else
- echo_resolv "$i" && echo
- fi
- [ $? = 0 ] && [ "$retval" = 1 ] && retval=0
+ for i in $keys; do
+ echo_resolv "$i" && echo
done
- [ "$cmd" = i ] || [ "$cmd" = "-i" ] && echo
- return $retval
+}
+
+list_private()
+{
+ KEYS=
+ cd "$KEYDIR"
+ if [ -z "$1" ]; then
+ set -- "*"
+ fi
+ for i in $@; do
+ if private_key "$i"; then
+ KEYS="${KEYS}${KEYS:+ }$i"
+ fi
+ done
+ if [ -n "$KEYS" ]; then
+ echo "$KEYS"
+ fi
+}
+
+list_nosearch()
+{
+
+ KEYS=
+ cd "$KEYDIR"
+ if [ -z "$1" ]; then
+ set -- "*"
+ fi
+ for i in $@; do
+ if nosearch_key "$i"; then
+ KEYS="${KEYS}${KEYS:+ }$i"
+ fi
+ done
+ if [ -n "$KEYS" ]; then
+ echo "$KEYS"
+ fi
+}
+
+list_exclusive()
+{
+ KEYS=
+ cd "$KEYDIR"
+ if [ -z "$1" ]; then
+ set -- "*"
+ fi
+ for i in $@; do
+ if exclusive_key "$i"; then
+ KEYS="${KEYS}${KEYS:+ }$i"
+ fi
+ done
+ if [ -n "$KEYS" ]; then
+ echo "$KEYS"
+ fi
}
list_remove()
@@ -558,7 +858,81 @@
echo
}
-replace()
+tolower() {
+ # There is no good way of doing this portably in shell :(
+ # Luckily we are only doing this for domain names which we
+ # know have to be ASCII.
+ # Non ASCII domains *should* be translated to ASCII *before*
+ # we get to this stage.
+ # We could use echo "$@" | tr '[:upper:]' '[:lower:]' but
+ # tr is in /usr/bin and may not be available when data is fed
+ # to resolvconf.
+ # So it's the cost of a pipe + fork vs this slow loop
+ #
+ for word; do
+ # Check if we have any upper to avoid looping per char
+ case "$word" in
+ *[A-Z]*) ;;
+ *) printf "%s " "$word"; continue;;
+ esac
+
+ while [ -n "$word" ]; do
+ # Remove everything except the first character
+ afterchar="${word#?}"
+ # Remove the afterchar to get the first character
+ char="${word%%$afterchar}"
+ # Assign afterchar back to word for looping
+ word="$afterchar"
+
+ # Now enforce lowercase a-z
+ case "$char" in
+ A) char=a;;
+ B) char=b;;
+ C) char=c;;
+ D) char=d;;
+ E) char=e;;
+ F) char=f;;
+ G) char=g;;
+ H) char=h;;
+ I) char=i;;
+ J) char=j;;
+ K) char=k;;
+ L) char=l;;
+ M) char=m;;
+ N) char=n;;
+ O) char=o;;
+ P) char=p;;
+ Q) char=q;;
+ R) char=r;;
+ S) char=s;;
+ T) char=t;;
+ U) char=u;;
+ V) char=v;;
+ W) char=w;;
+ X) char=x;;
+ Y) char=y;;
+ Z) char=z;;
+ esac
+ printf %s "$char"
+ done
+ printf " "
+ done
+ printf "\n"
+}
+
+# Strip any trailing dot from each name as a FQDN does not belong
+# in resolv.conf(5).
+# While DNS is not case sensitive, our labels for building the zones
+# are, so ensure it's lower case.
+process_domain()
+{
+ for word in $(tolower "$@"); do
+ printf "%s " "${word%.}"
+ done
+ printf "\n"
+}
+
+process_resolv()
{
while read -r keyword value; do
for r in $replace; do
@@ -593,6 +967,18 @@
done
val="$val${val:+ }$sub"
done
+ case "$keyword" in
+ \#)
+ case "$val" in
+ "resolv.conf from "*) ;;
+ *) continue;;
+ esac
+ ;;
+ \#*) continue;;
+ esac
+ case "$keyword" in
+ domain|search) val="$(process_domain $val)";;
+ esac
printf "%s %s\n" "$keyword" "$val"
done
}
@@ -605,14 +991,12 @@
SEARCH=
NAMESERVERS=
LOCALNAMESERVERS=
-
+
if [ -n "${name_servers}${search_domains}" ]; then
eval "$(echo_prepend | parse_resolv)"
fi
if [ -z "$VFLAG" ]; then
- IF_EXCLUSIVE=1
- list_resolv -i "$@" >/dev/null || IF_EXCLUSIVE=0
- eval "$(list_resolv -l "$@" | replace | parse_resolv)"
+ eval "$(list_resolv -L "$@" | process_resolv | parse_resolv)"
fi
if [ -n "${name_servers_append}${search_domains_append}" ]; then
eval "$(echo_append | parse_resolv)"
@@ -646,6 +1030,7 @@
newdomains="$newdomains${newdomains:+ }$dn:$newns"
fi
done
+
DOMAIN="$(list_remove domain_blacklist $DOMAIN)"
SEARCH="$(uniqify $SEARCH)"
SEARCH="$(list_remove domain_blacklist $SEARCH)"
@@ -653,21 +1038,30 @@
NAMESERVERS="$(list_remove name_server_blacklist $NAMESERVERS)"
LOCALNAMESERVERS="$(uniqify $LOCALNAMESERVERS)"
LOCALNAMESERVERS="$(list_remove name_server_blacklist $LOCALNAMESERVERS)"
- echo "DOMAIN='$DOMAIN'"
- echo "SEARCH='$SEARCH'"
- echo "NAMESERVERS='$NAMESERVERS'"
- echo "LOCALNAMESERVERS='$LOCALNAMESERVERS'"
- echo "DOMAINS='$newdomains'"
+
+ # Ensure output is quoted for eval
+ printf 'DOMAIN=%s\n' "$(quote "$DOMAIN")"
+ printf 'SEARCH=%s\n' "$(quote "$SEARCH")"
+ printf 'NAMESERVERS=%s\n' "$(quote "$NAMESERVERS")"
+ printf 'LOCALNAMESERVERS=%s\n' "$(quote "$LOCALNAMESERVERS")"
+ printf 'DOMAINS=%s\n' "$(quote "$newdomains")"
}
force=false
+LFLAG=
VFLAG=
-while getopts a:Dd:fhIilm:pRruvVx OPT; do
+while getopts a:C:c:Dd:fhIiLlm:pRruvVx OPT; do
case "$OPT" in
f) force=true;;
h) usage;;
m) IF_METRIC="$OPTARG";;
- p) IF_PRIVATE=1;;
+ p)
+ if [ "$IF_PRIVATE" = 1 ]; then
+ IF_NOSEARCH=1
+ else
+ IF_PRIVATE=1
+ fi
+ ;;
V)
VFLAG=1
if [ "$local_nameservers" = \
@@ -677,19 +1071,23 @@
fi
;;
x) IF_EXCLUSIVE=1;;
- '?') ;;
- *) cmd="$OPT"; iface="$OPTARG";;
+ '?') exit 1;;
+ *)
+ [ "$OPT" != L ] || LFLAG=1
+ cmd="$OPT"; key="$OPTARG";;
esac
done
shift $(($OPTIND - 1))
-args="$iface${iface:+ }$*"
+if [ -n "$key" ]; then
+ set -- "$key" "$@"
+fi
-# -I inits the state dir
-if [ "$cmd" = I ]; then
- if [ -d "$VARDIR" ]; then
- rm -rf "$VARDIR"/*
+if [ -z "$cmd" ]; then
+ if [ "$IF_PRIVATE" = 1 ]; then
+ cmd=p
+ elif [ "$IF_EXCLUSIVE" = 1 ]; then
+ cmd=x
fi
- exit $?
fi
# -D ensures that the listed config file base dirs exist
@@ -698,9 +1096,38 @@
exit $?
fi
-# -l lists our resolv files, optionally for a specific interface
-if [ "$cmd" = l ] || [ "$cmd" = i ]; then
- list_resolv "$cmd" "$args"
+# -i lists which keys have a resolv file
+if [ "$cmd" = i ]; then
+ # If the -L modifier is given, the list is post-processed
+ if [ "$LFLAG" = 1 ]; then
+ cmd="L"
+ fi
+ list_keys "-$cmd" "$@"
+ exit $?
+fi
+
+# -l lists our resolv files, optionally for a specific key
+if [ "$cmd" = l ]; then
+ list_resolv "-$cmd" "$@"
+ exit $?
+fi
+# -L is the same as -l, but post-processed from our config
+if [ "$cmd" = L ]; then
+ list_resolv "-$cmd" "$@" | process_resolv
+ exit $?
+fi
+
+if [ "$cmd" = p ]; then
+ if [ "$IF_NOSEARCH" = 1 ]; then
+ list_nosearch "$@"
+ else
+ list_private "$@"
+ fi
+ exit $?
+fi
+
+if [ "$cmd" = x ]; then
+ list_exclusive "$@"
exit $?
fi
@@ -708,7 +1135,6 @@
if [ "$cmd" = r ] || [ "$cmd" = R ]; then
detect_init || exit 1
if [ "$cmd" = r ]; then
- set -- $args
eval "$RESTARTCMD"
else
echo "$RESTARTCMD" |
@@ -719,30 +1145,36 @@
# Not normally needed, but subscribers should be able to run independently
if [ "$cmd" = v ] || [ -n "$VFLAG" ]; then
- make_vars "$iface"
+ make_vars "$@"
exit $?
fi
# Test that we have valid options
-if [ "$cmd" = a ] || [ "$cmd" = d ]; then
- if [ -z "$iface" ]; then
- usage "Interface not specified"
+case "$cmd" in
+a|d|C|c)
+ if [ -z "$key" ]; then
+ error_exit "Key not specified"
+ fi
+ ;;
+I|u) ;;
+*)
+ if [ -n "$cmd" ] && [ "$cmd" != h ]; then
+ error_exit "Unknown option $cmd"
fi
-elif [ "$cmd" != u ]; then
- [ -n "$cmd" ] && [ "$cmd" != h ] && usage "Unknown option $cmd"
usage
-fi
+ ;;
+esac
if [ "$cmd" = a ]; then
- for x in '/' \\ ' ' '*'; do
- case "$iface" in
- *[$x]*) error_exit "$x not allowed in interface name";;
+ for x in '/' '\' ' ' '*'; do
+ case "$key" in
+ "$x"|"$x"*|*"$x"|*"$x"*) error_exit "$x not allowed in key name";;
esac
done
for x in '.' '-' '~'; do
- case "$iface" in
- [$x]*) error_exit \
- "$x not allowed at start of interface name";;
+ case "$key" in
+ "$x"*) error_exit \
+ "$x not allowed at start of key name";;
esac
done
[ "$cmd" = a ] && [ -t 0 ] && error_exit "No file given via stdin"
@@ -765,15 +1197,15 @@
fi
fi
-if [ ! -d "$IFACEDIR" ]; then
- mkdir -m 0755 -p "$IFACEDIR" || \
- error_exit "Failed to create needed directory $IFACEDIR"
+if [ ! -d "$KEYDIR" ]; then
+ mkdir -m 0755 -p "$KEYDIR" || \
+ error_exit "Failed to create needed directory $KEYDIR"
if [ "$cmd" = d ]; then
# Provide the same error messages as below
if ! ${force}; then
- cd "$IFACEDIR"
- for i in $args; do
- warn "No resolv.conf for interface $i"
+ cd "$KEYDIR"
+ for i in $@; do
+ warn "No resolv.conf for key $i"
done
fi
${force}
@@ -781,7 +1213,7 @@
fi
fi
-# An interface was added, changed, deleted or a general update was called.
+# A key was added, changed, deleted or a general update was called.
# Due to exclusivity we need to ensure that this is an atomic operation.
# Our subscribers *may* need this as well if the init system is sub par.
# As such we spinlock at this point as best we can.
@@ -789,6 +1221,9 @@
# in /usr which we do our very best to operate without.
[ -w "$VARDIR" ] || error_exit "Cannot write to $LOCKDIR"
: ${lock_timeout:=10}
+: ${clear_nopids:=5}
+have_pid=false
+had_pid=false
while true; do
if mkdir "$LOCKDIR" 2>/dev/null; then
trap 'rm -rf "$LOCKDIR";' EXIT
@@ -796,18 +1231,43 @@
echo $$ >"$LOCKDIR/pid"
break
fi
- pid=$(cat "$LOCKDIR/pid")
- if ! kill -0 "$pid"; then
+ pid=$(cat "$LOCKDIR/pid" 2>/dev/null)
+ if [ "$pid" -gt 0 ] 2>/dev/null; then
+ have_pid=true
+ had_pid=true
+ else
+ have_pid=false
+ clear_nopids=$(($clear_nopids - 1))
+ if [ "$clear_nopids" -le 0 ]; then
+ warn "not seen a pid, clearing lock directory"
+ rm -rf "$LOCKDIR"
+ else
+ lock_timeout=$(($lock_timeout - 1))
+ sleep 1
+ fi
+ continue
+ fi
+ if $have_pid && ! kill -0 "$pid"; then
warn "clearing stale lock pid $pid"
rm -rf "$LOCKDIR"
continue
fi
lock_timeout=$(($lock_timeout - 1))
if [ "$lock_timeout" -le 0 ]; then
- error_exit "timed out waiting for lock from pid $pid"
+ if $have_pid; then
+ error_exit "timed out waiting for lock from pid $pid"
+ else
+ if $had_pid; then
+ error_exit "timed out waiting for lock" \
+ "from some pids"
+ else
+ error_exit "timed out waiting for lock"
+ fi
+ fi
fi
sleep 1
done
+unset have_pid had_pid clear_nopids
case "$cmd" in
a)
@@ -816,9 +1276,9 @@
changed=false
changedfile=false
# If what we are given matches what we have, then do nothing
- if [ -e "$IFACEDIR/$iface" ]; then
+ if [ -e "$KEYDIR/$key" ]; then
if [ "$(echo "$resolv")" != \
- "$(cat "$IFACEDIR/$iface")" ]
+ "$(cat "$KEYDIR/$key")" ]
then
changed=true
changedfile=true
@@ -828,21 +1288,21 @@
changedfile=true
fi
- # Set metric and private before creating the interface resolv.conf file
+ # Set metric and private before creating the resolv.conf file
# to ensure that it will have the correct flags
[ ! -d "$METRICDIR" ] && mkdir "$METRICDIR"
- oldmetric="$METRICDIR/"*" $iface"
+ oldmetric="$METRICDIR/"*" $key"
newmetric=
if [ -n "$IF_METRIC" ]; then
# Pad metric to 6 characters, so 5 is less than 10
while [ ${#IF_METRIC} -le 6 ]; do
IF_METRIC="0$IF_METRIC"
done
- newmetric="$METRICDIR/$IF_METRIC $iface"
+ newmetric="$METRICDIR/$IF_METRIC $key"
fi
- rm -f "$METRICDIR/"*" $iface"
+ rm -f "$METRICDIR/"*" $key"
[ "$oldmetric" != "$newmetric" ] &&
- [ "$oldmetric" != "$METRICDIR/* $iface" ] &&
+ [ "$oldmetric" != "$METRICDIR/* $key" ] &&
changed=true
[ -n "$newmetric" ] && echo " " >"$newmetric"
@@ -852,19 +1312,37 @@
[ -e "$PRIVATEDIR" ] && rm "$PRIVATEDIR"
mkdir "$PRIVATEDIR"
fi
- [ -e "$PRIVATEDIR/$iface" ] || changed=true
- [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$iface"
+ [ -e "$PRIVATEDIR/$key" ] || changed=true
+ [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$key"
;;
*)
- if [ -e "$PRIVATEDIR/$iface" ]; then
- rm -f "$PRIVATEDIR/$iface"
+ if [ -e "$PRIVATEDIR/$key" ]; then
+ rm -f "$PRIVATEDIR/$key"
changed=true
fi
;;
esac
+ case "$IF_NOSEARCH" in
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ if [ ! -d "$NOSEARCHDIR" ]; then
+ [ -e "$NOSEARCHDIR" ] && rm "$NOSEARCHDIR"
+ mkdir "$NOSEARCHDIR"
+ fi
+ [ -e "$NOSEARCHDIR/$key" ] || changed=true
+ [ -d "$NOSEARCHDIR" ] && echo " " >"$NOSEARCHDIR/$key"
+ ;;
+ *)
+ if [ -e "$NOSEARCHDIR/$key" ]; then
+ rm -f "$NOSEARCHDIR/$key"
+ changed=true
+ fi
+ ;;
+ esac
+ set +x
+
oldexcl=
- for x in "$EXCLUSIVEDIR/"*" $iface"; do
+ for x in "$EXCLUSIVEDIR/"*" $key"; do
if [ -f "$x" ]; then
oldexcl="$x"
break
@@ -880,7 +1358,7 @@
for x in *; do
[ -f "$x" ] && break
done
- if [ "${x#* }" != "$iface" ]; then
+ if [ "${x#* }" != "$key" ]; then
if [ "$x" = "${x% *}" ]; then
x=10000000
else
@@ -892,7 +1370,7 @@
x=$(($x - 1))
fi
if [ -d "$EXCLUSIVEDIR" ]; then
- echo " " >"$EXCLUSIVEDIR/$x $iface"
+ echo " " >"$EXCLUSIVEDIR/$x $key"
fi
changed=true
fi
@@ -906,34 +1384,80 @@
esac
if $changedfile; then
- printf "%s\n" "$resolv" >"$IFACEDIR/$iface" || exit $?
- elif ! $changed; then
+ printf "%s\n" "$resolv" >"$KEYDIR/$key" || exit $?
+ elif ! $changed && [ ! -e "$VARDIR"/error ]; then
exit 0
fi
unset changed changedfile oldmetric newmetric x oldexcl
;;
d)
- # Delete any existing information about the interface
- cd "$IFACEDIR"
+ # Delete any existing information about the key
+ cd "$KEYDIR"
changed=false
- for i in $args; do
+ for i in $@; do
if [ -e "$i" ]; then
changed=true
elif ! ${force}; then
- warn "No resolv.conf for interface $i"
+ warn "No resolv.conf for key $i"
fi
rm -f "$i" "$METRICDIR/"*" $i" \
"$PRIVATEDIR/$i" \
"$EXCLUSIVEDIR/"*" $i" || exit $?
done
- if ! ${changed}; then
+
+ if ! $changed && [ ! -e "$VARDIR"/error ]; then
# Set the return code based on the forced flag
- ${force}
+ $force
exit $?
fi
unset changed i
;;
+
+C)
+ # Mark key as deprecated
+ [ ! -d "$DEPRECATEDDIR" ] && mkdir "$DEPRECATEDDIR"
+ cd "$DEPRECATEDDIR"
+ changed=false
+ for i in $@; do
+ if [ ! -e "$i" ]; then
+ changed=true
+ echo " " >"$i" || exit $?
+ fi
+ done
+ if ! $changed && [ ! -e "$VARDIR"/error ]; then
+ exit 0
+ fi
+ unset changed i
+ ;;
+
+c)
+ # Mark key as active
+ if [ -d "$DEPRECATEDDIR" ]; then
+ cd "$DEPRECATEDDIR"
+ changed=false
+ for i in $@; do
+ if [ -e "$i" ]; then
+ changed=true
+ rm "$i" || exit $?
+ fi
+ done
+ if ! $changed && [ ! -e "$VARDIR"/error ]; then
+ exit 0
+ fi
+ unset changed i
+ fi
+ ;;
+I)
+ # Init the state dir, keeping our lock and key directories only
+ for i in "$VARDIR"/*; do
+ case "$i" in
+ "$LOCKDIR") ;;
+ "$KEYDIR") rm -rf "$KEYDIR"/*;;
+ *) rm -rf "$i";;
+ esac
+ done
+ ;;
esac
case "${resolvconf:-YES}" in
@@ -947,7 +1471,7 @@
eval "$(make_vars)"
export RESOLVCONF DOMAINS SEARCH NAMESERVERS LOCALNAMESERVERS
-: ${list_resolv:=list_resolv -l}
+: ${list_resolv:=list_resolv -L}
retval=0
# Run scripts in the same directory resolvconf is run from
@@ -955,17 +1479,26 @@
cd "$_PWD"
for script in "$LIBEXECDIR"/*; do
if [ -f "$script" ]; then
- eval script_enabled="\$${script##*/}"
+ script_var="${script##*/}"
+ while [ "${script_var%%-*}" != "$script_var" ]; do
+ script_var="${script_var%%-*}_${script_var#*-}"
+ done
+ eval script_enabled="\$$script_var"
case "${script_enabled:-YES}" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
*) continue;;
esac
if [ -x "$script" ]; then
- "$script" "$cmd" "$iface"
+ "$script" "$cmd" "$key"
else
- (set -- "$cmd" "$iface"; . "$script")
+ (set -- "$cmd" "$key"; . "$script")
fi
retval=$(($retval + $?))
fi
done
+if [ "$retval" = 0 ]; then
+ rm -f "$VARDIR"/error
+else
+ echo "$retval" >"$VARDIR"/error
+fi
exit $retval
diff --git a/contrib/openresolv/resolvectl.in b/contrib/openresolv/resolvectl.in
new file mode 100644
--- /dev/null
+++ b/contrib/openresolv/resolvectl.in
@@ -0,0 +1,159 @@
+#!/bin/sh
+# Copyright (c) 2025 Roy Marples
+# All rights reserved
+
+# resolvectl subscriber for resolvconf
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
+. "@SYSCONFDIR@/resolvconf.conf" || exit 1
+
+case "${resolvectl:-NO}" in
+[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
+*) exit 0;;
+esac
+
+# If we don't have resolvectl or systemd-resolved isn't running then
+# we can't do much.
+# We can't persist our data in /run/systemd/resolve/netif/$ifindex
+# because systemd-resolved keeps it somehow, ie we can't change it
+# once we have inserted it
+if ! [ -d /sys/class/net ] || \
+ ! type resolvectl >/dev/null 2>&1 || \
+ ! pidof systemd-resolved >/dev/null
+then
+ exit 1
+fi
+
+# resolvectl only accepts resolv.conf setup per physical interface
+# although resolvconf has always hinted that the named configuration
+# should be $interface.$protocol, this has never been a fixed requirement.
+# Because resolvectl only accepts one configuration per interface we need
+# to try and merge the resolv.conf's together.
+# Luckily resolvconf makes this easy for us.
+
+# Returns a list of resolvconf entries for a real interface
+get_resolvconf_interfaces() {
+ IFACE="$1"
+ [ -d /sys/class/net/"$IFACE" ] || return 1
+
+ IFACES=
+ for IFACE_PROTO in $(@SBINDIR@/resolvconf -Li "$IFACE" "$IFACE.*" 2>/dev/null); do
+ # ens5 will work with ens5.dhcp and ens5.ra,
+ # but not ens5.5 or ens5.5.dhcp
+ if [ "$IFACE_PROTO" != "$IFACE" ]; then
+ # Ensure that ens5.5.dhcp doesn't work for ens5
+ if [ "${IFACE_PROTO%.*}" != "$IFACE" ]; then
+ continue
+ fi
+ # Ensure that ens5.dhcp isn't a real interface
+ # as ens5.5 likely is and the .5 matches the .dhcp
+ if [ -d /sys/class/net/"$IFACE_PROTO" ]; then
+ continue
+ fi
+ fi
+ IFACES="$IFACES${IFACES:+ }$IFACE_PROTO"
+ done
+ echo "$IFACES"
+}
+
+# For the given interface, apply a list of resolvconf entries
+apply_resolvconf() {
+ IFACE="$1"
+ shift
+
+ if [ -z "$1" ]; then
+ resolvectl revert "$IFACE"
+ return
+ fi
+
+ # Set the default-route property first to avoid leakage.
+ # If any entry is private, the whole interface has to be private.
+ # If a more granular approach is needed, consider using the
+ # systemd-resolved subscriber instead which supports DNS delegates.
+ if [ -n "$(@SBINDIR@/resolvconf -p $@)" ]; then
+ resolvectl default-route "$IFACE" false
+ else
+ resolvectl default-route "$IFACE" true
+ fi
+
+ # Now set domain and dns
+ DOMAIN=$(@SBINDIR@/resolvconf -L $@ 2>/dev/null | sed -n -e "s/domain //p" -e "s/search //p")
+ NS=$(@SBINDIR@/resolvconf -L $@ 2>/dev/null | sed -n -e "s/nameserver //p")
+ if [ -n "$DOMAIN" ]; then
+ # If any entry is marked as not searchable, we mark all the
+ # domains as non searchable.
+ # If a more granular approach is needed, consider using the
+ # systemd-resolved subscriber instead which supports DNS delegates.
+ if [ -n "$(@SBINDIR@/resolvconf -pp $@)" ]; then
+ ND=
+ for d in $DOMAIN; do
+ ND="$ND${ND:+ }~$d"
+ done
+ DOMAIN="$ND"
+ fi
+ resolvectl domain "$IFACE" $DOMAIN
+ else
+ resolvectl domain "$IFACE" ""
+ fi
+ if [ -n "$NS" ]; then
+ resolvectl dns "$IFACE" $NS
+ else
+ resolvectl dns "$IFACE" ""
+ fi
+}
+
+# To get the full features of resolvconf, we need to work out each interface
+# for every resolvconf addition and deletion
+# This is because resolvconf.conf might have changed OR an exclusive
+# interface deleted which makes other interfaces visible.
+cd /sys/class/net
+for IFACE in *; do
+ if [ "$IFACE" = lo ]; then
+ # systemd-resolved doesn't work with lo
+ continue
+ fi
+
+ IFACES=$(get_resolvconf_interfaces "$IFACE")
+ apply_resolvconf "$IFACE" $IFACES
+done
+
+# warn about resolv.conf with no matching interface
+FAILED=
+for IFACE_PROTO in $(@SBINDIR@/resolvconf -Li); do
+ IFACE="${IFACE_PROTO%.*}"
+ if [ "$IFACE" = lo ]; then
+ # Don't warn about loopback interface as that is typically
+ # used to configure libc for a nameserver on it and the libc
+ # subscriber will process that just fine.
+ continue
+ fi
+
+ if ! [ -d "/sys/class/net/$IFACE" ]; then
+ FAILED="$FAILED${FAILED:+ }$IFACE_PROTO"
+ fi
+done
+if [ -n "$FAILED" ]; then
+ echo "Could not apply resolv.conf to resolvectl: $FAILED" >&2
+fi
diff --git a/contrib/openresolv/unbound.in b/contrib/openresolv/systemd-resolved.in
copy from contrib/openresolv/unbound.in
copy to contrib/openresolv/systemd-resolved.in
--- a/contrib/openresolv/unbound.in
+++ b/contrib/openresolv/systemd-resolved.in
@@ -1,8 +1,8 @@
#!/bin/sh
-# Copyright (c) 2009-2016 Roy Marples
+# Copyright (c) 2025 Roy Marples
# All rights reserved
-# unbound subscriber for resolvconf
+# systemd-resolved subscriber for resolvconf
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -26,72 +26,71 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-unbound_insecure=
-
[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
. "@SYSCONFDIR@/resolvconf.conf" || exit 1
-[ -z "$unbound_conf" ] && exit 0
-[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
+
+case "${systemd_resolved:-NO}" in
+[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
+*) exit 0;;
+esac
+
+[ -n "$RESOLVCONF" ] || eval "$(@SBINDIR@/resolvconf -v)"
NL="
"
-: ${unbound_pid:=/var/run/unbound.pid}
-: ${unbound_service:=unbound}
-newconf="# Generated by resolvconf$NL"
+: ${systemd_resolved_conf:=/run/systemd/resolved.conf.d/60-resolvconf.conf}
+: ${systemd_delegate_dir:=/run/systemd/dns-delegate.d}
+# Try to ensure that config dirs exist
+if command -v config_mkdirs >/dev/null 2>&1; then
+ config_mkdirs "$systemd_resolved_conf" "$systemd_delegate_dir/x"
+else
+ @SBINDIR@/resolvconf -D "$systemd_resolved_conf" "$systemd_delegate_dir/x"
+fi
+
+header="# Generated by resolvconf$NL"
+header="${header}$NL"
+header="${header}[Resolve]$NL"
+
+conf="$header"
+# We emit blank values to force them to reset on SIGHUP
+conf="${conf}DNS=$NAMESERVERS$NL"
+# Indicate these nameservers are for all domain lookups by using ~.
+conf="${conf}Domains=$SEARCH${NAMESERVERS:+ ~.}$NL"
+
+printf %s "$conf" >"$systemd_resolved_conf"
+
+# DNS Delegates requires https://github.com/systemd/systemd/pull/34368
+rm -f "$systemd_delegate_dir/resolvconf-"*".dns-delegate"
+header="# Generated by resolvconf$NL"
+header="${header}$NL"
+header="${header}[Delegate]$NL"
for d in $DOMAINS; do
dn="${d%%:*}"
ns="${d#*:}"
- case "$unbound_insecure" in
- [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
- newconf="$newconf${NL}server:$NL"
- newconf="$newconf domain-insecure: \"$dn\"$NL"
- ;;
- esac
- newconf="$newconf${NL}forward-zone:$NL name: \"$dn\"$NL"
+ dconf="${header}Domains="
+ search=false
+ for sd in $SEARCH; do
+ if [ "$sd" = "$dn" ]; then
+ search=true
+ break
+ fi
+ done
+ if ! $search; then
+ dconf="${dconf}~"
+ fi
+ dconf="${dconf}$dn$NL"
+ dconf="${dconf}DNS="
while [ -n "$ns" ]; do
- newconf="$newconf forward-addr: ${ns%%,*}$NL"
+ dconf="$dconf${ns%%,*} "
[ "$ns" = "${ns#*,}" ] && break
ns="${ns#*,}"
done
+ dconf="$dconf$NL"
+ printf %s "$dconf" >"$systemd_delegate_dir/resolvconf-$dn.dns-delegate"
done
-if [ -n "$NAMESERVERS" ]; then
- newconf="$newconf${NL}forward-zone:$NL name: \".\"$NL"
- for n in $NAMESERVERS; do
- newconf="$newconf forward-addr: $n$NL"
- done
-fi
-
-# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
- config_mkdirs "$unbound_conf"
-else
- @SBINDIR@/resolvconf -D "$unbound_conf"
-fi
-
-restart_unbound()
-{
- if [ -n "$unbound_restart" ]; then
- eval $unbound_restart
- elif [ -n "$RESTARTCMD" ]; then
- set -- ${unbound_service}
- eval "$RESTARTCMD"
- else
- @SBINDIR@/resolvconf -r ${unbound_service}
- fi
-}
-
-if [ ! -f "$unbound_conf" ] || \
- [ "$(cat "$unbound_conf")" != "$(printf %s "$newconf")" ]
-then
- printf %s "$newconf" >"$unbound_conf"
- # If we can't sent a HUP then force a restart
- if [ -s "$unbound_pid" ]; then
- if ! kill -HUP $(cat "$unbound_pid") 2>/dev/null; then
- restart_unbound
- fi
- else
- restart_unbound
- fi
+pid=$(pidof systemd-resolved)
+if [ -n "$pid" ]; then
+ kill -HUP $pid
fi
diff --git a/contrib/openresolv/unbound.in b/contrib/openresolv/unbound.in
--- a/contrib/openresolv/unbound.in
+++ b/contrib/openresolv/unbound.in
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (c) 2009-2016 Roy Marples
+# Copyright (c) 2009-2023 Roy Marples
# All rights reserved
# unbound subscriber for resolvconf
@@ -27,6 +27,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
unbound_insecure=
+unbound_private=
[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
. "@SYSCONFDIR@/resolvconf.conf" || exit 1
@@ -42,13 +43,29 @@
for d in $DOMAINS; do
dn="${d%%:*}"
ns="${d#*:}"
+ create_unbound_insecure=false
+ create_unbound_private=false
case "$unbound_insecure" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
- newconf="$newconf${NL}server:$NL"
- newconf="$newconf domain-insecure: \"$dn\"$NL"
- ;;
+ create_unbound_insecure=true ;;
esac
+ case "$unbound_private" in
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ create_unbound_private=true ;;
+ esac
+ if $create_unbound_insecure || $create_unbound_private; then
+ newconf="$newconf${NL}server:$NL"
+ if $create_unbound_insecure; then
+ newconf="$newconf domain-insecure: \"$dn\"$NL"
+ fi
+ if $create_unbound_private; then
+ newconf="$newconf private-domain: \"$dn\"$NL"
+ fi
+ fi
newconf="$newconf${NL}forward-zone:$NL name: \"$dn\"$NL"
+ if [ -n "$unbound_forward_zone_options" ]; then
+ newconf="$newconf $unbound_forward_zone_options${NL}"
+ fi
while [ -n "$ns" ]; do
newconf="$newconf forward-addr: ${ns%%,*}$NL"
[ "$ns" = "${ns#*,}" ] && break
@@ -58,13 +75,16 @@
if [ -n "$NAMESERVERS" ]; then
newconf="$newconf${NL}forward-zone:$NL name: \".\"$NL"
+ if [ -n "$unbound_forward_zone_options" ]; then
+ newconf="$newconf $unbound_forward_zone_options${NL}"
+ fi
for n in $NAMESERVERS; do
newconf="$newconf forward-addr: $n$NL"
done
fi
# Try to ensure that config dirs exist
-if type config_mkdirs >/dev/null 2>&1; then
+if command -v config_mkdirs >/dev/null 2>&1; then
config_mkdirs "$unbound_conf"
else
@SBINDIR@/resolvconf -D "$unbound_conf"

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 12, 11:47 PM (11 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31341395
Default Alt Text
D56269.diff (79 KB)

Event Timeline