git: 266022bf0b60 - stable/14 - contrib/openresolv: MFV openresolv 3.17.4

From: Siva Mahadevan <siva_at_FreeBSD.org>
Date: Tue, 07 Jul 2026 01:34:11 UTC
The branch stable/14 has been updated by siva:

URL: https://cgit.FreeBSD.org/src/commit/?id=266022bf0b6092a0d052c3faa10130755be21ad5

commit 266022bf0b6092a0d052c3faa10130755be21ad5
Author:     Siva Mahadevan <siva@FreeBSD.org>
AuthorDate: 2026-04-28 19:25:49 +0000
Commit:     Siva Mahadevan <siva@FreeBSD.org>
CommitDate: 2026-07-07 01:29:01 +0000

    contrib/openresolv: MFV openresolv 3.17.4
    
    Reviewed by:    pfg
    Approved by:    lwhsu (mentor)
    Differential Revision:  https://reviews.freebsd.org/D56269
    
    (cherry picked from commit cb0e3a5fba5fe48607db8c1042bfe6a1164e0db7)
---
 contrib/openresolv/LICENSE              |   2 +-
 contrib/openresolv/Makefile             |  54 +-
 contrib/openresolv/README.md            |   9 +-
 contrib/openresolv/avahi-daemon.in      |  32 ++
 contrib/openresolv/configure            |   4 +-
 contrib/openresolv/dnsmasq.in           |   8 +-
 contrib/openresolv/libc.in              |  82 ++-
 contrib/openresolv/mdnsd.in             |  32 ++
 contrib/openresolv/named.in             |   4 +-
 contrib/openresolv/pdns_recursor.in     |   4 +-
 contrib/openresolv/pdnsd.in             |  10 +-
 contrib/openresolv/resolvconf.8.in      | 226 +++++---
 contrib/openresolv/resolvconf.conf.5.in | 182 ++++--
 contrib/openresolv/resolvconf.in        | 947 +++++++++++++++++++++++++-------
 contrib/openresolv/resolvectl.in        | 159 ++++++
 contrib/openresolv/systemd-resolved.in  |  96 ++++
 contrib/openresolv/unbound.in           |  30 +-
 17 files changed, 1484 insertions(+), 397 deletions(-)

diff --git a/contrib/openresolv/LICENSE b/contrib/openresolv/LICENSE
index 758aec338057..19785ddb1e0f 100644
--- 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
index 6cfa6e4ea072..ba9a75d35f22 100644
--- a/contrib/openresolv/Makefile
+++ b/contrib/openresolv/Makefile
@@ -5,6 +5,9 @@ _CONFIG_MK!=	test -e config.mk && echo config.mk || echo config-null.mk
 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 @@ BINMODE?=	0755
 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_RCDIR=		-e 's:@RCDIR@:${RCDIR}:g'
 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 @@ clean:
 	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 @@ proginstall: ${TARGET}
 	${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 @@ dist-inst:
 	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 @@ _import-src:
 	@${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
index 739cc73356cb..50e54ced93ef 100644
--- a/contrib/openresolv/README.md
+++ b/contrib/openresolv/README.md
@@ -37,7 +37,7 @@ Here's some reasons:
 
 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 @@ openresolv ships with helpers for:
   *  [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/avahi-daemon.in b/contrib/openresolv/avahi-daemon.in
new file mode 100644
index 000000000000..cdac44fe8234
--- /dev/null
+++ b/contrib/openresolv/avahi-daemon.in
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (c) 2007-2023 Roy Marples
+# All rights reserved
+
+# 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
+# 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.
+
+: ${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
index c9422b74b69c..50fe74da8baa
--- a/contrib/openresolv/configure
+++ b/contrib/openresolv/configure
@@ -39,7 +39,7 @@ for x do
 	--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 @@ dragonfly*)
 	: ${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
index 8b51866dca25..ae33f094b649 100644
--- 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 @@ for d in $DOMAINS; do
 						empty=true
 						continue
 					fi
-					i=$(($i + 1))
+					i=$((i + 1))
 					while [ ${#addr} -lt 4 ]; do
 						addr="0${addr}"
 					done
@@ -118,7 +118,7 @@ for d in $DOMAINS; do
 					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 @@ else
 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
index 3651d2acba40..78fe86ce00cd 100644
--- 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 @@ elif [ -d "$SYSCONFDIR"/resolvconf ]; then
 	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 @@ then
 	resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.tail)"
 fi
 
-backup=true
 signature="# Generated by resolvconf"
- 
+
 uniqify()
 {
 	result=
@@ -123,15 +139,14 @@ uniqify()
 
 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 @@ esac
 
 # 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/mdnsd.in b/contrib/openresolv/mdnsd.in
new file mode 100644
index 000000000000..3b01cd459f16
--- /dev/null
+++ b/contrib/openresolv/mdnsd.in
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (c) 2007-2023 Roy Marples
+# All rights reserved
+
+# 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
+# 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.
+
+: ${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
index e5b5a91ee77a..978eb98eafa4 100644
--- 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 @@ for d in $DOMAINS; do
 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
index f3632e000385..710456894652 100644
--- 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 @@ for d in $DOMAINS; do
 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
index 971d90d26a1a..149808c09668 100644
--- 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 @@ remove_markers()
 	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 @@ remove_markers()
 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 @@ newresolv="# Generated by resolvconf$NL"
 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
index fa00582976d8..f29d272d71e6 100644
--- 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 @@ file to
 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 @@ then
 .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
-.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,
+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
-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 @@ for how to configure
 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 key
+arguments to clean up the
+.Pa resolv.conf
+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 d Ar interface.*
-arguments to delete the
+.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
-file(s) for all the
-.Ar protocols
-on the
-.Ar interface .
+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 @@ Force
 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 @@ except that only the information configured in
 .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 @@ for details on these lists.
 .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 @@ option is not present then we use
 .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 @@ Directory of subscribers which are run after the libc subscriber is run.
 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 @@ resolvconf, as written by Thomas Hood.
 .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
index 1b0c47160845..4501221be84b 100644
--- 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 @@ Set to NO to disable
 .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
*** 2036 LINES SKIPPED ***