aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile66
-rw-r--r--README11
-rw-r--r--configure186
-rw-r--r--dnsmasq.in125
-rw-r--r--libc.in168
-rw-r--r--named.in94
-rw-r--r--pdnsd.in153
-rw-r--r--resolvconf.8.in240
-rw-r--r--resolvconf.conf7
-rw-r--r--resolvconf.conf.5.in187
-rw-r--r--resolvconf.in421
-rw-r--r--unbound.in69
12 files changed, 1727 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000000..e4e3498ac9f4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,66 @@
+include config.mk
+
+NAME= openresolv
+VERSION= 3.4.1
+PKG= ${NAME}-${VERSION}
+
+INSTALL?= install
+SED?= sed
+
+BINMODE?= 0755
+DOCMODE?= 0644
+MANMODE?= 0444
+
+RESOLVCONF= resolvconf resolvconf.8 resolvconf.conf.5
+SUBSCRIBERS= libc dnsmasq named pdnsd unbound
+TARGET= ${RESOLVCONF} ${SUBSCRIBERS}
+SRCS= ${TARGET:C,$,.in,} # pmake
+SRCS:= ${TARGET:=.in} # gmake
+
+SED_PREFIX= -e 's:@PREFIX@:${PREFIX}:g'
+SED_SYSCONFDIR= -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g'
+SED_LIBEXECDIR= -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g'
+SED_VARDIR= -e 's:@VARDIR@:${VARDIR}:g'
+SED_RCDIR= -e 's:@RCDIR@:${RCDIR}:g'
+SED_RESTARTCMD= -e 's:@RESTARTCMD \(.*\)@:${RESTARTCMD}:g'
+
+.SUFFIXES: .in
+
+all: ${TARGET}
+
+.in:
+ ${SED} ${SED_PREFIX} ${SED_SYSCONFDIR} ${SED_LIBEXECDIR} \
+ ${SED_VARDIR} ${SED_RCDIR} ${SED_RESTARTCMD} \
+ $< > $@
+
+clean:
+ rm -f ${TARGET} openresolv-${VERSION}.tar.bz2
+
+distclean: clean
+ rm -f config.mk
+
+installdirs:
+
+install: ${TARGET}
+ ${INSTALL} -d ${DESTDIR}${SBINDIR}
+ ${INSTALL} -m ${BINMODE} resolvconf ${DESTDIR}${SBINDIR}
+ ${INSTALL} -d ${DESTDIR}${SYSCONFDIR}
+ test -e ${DESTDIR}${SYSCONFDIR}/resolvconf.conf || \
+ ${INSTALL} -m ${DOCMODE} resolvconf.conf ${DESTDIR}${SYSCONFDIR}
+ ${INSTALL} -d ${DESTDIR}${LIBEXECDIR}
+ ${INSTALL} -m ${DOCMODE} ${SUBSCRIBERS} ${DESTDIR}${LIBEXECDIR}
+ ${INSTALL} -d ${DESTDIR}${MANDIR}/man8
+ ${INSTALL} -m ${MANMODE} resolvconf.8 ${DESTDIR}${MANDIR}/man8
+ ${INSTALL} -d ${DESTDIR}${MANDIR}/man5
+ ${INSTALL} -m ${MANMODE} resolvconf.conf.5 ${DESTDIR}${MANDIR}/man5
+
+import:
+ rm -rf /tmp/${PKG}
+ ${INSTALL} -d /tmp/${PKG}
+ cp README ${SRCS} /tmp/${PKG}
+
+dist: import
+ cp configure Makefile resolvconf.conf /tmp/${PKG}
+ tar cvjpf ${PKG}.tar.bz2 -C /tmp ${PKG}
+ rm -rf /tmp/${PKG}
+ ls -l ${PKG}.tar.bz2
diff --git a/README b/README
new file mode 100644
index 000000000000..b4042b0e81a5
--- /dev/null
+++ b/README
@@ -0,0 +1,11 @@
+openresolv is a resolvconf implementation which manages resolv.conf
+You can find the latest version at http://roy.marples.name/projects/openresolv
+It is written and maintained by Roy Marples <roy@marples.name>
+
+This resolvconf implementation, along with its subscribers, work with a
+POSIX compliant shell and userland utilities. It is designed to work without
+tools such as sed as it *has* to work without /usr being available.
+
+On systems where resolvconf is expected to be used before /var/run is available
+for writing, you can configure openresolv to write somewhere else, like say a
+ramdisk.
diff --git a/configure b/configure
new file mode 100644
index 000000000000..39bdddb65412
--- /dev/null
+++ b/configure
@@ -0,0 +1,186 @@
+#!/bin/sh
+# Try and be like autotools configure, but without autotools
+
+# Ensure that we do not inherit these from env
+OS=
+BUILD=
+HOST=
+TARGET=
+RESTARTCMD=
+RCDIR=
+
+for x; do
+ opt=${x%%=*}
+ var=${x#*=}
+ case "$opt" in
+ --os|OS) OS=$var;;
+ --with-cc|CC) CC=$var;;
+ --debug) DEBUG=$var;;
+ --disable-debug) DEBUG=no;;
+ --enable-debug) DEBUG=yes;;
+ --prefix) prefix=$var;;
+ --sysconfdir) SYSCONFDIR=$var;;
+ --bindir|--sbindir) SBINDIR=$var;;
+ --libexecdir) LIBEXECDIR=$var;;
+ --statedir|--localstatedir) STATEDIR=$var;;
+ --dbdir) DBDIR=$var;;
+ --rundir) RUNDIR=$var;;
+ --mandir) MANDIR=$var;;
+ --with-ccopts|CFLAGS) CFLAGS=$var;;
+ CPPFLAGS) CPPFLAGS=$var;;
+ --build) BUILD=$var;;
+ --host) HOST=$var;;
+ --target) TARGET=$var;;
+ --libdir) LIBDIR=$var;;
+ --restartcmd) RESTARTCMD=$var;;
+ --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;;
+ *) echo "$0: WARNING: unknown option $opt" >&2;;
+ esac
+done
+
+: ${SED:=sed}
+
+: ${PREFIX:=$prefix}
+: ${SYSCONFDIR:=$PREFIX/etc}
+: ${SBINDIR:=$PREFIX/sbin}
+: ${LIBEXECDIR:=$PREFIX/libexec}
+: ${STATEDIR:=/var}
+: ${RUNDIR:=$STATEDIR/run}
+: ${MANDIR:=${PREFIX:-/usr}/share/man}
+
+eval SYSCONFDIR="$SYSCONFDIR"
+eval SBINDIR="$SBINDIR"
+eval LIBEXECDIR="$LIBEXECDIR/resolvconf"
+eval VARDIR="$RUNDIR/resolvconf"
+eval MANDIR="$MANDIR"
+
+CONFIG_MK=config.mk
+
+if [ -z "$BUILD" ]; then
+ BUILD=`uname -m`-`uname -s | tr '[:upper:]' '[:lower:]'`
+fi
+if [ -z "$HOST" ]; then
+ [ -z "$TARGET" ] && TARGET=$BUILD
+ HOST=$TARGET
+fi
+if [ -z "$TARGET" ]; then
+ [ -z "$HOST" ] && HOST=$BUILD
+ TARGET=$HOST
+fi
+
+# Debian and Slackware have linux in different places when dealing with
+# autoconf, so we deal with that here.
+if [ -z "$OS" ]; then
+ case "$TARGET" in
+ *-linux-*|linux-*|*-linux|linux) OS=linux;;
+ esac
+fi
+
+if [ -z "$OS" ]; then
+ # Derive OS from cpu-manufacturer-os-kernel
+ CPU=${TARGET%%-*}
+ REST=${TARGET#*-}
+ if [ "$CPU" != "$REST" ]; then
+ MANU=${REST%%-*}
+ REST=${REST#*-}
+ if [ "$MANU" != "$REST" ]; then
+ OS=${REST%%-*}
+ REST=${REST#*-}
+ if [ "$OS" != "$REST" ]; then
+ KERNEL=${REST%%-*}
+ else
+ # 3 tupple
+ KERNEL=$OS
+ OS=$MANU
+ MANU=
+ fi
+ else
+ # 2 tupple
+ OS=$MANU
+ MANU=
+ fi
+ fi
+fi
+
+echo "Configuring openresolv for ... $OS"
+rm -rf $CONFIG_MK
+echo "# $OS" >$CONFIG_MK
+
+for x in SYSCONFDIR SBINDIR LIBEXECDIR VARDIR MANDIR; do
+ eval v=\$$x
+ # Make files look nice for import
+ l=$((10 - ${#x}))
+ unset t
+ [ $l -gt 3 ] && t=" "
+ echo "$x=$t $v" >>$CONFIG_MK
+done
+
+if [ -e /etc/arch-release -a -d /etc/rc.d ]; then
+ echo "Overriding service status check for Arch Linux"
+ RCDIR=/etc/rc.d
+ RESTARTCMD="[ -e /var/run/daemons/\1 ] \&\& /etc/rc.d/\1 restart"
+ echo "yes"
+fi
+
+if [ -z "$RESTARTCMD" ]; then
+ printf "Checking for OpenRC ... "
+ if [ -x /sbin/rc-service ]; then
+ RESTARTCMD="/sbin/rc-service -e \1 \&\& /sbin/rc-service \1 -- -Ds restart"
+ echo "yes"
+ else
+ echo "no"
+ fi
+fi
+if [ -z "$RESTARTCMD" ]; then
+ printf "Checking for invoke-rc.d ... "
+ if [ -x /usr/sbin/invoke-rc.d ]; then
+ RCDIR=/etc/init.d
+ RESTARTCMD="/usr/sbin/invoke-rc.d --quiet \1 status >/dev/null 2>\&1 \&\& /usr/sbin/invoke-rc.d \1 restart"
+ echo "yes"
+ else
+ echo "no"
+ fi
+fi
+if [ -z "$RESTARTCMD" ]; then
+ printf "Checking for service ... "
+ if [ -x /sbin/service ]; then
+ RCDIR=/etc/init.d
+ RESTARTCMD="/sbin/service \1 \&\& /sbin/service \1 restart"
+ echo "yes"
+ else
+ echo "no"
+ fi
+fi
+if [ -z "$RESTARTCMD" ]; then
+ for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do
+ printf "Checking for $x ... "
+ if [ -d $x ]; then
+ RCDIR=$x
+ RESTARTCMD="$x/\1 status >/dev/null 2>\&1 \&\& $x/\1 restart"
+ echo "yes"
+ break
+ else
+ echo "no"
+ fi
+ done
+fi
+
+if [ -z "$RESTARTCMD" ]; then
+ echo "WARNING! No means of interacting with system services detected!"
+ exit 1
+fi
+
+echo "RCDIR= $RCDIR" >>$CONFIG_MK
+# Work around bug in the dash shell as "echo 'foo \1'" does bad things
+printf "%s\n" "RESTARTCMD= $RESTARTCMD" >>$CONFIG_MK
+
+echo
+echo " SYSCONFDIR = $SYSCONFDIR"
+echo " SBINDIR = $SBINDIR"
+echo " LIBEXECDIR = $LIBEXECDIR"
+echo " VARDIR = $RUNDIR"
+echo " MANDIR = $MANDIR"
+echo
diff --git a/dnsmasq.in b/dnsmasq.in
new file mode 100644
index 000000000000..167886628303
--- /dev/null
+++ b/dnsmasq.in
@@ -0,0 +1,125 @@
+#!/bin/sh
+# Copyright (c) 2007-2009 Roy Marples
+# All rights reserved
+
+# dnsmasq 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
+[ -z "$dnsmasq_conf" -a -z "$dnsmasq_resolv" ] && exit 0
+[ -z "$RESOLVCONF" ] && eval "$(@PREFIX@/sbin/resolvconf -v)"
+
+: ${dnsmasq_pid:=/var/run/dnsmasq.pid}
+[ -s "$dnsmasq_pid" ] || dnsmasq_pid=/var/run/dnsmasq/dnsmasq.pid
+: ${dnsmasq_service:=dnsmasq}
+: ${dnsmasq_restart:=@RESTARTCMD ${dnsmasq_service}@}
+newconf="# Generated by resolvconf\n"
+newresolv="$newconf"
+
+# Using dbus means that we never have to restart the daemon
+# This is important as it means we should not drop DNS queries
+# whilst changing DNS options around. However, dbus support is optional
+# so we need to validate a few things first.
+# Check for DBus support in the binary
+dbus=false
+: ${dbus_pid:=/var/run/dbus/dbus.pid}
+[ -s "$dbus_pid" ] || dbus_pid=/var/run/dbus.pid
+[ -s "$dbus_pid" ] || dbus_pid=/var/run/dbus/pid
+if [ -s "$dbus_pid" -a -s "$dnsmasq_pid" ]; then
+ if dnsmasq --version 2>/dev/null | \
+ grep -q "^Compile time options.*[[:space:]]DBus[[:space:]]"
+ then
+ # Sanity - check that dnsmasq and dbus are running
+ if kill -0 $(cat "$dbus_pid") 2>/dev/null && \
+ kill -0 $(cat "$dnsmasq_pid") 2>/dev/null
+ then
+ dbus=true
+ newconf="$newconf\n# Domain specific servers will"
+ newconf="$newconf be sent over dbus\nenable-dbus\n"
+ fi
+ fi
+fi
+
+for n in $NAMESERVERS; do
+ newresolv="${newresolv}nameserver $n\n"
+done
+
+dbusdest=
+for d in $DOMAINS; do
+ dn="${d%%:*}"
+ ns="${d#*:}"
+ while [ -n "$ns" ]; do
+ if $dbus; then
+ SIFS=${IFS-y} OIFS=$IFS
+ IFS=.
+ set -- ${ns%%,*}
+ num="0x$(printf "%02x" $1 $2 $3 $4)"
+ if [ "$SIFS" = yi ]; then
+ unset IFS
+ else
+ IFS=$OIFS
+ fi
+ dbusdest="$dbusdest uint32:$(printf "%u" $num)"
+ dbusdest="$dbusdest string:$dn"
+ else
+ newconf="${newconf}server=/$dn/${ns%%,*}\n"
+ fi
+ [ "$ns" = "${ns#*,}" ] && break
+ ns="${ns#*,}"
+ done
+done
+
+changed=false
+if [ -n "$dnsmasq_conf" ]; then
+ if [ ! -f "$dnsmasq_conf" ] || \
+ [ "$(cat "$dnsmasq_conf")" != "$(printf "$newconf")" ]
+ then
+ changed=true
+ printf "$newconf" >"$dnsmasq_conf"
+ fi
+fi
+if [ -n "$dnsmasq_resolv" ]; then
+ if [ -f "$dnsmasq_resolv" ]; then
+ if [ "$(cat "$dnsmasq_resolv")" != "$(printf "$newresolv")" ]
+ then
+ changed=true
+ printf "$newresolv" >"$dnsmasq_resolv"
+ fi
+ else
+ # dnsmasq polls this file so no need to set changed=true
+ printf "$newresolv" >"$dnsmasq_resolv"
+ fi
+fi
+
+if $changed; then
+ eval $dnsmasq_restart
+fi
+if $dbus; then
+ $changed || kill -HUP $(cat "$dnsmasq_pid")
+ # Send even if empty so old servers are cleared
+ dbus-send --system --dest=uk.org.thekelleys.dnsmasq \
+ /uk/org/thekelleys/dnsmasq uk.org.thekelleys.SetServers \
+ $dbusdest
+fi
diff --git a/libc.in b/libc.in
new file mode 100644
index 000000000000..4ceb0d2d038f
--- /dev/null
+++ b/libc.in
@@ -0,0 +1,168 @@
+#!/bin/sh
+# Copyright (c) 2007-2009 Roy Marples
+# All rights reserved
+
+# libc 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.
+
+SYSCONFDIR=@SYSCONFDIR@
+LIBEXECDIR=@LIBEXECDIR@
+VARDIR=@VARDIR@
+IFACEDIR="$VARDIR/interfaces"
+
+# sed may not be available, and this is faster on small files
+key_get_value()
+{
+ local key="$1" value= x= line=
+
+ shift
+ if [ $# -eq 0 ]; then
+ while read line; do
+ case "$line" in
+ "$key"*) echo "${line##$key}";;
+ esac
+ done
+ else
+ for x; do
+ while read line; do
+ case "$line" in
+ "$key"*) echo "${line##$key}";;
+ esac
+ done < "$x"
+ done
+ fi
+}
+
+# Support original resolvconf configuration layout
+# as well as the openresolv config file
+if [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
+ . "$SYSCONFDIR"/resolvconf.conf
+elif [ -d "$SYSCONFDIR"/resolvconf ]; then
+ SYSCONFDIR="$SYSCONFDIR/resolvconf/resolv.conf.d"
+ base="$SYSCONFDIR/resolv.conf.d/base"
+ if [ -f "$base" ]; then
+ name_servers="$(key_get_value "nameserver " "$base")"
+ search_domains="$(key_get_value "search " "$base")"
+ if [ -z "$search_domains" ]; then
+ search_domains="$(key_get_value "domain " "$base")"
+ fi
+ resolv_conf_options="$(key_get_value "options " "$base")"
+ fi
+ if [ -f "$SYSCONFDIR"/resolv.conf.d/head ]; then
+ resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.d/head)"
+ fi
+ if [ -f "$SYSCONFDIR"/resolv.conf.d/tail ]; then
+ resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.d/tail)"
+ fi
+fi
+: ${resolv_conf:=/etc/resolv.conf}
+: ${libc_service:=nscd}
+: ${libc_restart:=@RESTARTCMD ${libc_service}@}
+: ${list_resolv:=@PREFIX@/sbin/resolvconf -l}
+if [ "${resolv_conf_head-x}" = x -a -f "$SYSCONFDIR"/resolv.conf.head ]; then
+ resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.head)"
+fi
+if [ "${resolv_conf_tail-x}" = x -a -f "$SYSCONFDIR"/resolv.conf.tail ]; then
+ resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.tail)"
+fi
+
+uniqify()
+{
+ local result=
+ while [ -n "$1" ]; do
+ case " $result " in
+ *" $1 "*);;
+ *) result="$result $1";;
+ esac
+ shift
+ done
+ echo "${result# *}"
+}
+
+case "${resolv_conf_passthrough:-NO}" in
+[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ newest=
+ for conf in "$IFACEDIR"/*; do
+ if [ -z "$newest" -o "$conf" -nt "$newest" ]; then
+ newest="$conf"
+ fi
+ done
+ [ -z "$newest" ] && exit 0
+ newconf="$(cat "$newest")\n"
+ ;;
+*)
+ [ -z "$RESOLVCONF" ] && eval "$(@PREFIX@/sbin/resolvconf -v)"
+ newsearch="$(uniqify $search_domains $SEARCH $search_domains_append)"
+ NS="$LOCALNAMESERVERS $NAMESERVERS"
+ newns="$(uniqify $name_servers $NS $name_servers_append)"
+
+ # Hold our new resolv.conf in a variable to save on temporary files
+ newconf="# Generated by resolvconf\n"
+ if [ -n "$resolv_conf_head" ]; then
+ newconf="$newconf$resolv_conf_head\n"
+ fi
+ [ -n "$newsearch" ] && newconf="${newconf}search $newsearch\n"
+ for n in $newns; do
+ newconf="${newconf}nameserver $n\n"
+ done
+
+ # Now get any configured options
+ opts="$resolv_conf_options${resolv_conf_options:+ }"
+ opts="$opts$($list_resolv | key_get_value "options ")"
+ if [ -n "$opts" ]; then
+ newconf="${newconf}options"
+ for opt in $(uniqify $opts); do
+ newconf="${newconf} $opt"
+ done
+ newconf="$newconf\n"
+ fi
+
+ if [ -n "$resolv_conf_tail" ]; then
+ newconf="$newconf$resolv_conf_tail\n"
+ fi
+ ;;
+esac
+
+# Check if the file has actually changed or not
+if [ -e "$resolv_conf" ]; then
+ [ "$(cat "$resolv_conf")" = "$(printf "$newconf")" ] && exit 0
+fi
+
+# Create our resolv.conf now
+(umask 022; printf "$newconf" >"$resolv_conf")
+eval $libc_restart
+
+retval=0
+# Notify users of the resolver
+for script in "$LIBEXECDIR"/libc.d/*; do
+ if [ -f "$script" ]; then
+ if [ -x "$script" ]; then
+ "$script" "$@"
+ else
+ (. "$script" "$@")
+ fi
+ retval=$(($retval + $?))
+ fi
+done
+exit $retval
diff --git a/named.in b/named.in
new file mode 100644
index 000000000000..644896128507
--- /dev/null
+++ b/named.in
@@ -0,0 +1,94 @@
+#!/bin/sh
+# Copyright (c) 2007-2009 Roy Marples
+# All rights reserved
+
+# named 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
+[ -z "$named_zones" -a -z "$named_options" ] && exit 0
+[ -z "$RESOLVCONF" ] && eval "$(@PREFIX@/sbin/resolvconf -v)"
+
+# Platform specific kludges
+if [ -z "$named_service" -a -z "$named_restart" -a \
+ -d "@RCDIR@" -a ! -x "@RCDIR@"/named ]
+then
+ if [ -x "@RCDIR@"/bind9 ]; then
+ # Debian and derivatives
+ named_service=bind9
+ fi
+fi
+: ${named_service:=named}
+: ${named_restart:=@RESTARTCMD ${named_service}@}
+newoptions="# Generated by resolvconf\n"
+newzones="$newoptions"
+
+forward=
+for n in $NAMESERVERS; do
+ case "$forward" in
+ *"\n\t$n;"*);;
+ *) forward="$forward\n\t$n;";;
+ esac
+done
+if [ -n "$forward" ]; then
+ newoptions="${newoptions}forward first;\nforwarders {$forward\n};\n"
+fi
+
+for d in $DOMAINS; do
+ newzones="${newzones}zone \"${d%%:*}\" {\n"
+ newzones="$newzones\ttype forward;\n"
+ newzones="$newzones\tforward first;\n\tforwarders {\n"
+ ns="${d#*:}"
+ while [ -n "$ns" ]; do
+ newzones="$newzones\t\t${ns%%,*};\n"
+ [ "$ns" = "${ns#*,}" ] && break
+ ns="${ns#*,}"
+ done
+ newzones="$newzones\t};\n};\n"
+done
+
+# No point in changing files or reloading bind if the end result has not
+# changed
+changed=false
+if [ -n "$named_options" ]; then
+ if [ ! -f "$named_options" ] || \
+ [ "$(cat "$named_options")" != "$(printf "$newoptions")" ]
+ then
+ printf "$newoptions" >"$named_options"
+ changed=true
+ fi
+fi
+if [ -n "$named_zones" ]; then
+ if [ ! -f "$named_zones" ] || \
+ [ "$(cat "$named_zones")" != "$(printf "$newzones")" ]
+ then
+ printf "$newzones" >"$named_zones"
+ changed=true
+ fi
+fi
+
+if $changed; then
+ eval $named_restart
+fi
diff --git a/pdnsd.in b/pdnsd.in
new file mode 100644
index 000000000000..ff3b9b23ab5a
--- /dev/null
+++ b/pdnsd.in
@@ -0,0 +1,153 @@
+#!/bin/sh
+# Copyright (c) 2010 Roy Marples
+# All rights reserved
+
+# pdnsd 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
+[ -z "$pdnsd_conf" -a -z "$pdnsd_resolv" ] && exit 0
+[ -z "$RESOLVCONF" ] && eval "$(@PREFIX@/sbin/resolvconf -v)"
+
+: ${pdnsd_restart:=pdnsd-ctl config $pdnsd_conf}
+signature="# Generated by resolvconf"
+signature_end="# End of resolvconf"
+
+# We normally use sed to remove markers from a configuration file
+# but sed may not always be available at the time.
+remove_markers()
+{
+ local m1="$1" m2="$2" x= line= in_marker=0
+
+ shift; shift
+ if type sed >/dev/null 2>&1; then
+ sed "/^$m1/,/^$m2/d" $@
+ else
+ for x; do
+ while read line; do
+ case "$line" in
+ "$m1"*) in_marker=1;;
+ "$m2"*) in_marker=0;;
+ *) [ $in_marker = 0 ] && echo "$line";;
+ esac
+ done < "$x"
+ done
+ fi
+}
+
+# Compare two files
+# If different, replace first with second otherwise remove second
+change_file()
+{
+ if [ -e "$1" ]; then
+ if type cmp >/dev/null 2>&1; then
+ cmp -s "$1" "$2"
+ elif type diff >/dev/null 2>&1; then
+ diff -q "$1" "$2" >/dev/null
+ else
+ # Hopefully we're only working on small text files ...
+ [ "$(cat "$1")" = "$(cat "$2")" ]
+ fi
+ if [ $? -eq 0 ]; then
+ rm -f "$2"
+ return 1
+ fi
+ fi
+ cat "$2" > "$1"
+ rm -f "$2"
+ return 0
+}
+
+newresolv="# Generated by resolvconf\n"
+changed=false
+
+if [ -n "$pdnsd_resolv" ]; then
+ for n in $NAMESERVERS; do
+ newresolv="${newresolv}nameserver $n\n"
+ done
+fi
+
+if [ -n "$pdnsd_conf" ]; then
+ cf="$pdnsd_conf.new"
+ newconf=
+
+ if [ -z "$pdnsd_resolv" ]; then
+ newconf="${newconf}server {\n"
+ newconf="${newconf}\tlabel=resolvconf;\n"
+ if [ -n "$NAMESERVERS" ]; then
+ newconf="${newconf}\tip="
+ first=true
+ for n in $NAMESERVERS; do
+ if $first; then
+ first=false
+ else
+ newconf="${newconf},"
+ fi
+ newconf="$newconf$n"
+ done
+ newconf="${newconf};\n"
+ fi
+ newconf="${newconf}}\n"
+ fi
+
+ for d in $DOMAINS; do
+ newconf="${newconf}server {\n"
+ newconf="${newconf}\tinclude=.${d%%:*}.;\n"
+ newconf="${newconf}\tpolicy=excluded;\n"
+ newconf="${newconf}\tip="
+ ns="${d#*:}"
+ while [ -n "$ns" ]; do
+ newconf="${newconf}${ns%%,*}"
+ [ "$ns" = "${ns#*,}" ] && break
+ ns="${ns#*,}"
+ newconf="${newconf},"
+ done
+ newconf="${newconf};\n}\n"
+ done
+
+ rm -f "$cf"
+ remove_markers "$signature" "$signature_end" "$pdnsd_conf" > "$cf"
+ if [ -n "$newconf" ]; then
+ echo "$signature" >> "$cf"
+ printf "$newconf" >> "$cf"
+ echo "$signature_end" >> "$cf"
+ fi
+ if change_file "$pdnsd_conf" "$cf"; then
+ changed=true
+ fi
+fi
+
+if [ -n "$pdnsd_resolv" ]; then
+ if [ ! -f "$pdnsd_resolv" ] || \
+ [ "$(cat "$pdnsd_resolv")" != "$(printf "$newresolv")" ]
+ then
+ changed=true
+ printf "$newresolv" >"$pdnsd_resolv"
+ fi
+fi
+
+if $changed; then
+ eval $pdnsd_restart
+fi
diff --git a/resolvconf.8.in b/resolvconf.8.in
new file mode 100644
index 000000000000..4e6f59a0449e
--- /dev/null
+++ b/resolvconf.8.in
@@ -0,0 +1,240 @@
+.\" Copyright (c) 2007-2009 Roy Marples
+.\" All rights reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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 AUTHOR 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 AUTHOR 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.
+.\"
+.Dd December 3, 2009
+.Dt RESOLVCONF 8 SMM
+.Os
+.Sh NAME
+.Nm resolvconf
+.Nd a framework for managing multiple DNS configurations
+.Sh SYNOPSIS
+.Nm
+.Fl I
+.Nm
+.Op Fl m Ar metric
+.Op Fl p
+.Fl a Ar interface No < Ns Pa file
+.Nm
+.Op Fl f
+.Fl d Ar interface
+.Nm
+.Fl il Ar pattern
+.Nm
+.Fl u
+.Sh DESCRIPTION
+.Nm
+manages
+.Xr resolv.conf 5
+files from multiple sources, such as DHCP and VPN clients.
+Traditionally, the host runs just one client and that updates
+.Pa /etc/resolv.conf .
+More modern systems frequently have wired and wireless interfaces and there is
+no guarantee both are on the same network.
+With the advent of VPN and other
+types of networking daemons, many things now contend for the contents of
+.Pa /etc/resolv.conf .
+.Pp
+.Nm
+solves this by letting the daemon send their
+.Xr resolv.conf 5
+file to
+.Nm
+via
+.Xr stdin 3
+with the argument
+.Fl a Ar interface
+instead of the filesystem.
+.Nm
+then updates
+.Pa /etc/resolv.conf
+as it thinks best.
+When a local resolver other than libc is installed, such as
+.Xr dnsmasq 8
+or
+.Xr named 8 ,
+then
+.Nm
+will supply files that the resolver should be configured to include.
+.Pp
+.Nm
+can mark an interfaces
+.Pa resolv.conf
+as private.
+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.
+This only works when a local resolver other than libc is installed.
+See
+.Xr resolvconf.conf 5
+for how to configure
+.Nm
+to use a local name server.
+.Pp
+When an interface goes down, it should then call
+.Nm
+with
+.Fl d Ar interface
+arguments to delete the
+.Pa resolv.conf
+file for the
+.Ar interface .
+.Pp
+Here are some more options that
+.Nm
+has:-
+.Bl -tag -width indent
+.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.
+.It Fl f
+Ignore non existant interfaces.
+Only really useful for deleting interfaces.
+.It Fl i Ar pattern
+List the interfaces, optionally matching
+.Ar pattern ,
+we have
+.Pa resolv.conf
+files for.
+.It Fl l Ar pattern
+List the
+.Pa resolv.conf
+files we have.
+If
+.Ar pattern
+is specified then we list the files for the interfaces that match it.
+.It Fl m Ar metric
+Set the metric of the interface 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
+.Pa resolv.conf
+as private.
+.It Fl u
+Force
+.Nm
+to update all it's subscribers.
+.Nm
+does not update the subscribers when adding a resolv.conf that matches
+what it already has for that interface.
+.El
+.Pp
+.Nm
+also has some options designed to be used by it's subscribers:-
+.Bl -tag -width indent
+.It Fl v
+Echo variables DOMAINS, SEARCH and NAMESERVERS so that the subscriber can
+configure the resolver easily.
+.El
+.Sh INTERFACE ORDERING
+For
+.Nm
+to work effectively, it has to process the resolv.confs for the interfaces
+in the correct order.
+.Nm
+first processes interfaces from the
+.Sy interface_order
+list, then interfaces without a metic and that match the
+.Sy dynamic_order
+list, then interfaces with a metric in order and finally the rest in
+the operating systems lexical order.
+See
+.Xr resolvconf.conf 5
+for details on these lists.
+.Sh IMPLEMENTATION NOTES
+If a subscriber has the executable bit then it is executed otherwise it is
+assumed to be a shell script and sourced into the current environment in a
+subshell.
+This is done so that subscribers can remain fast, but are also not limited
+to the shell language.
+.Pp
+Portable subscribers should not use anything outside of
+.Pa /bin
+and
+.Pa /sbin
+because
+.Pa /usr
+and others may not be available when booting.
+Also, it would be unwise to assume any shell specific features.
+.Sh ENVIRONMENT
+.Bl -ohang
+.It Va IF_METRIC
+If the
+.Fl m
+option is not present then we use
+.Va IF_METRIC
+for the metric.
+.It Va IF_PRIVATE
+Marks the interface
+.Pa resolv.conf
+as private.
+.El
+.Sh FILES
+.Bl -ohang
+.It Pa @SYSCONFDIR@/resolvconf.conf
+Configuration file for
+.Nm .
+.It Pa @LIBEXECDIR@
+Directory of subscribers which are run every time
+.Nm
+adds, deletes or updates.
+.It Pa @LIBEXECDIR@/libc.d
+Directory of subscribers which are run after the libc subscriber is run.
+.It Pa @VARDIR@
+State directory for
+.Nm .
+.El
+.Sh HISTORY
+This implementation of
+.Nm
+is called openresolv and is fully command line compatible with Debian's
+resolvconf, as written by Thomas Hood.
+.Sh BUGS
+.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.
+.Sh SEE ALSO
+.Xr resolv.conf 5 ,
+.Xr resolvconf.conf 5 ,
+.Xr resolver 3 ,
+.Xr stdin 3
+.Sh AUTHORS
+.An Roy Marples Aq roy@marples.name
+.Sh BUGS
+Please report them to http://roy.marples.name/projects/openresolv
diff --git a/resolvconf.conf b/resolvconf.conf
new file mode 100644
index 000000000000..607f6af4d919
--- /dev/null
+++ b/resolvconf.conf
@@ -0,0 +1,7 @@
+# Configuration for resolvconf(8)
+# See resolvconf.conf(5) for details
+
+resolv_conf=/etc/resolv.conf
+# If you run a local name server, you should uncomment the below line and
+# configure your subscribers configuration files below.
+#name_servers=127.0.0.1 \ No newline at end of file
diff --git a/resolvconf.conf.5.in b/resolvconf.conf.5.in
new file mode 100644
index 000000000000..9a47a1caed6f
--- /dev/null
+++ b/resolvconf.conf.5.in
@@ -0,0 +1,187 @@
+.\" Copyright (c) 2009-2010 Roy Marples
+.\" All rights reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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 AUTHOR 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 AUTHOR 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.
+.\"
+.Dd October 29, 2010
+.Dt RESOLVCONF.CONF 5 SMM
+.Os
+.Sh NAME
+.Nm resolvconf.conf
+.Nd resolvconf configuration file
+.Sh DESCRIPTION
+.Nm
+is the configuration file for
+.Xr resolvconf 8 .
+The
+.Nm
+file is a shell script that is sourced by
+.Xr resolvconf 8 ,
+meaning that
+.Nm
+must contain valid shell commands.
+Listed below are the standard
+.Nm
+variables that may be set.
+.Pp
+After updaing this file, you may wish to run
+.Nm resolvconf -u
+to apply the new configuration.
+.Sh RESOLVCONF OPTIONS
+.Bl -tag -width indent
+.It Sy interface_order
+These interfaces will always be processed first.
+If unset, defaults to the following:-
+.D1 lo lo[0-9]*
+.It Sy dynamic_order
+These interfaces will be processed next, unless they have a metric.
+If unset, defaults to the following:-
+.D1 tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]*
+.It Sy search_domains
+Prepend search domains to the dynamically generated list.
+.It Sy search_domains_append
+Append search domains to the dynamically generated list.
+.It Sy name_servers
+Prepend name servers to the dynamically generated list.
+You should set this to 127.0.0.1 if you use a local name server other than
+libc.
+.It Sy name_servers_append
+Append name servers to the dynamically generated list.
+.It Sy private_interfaces
+These interfaces name servers will only be queried for the domains listed
+in their resolv.conf.
+Useful for VPN domains.
+This is equivalent to the
+.Nm resolvconf -p
+option.
+.It Sy state_dir
+Override the default state directory of
+.Pa @VARDIR@ .
+This should not be changed once
+.Nm resolvconf
+is in use unless the old directory is copied to the new one.
+.El
+.Sh LIBC OPTIONS
+The following variables affect
+.Xr resolv.conf 5
+directly:-
+.Bl -tag -width indent
+.It Sy resolv_conf
+Defaults to
+.Pa /etc/resolv.conf
+if not set.
+.It Sy resolv_conf_options
+A list of libc resolver options, as specified in
+.Xr resolv.conf 5 .
+.It Sy resolv_conf_passthrough
+When set to YES the latest resolv.conf is written to
+.Sy resolv_conf
+without any alteration.
+.El
+.Sh SUBSCRIBER OPTIONS
+openresolv ships with subscribers for the name servers
+.Xr dnsmasq 8 ,
+.Xr named 8 ,
+.Xr pdnsd 8
+and
+.Xr unbound 8 .
+Each subscriber can create configuration files which should be included in
+in the subscribers main configuration file.
+.Bl -tag -width indent
+.It Sy dnsmasq_conf
+This file tells dnsmasq which nameservers to use for specific domains.
+.It Sy dnsmasq_resolv
+This file tells dnsmasq which nameservers to use for global lookups.
+.Pp
+Example resolvconf.conf for dnsmasq:
+.D1 nameservers=127.0.0.1
+.D1 dnsmasq_conf=/etc/dnsmasq-conf.conf
+.D1 dnsmasq_resolv=/etc/dnsmasq-resolv.conf
+.Pp
+Example dnsmasq.conf:
+.D1 listen-address=127.0.0.1
+.D1 conf-file=/etc/dnsmasq-conf.conf
+.D1 resolv-file=/etc/dnsmasq-resolv.conf
+.It Sy named_options
+Include this file in the named options block.
+This file tells named which nameservers to use for global lookups.
+.It Sy named_zones
+Include this file in the named global scope, after the options block.
+This file tells named which nameservers to use for specific domains.
+.Pp
+Example resolvconf.conf for named:
+.D1 nameservers=127.0.0.1
+.D1 named_options=/etc/named-options.conf
+.D1 named_zones=/etc/named-zones.conf
+.Pp
+Example named.conf:
+.D1 options {
+.D1 listen-on { 127.0.0.1; };
+.D1 include "/etc/named-options.conf";
+.D1 };
+.D1 include "/etc/named-zones.conf";
+.It Sy pdnsd_conf
+This is the main pdnsd configuration file which we modify to add our
+forward domains to.
+If this variable is not set then we rely on the pdnsd configuration file
+setup to read
+.Pa pdnsd_resolv
+as documented below.
+.It Sy pdnsd_resolv
+This file tells pdnsd about global nameservers.
+If this variable is not set then it's written to
+.Pa pdnsd_conf .
+.Pp
+Example resolvconf.conf for pdnsd:
+.D1 nameservers=127.0.0.1
+.D1 pdnsd_conf=/etc/pdnsd.conf
+.D1 # pdnsd_resolv=/etc/pdnsd-resolv.conf
+.Pp
+Example pdnsd.conf:
+.D1 global {
+.D1 server_ip = 127.0.0.1;
+.D1 status_ctl = on;
+.D1 }
+.D1 server {
+.D1 # A server definition is required, even if emtpy.
+.D1 label="empty";
+.D1 proxy_only=on;
+.D1 # file="/etc/pdnsd-resolv.conf";
+.D1 }
+.It Sy unbound_conf
+This file tells unbound about specific and global nameservers.
+.Pp
+Example resolvconf.conf for unbound:
+.D1 nameservers=127.0.0.1
+.D1 unbound_conf=/etc/unbound-resolvconf.conf
+.Pp
+Example unbound.conf:
+.D1 include: /etc/unbound-resolvconf.conf
+.El
+.Sh SEE ALSO
+.Xr resolv.conf 5
+and
+.Xr resolvconf 8 .
+.Sh AUTHORS
+.An Roy Marples Aq roy@marples.name
+.Sh BUGS
+Please report them to http://roy.marples.name/projects/openresolv
diff --git a/resolvconf.in b/resolvconf.in
new file mode 100644
index 000000000000..c3a1aa331690
--- /dev/null
+++ b/resolvconf.in
@@ -0,0 +1,421 @@
+#!/bin/sh
+# Copyright (c) 2007-2009 Roy Marples
+# All rights reserved
+
+# 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.
+
+RESOLVCONF="$0"
+SYSCONFDIR=@SYSCONFDIR@
+LIBEXECDIR=@LIBEXECDIR@
+VARDIR=@VARDIR@
+# Support original resolvconf configuration layout
+# as well as the openresolv config file
+if [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
+ . "$SYSCONFDIR"/resolvconf.conf
+ [ -n "$state_dir" ] && VARDIR="$state_dir"
+elif [ -d "$SYSCONFDIR/resolvconf" ]; then
+ SYSCONFDIR="$SYSCONFDIR/resolvconf"
+ if [ -f "$SYSCONFDIR"/interface-order ]; then
+ interface_order="$(cat "$SYSCONFDIR"/interface-order)"
+ fi
+fi
+IFACEDIR="$VARDIR/interfaces"
+METRICDIR="$VARDIR/metrics"
+PRIVATEDIR="$VARDIR/private"
+
+: ${dynamic_order:=tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]*}
+: ${interface_order:=lo lo[0-9]*}
+
+error_exit()
+{
+ echo "$*" >&2
+ exit 1
+}
+
+usage()
+{
+ cat <<-EOF
+ Usage: ${RESOLVCONF##*/} [options]
+
+ Inform the system about any DNS updates.
+
+ Options:
+ -a \$INTERFACE Add DNS information to the specified interface
+ (DNS supplied via stdin in resolv.conf format)
+ -m metric Give the added DNS information a metric
+ -p Mark the interface as private
+ -d \$INTERFACE Delete DNS information from the specified interface
+ -f Ignore non existant interfaces
+ -I Init the state dir
+ -u Run updates from our current DNS information
+ -l [\$PATTERN] Show DNS information, optionally from interfaces
+ that match the specified pattern
+ -i [\$PATTERN] Show interfaces that have supplied DNS information
+ optionally from interfaces that match the specified
+ pattern
+ -v [\$PATTERN] echo NEWDOMAIN, NEWSEARCH and NEWNS variables to
+ the console
+ -h Show this help cruft
+ EOF
+ [ -z "$1" ] && exit 0
+ echo
+ error_exit "$*"
+}
+
+echo_resolv()
+{
+ local line=
+ [ -n "$1" -a -e "$IFACEDIR/$1" ] || return 1
+ echo "# resolv.conf from $1"
+ # Our variable maker works of the fact each resolv.conf per interface
+ # is separated by blank lines.
+ # So we remove them when echoing them.
+ while read line; do
+ [ -n "$line" ] && echo "$line"
+ done < "$IFACEDIR/$1"
+ echo
+}
+
+# Parse resolv.conf's and make variables
+# for domain name servers, search name servers and global nameservers
+parse_resolv()
+{
+ local line= ns= ds= search= d= n= newns=
+ local new=true iface= private=false p=
+
+ echo "DOMAINS="
+ echo "SEARCH=\"$search_domains\""
+ # let our subscribers know about global nameservers
+ for n in $name_servers; do
+ case "$n" in
+ 127.*|0.0.0.0|255.255.255.255|::1) :;;
+ *) newns="$newns${newns:+ }$n";;
+ esac
+ done
+ echo "NAMESERVERS=\"$newns\""
+ echo "LOCALNAMESERVERS="
+ newns=
+
+ while read line; do
+ case "$line" in
+ "# resolv.conf from "*)
+ if ${new}; then
+ iface="${line#\# resolv.conf from *}"
+ new=false
+ if [ -e "$PRIVATEDIR/$iface" ]; then
+ private=true
+ else
+ # Allow expansion
+ cd "$IFACEDIR"
+ private=false
+ for p in $private_interfaces; do
+ if [ "$p" = "$iface" ]; then
+ private=true
+ break
+ fi
+ done
+ fi
+ fi
+ ;;
+ "nameserver "*)
+ case "${line#* }" in
+ 127.*|0.0.0.0|255.255.255.255|::1)
+ echo "LOCALNAMESERVERS=\"\$LOCALNAMESERVERS ${line#* }\""
+ continue
+ ;;
+ esac
+ ns="$ns${line#* } "
+ ;;
+ "domain "*|"search "*)
+ search="${line#* }"
+ ;;
+ *)
+ [ -n "$line" ] && continue
+ if [ -n "$ns" -a -n "$search" ]; then
+ newns=
+ for n in $ns; do
+ newns="$newns${newns:+,}$n"
+ done
+ ds=
+ for d in $search; do
+ ds="$ds${ds:+ }$d:$newns"
+ done
+ echo "DOMAINS=\"\$DOMAINS $ds\""
+ fi
+ echo "SEARCH=\"\$SEARCH $search\""
+ if ! $private; then
+ echo "NAMESERVERS=\"\$NAMESERVERS $ns\""
+ fi
+ ns=
+ search=
+ new=true
+ ;;
+ esac
+ done
+}
+
+uniqify()
+{
+ local result=
+ while [ -n "$1" ]; do
+ case " $result " in
+ *" $1 "*);;
+ *) result="$result $1";;
+ esac
+ shift
+ done
+ echo "${result# *}"
+}
+
+list_resolv()
+{
+ [ -d "$IFACEDIR" ] || return 0
+
+ local report=false list= retval=0 cmd="$1"
+ shift
+
+ # 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
+ else
+ cd "$IFACEDIR"
+ for i in $interface_order; do
+ [ -e "$i" ] && list="$list $i"
+ done
+ for i in $dynamic_order; do
+ if [ -e "$i" -a ! -e "$METRICDIR/"*" $i" ]; then
+ list="$list $i"
+ fi
+ done
+ if [ -d "$METRICDIR" ]; then
+ cd "$METRICDIR"
+ for i in *; do
+ list="$list ${i#* }"
+ done
+ fi
+ list="$list *"
+ fi
+
+ cd "$IFACEDIR"
+ for i in $(uniqify $list); do
+ # Only list interfaces which we really have
+ if ! [ -e "$i" ]; then
+ if $report; then
+ echo "No resolv.conf for interface $i" >&2
+ retval=$(($retval + 1))
+ fi
+ continue
+ fi
+
+ if [ "$cmd" = i -o "$cmd" = "-i" ]; then
+ printf "$i "
+ else
+ echo_resolv "$i"
+ fi
+ done
+ [ "$cmd" = i -o "$cmd" = "-i" ] && echo
+ return $retval
+}
+
+make_vars()
+{
+ eval "$(list_resolv -l "$@" | parse_resolv)"
+
+ # Ensure that we only list each domain once
+ newdomains=
+ for d in $DOMAINS; do
+ dn="${d%%:*}"
+ case " $newdomains" in
+ *" ${dn}:"*) continue;;
+ esac
+ newdomains="$newdomains${newdomains:+ }$dn:"
+ newns=
+ for nd in $DOMAINS; do
+ if [ "$dn" = "${nd%%:*}" ]; then
+ ns="${nd#*:}"
+ while [ -n "$ns" ]; do
+ case ",$newns," in
+ *,${ns%%,*},*) ;;
+ *) newns="$newns${newns:+,}${ns%%,*}";;
+ esac
+ [ "$ns" = "${ns#*,}" ] && break
+ ns="${ns#*,}"
+ done
+ fi
+ done
+ newdomains="$newdomains$newns"
+ done
+ echo "DOMAINS='$newdomains'"
+ echo "SEARCH='$(uniqify $SEARCH)'"
+ echo "NAMESERVERS='$(uniqify $NAMESERVERS)'"
+ echo "LOCALNAMESERVERS='$(uniqify $LOCALNAMESERVERS)'"
+}
+
+force=false
+while getopts a:d:fhIilm:puv OPT; do
+ case "$OPT" in
+ f) force=true;;
+ h) usage;;
+ m) IF_METRIC="$OPTARG";;
+ p) IF_PRIVATE=1;;
+ '?') ;;
+ *) cmd="$OPT"; iface="$OPTARG";;
+ esac
+done
+shift $(($OPTIND - 1))
+args="$iface${iface:+ }$@"
+
+# -I inits the state dir
+if [ "$cmd" = I ]; then
+ if [ -d "$VARDIR" ]; then
+ rm -rf "$VARDIR"/*
+ fi
+ exit $?
+fi
+
+# -l lists our resolv files, optionally for a specific interface
+if [ "$cmd" = l -o "$cmd" = i ]; then
+ list_resolv "$cmd" "$args"
+ exit $?
+fi
+
+# Not normally needed, but subscribers should be able to run independently
+if [ "$cmd" = v ]; then
+ make_vars "$iface"
+ exit $?
+fi
+
+# Test that we have valid options
+if [ "$cmd" = a -o "$cmd" = d ]; then
+ if [ -z "$iface" ]; then
+ usage "Interface not specified"
+ fi
+elif [ "$cmd" != u ]; then
+ [ -n "$cmd" -a "$cmd" != h ] && usage "Unknown option $cmd"
+ usage
+fi
+if [ "$cmd" = a ]; then
+ for x in '/' \\ ' ' '*'; do
+ case "$iface" in
+ *[$x]*) error_exit "$x not allowed in interface name";;
+ esac
+ done
+ for x in '.' '-' '~'; do
+ case "$iface" in
+ [$x]*) error_exit \
+ "$x not allowed at start of interface name";;
+ esac
+ done
+ [ "$cmd" = a -a -t 0 ] && error_exit "No file given via stdin"
+fi
+
+if [ ! -d "$IFACEDIR" ]; then
+ if [ ! -d "$VARDIR" ]; then
+ if [ -L "$VARDIR" ]; then
+ dir="$(readlink "$VARDIR")"
+ # link maybe relative
+ cd "${VARDIR%/*}"
+ if ! mkdir -m 0755 -p "$dir"; then
+ error_exit "Failed to create needed" \
+ "directory $dir"
+ fi
+ else
+ if ! mkdir -m 0755 -p "$VARDIR"; then
+ error_exit "Failed to create needed" \
+ "directory $VARDIR"
+ fi
+ fi
+ fi
+ mkdir -m 0755 -p "$IFACEDIR" || \
+ error_exit "Failed to create needed directory $IFACEDIR"
+else
+ # Delete any existing information about the interface
+ if [ "$cmd" = d ]; then
+ cd "$IFACEDIR"
+ for i in $args; do
+ if [ "$cmd" = d -a ! -e "$i" ]; then
+ $force && continue
+ error_exit "No resolv.conf for" \
+ "interface $i"
+ fi
+ rm -f "$i" "$METRICDIR/"*" $i" \
+ "$PRIVATEDIR/$i" || exit $?
+ done
+ fi
+fi
+
+if [ "$cmd" = a ]; then
+ # Read resolv.conf from stdin
+ resolv="$(cat)\n"
+ # If what we are given matches what we have, then do nothing
+ if [ -e "$IFACEDIR/$iface" ]; then
+ if [ "$(printf "$resolv")" = \
+ "$(cat "$IFACEDIR/$iface")" ]
+ then
+ exit 0
+ fi
+ rm "$IFACEDIR/$iface"
+ fi
+ printf "$resolv" >"$IFACEDIR/$iface" || exit $?
+ [ ! -d "$METRICDIR" ] && mkdir "$METRICDIR"
+ rm -f "$METRICDIR/"*" $iface"
+ 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
+ echo " " >"$METRICDIR/$IF_METRIC $iface"
+ fi
+ case "$IF_PRIVATE" in
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ if [ ! -d "$PRIVATEDIR" ]; then
+ [ -e "$PRIVATEDIR" ] && rm "$PRIVATEDIR"
+ mkdir "$PRIVATEDIR"
+ fi
+ [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$iface"
+ ;;
+ *)
+ if [ -e "$PRIVATEDIR/$iface" ]; then
+ rm -f "$PRIVATEDIR/$iface"
+ fi
+ ;;
+ esac
+fi
+
+eval "$(make_vars)"
+export RESOLVCONF DOMAINS SEARCH NAMESERVERS LOCALNAMESERVERS
+: ${list_resolv:=list_resolv -l}
+retval=0
+for script in "$LIBEXECDIR"/*; do
+ if [ -f "$script" ]; then
+ if [ -x "$script" ]; then
+ "$script" "$cmd" "$iface"
+ else
+ (. "$script" "$cmd" "$iface")
+ fi
+ retval=$(($retval + $?))
+ fi
+done
+exit $retval
diff --git a/unbound.in b/unbound.in
new file mode 100644
index 000000000000..b5fb7ecf5340
--- /dev/null
+++ b/unbound.in
@@ -0,0 +1,69 @@
+#!/bin/sh
+# Copyright (c) 2009 Roy Marples
+# All rights reserved
+
+# unbound 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
+[ -z "$unbound_conf" ] && exit 0
+[ -z "$RESOLVCONF" ] && eval "$(@PREFIX@/sbin/resolvconf -v)"
+
+: ${unbound_pid:=/var/run/unbound.pid}
+: ${unbound_service:=unbound}
+: ${unbound_restart:=@RESTARTCMD ${unbound_service}@}
+newconf="# Generated by resolvconf\n"
+
+for d in $DOMAINS; do
+ dn="${d%%:*}"
+ ns="${d#*:}"
+ newconf="${newconf}\nforward-zone:\n\tname: \"$dn\"\n"
+ while [ -n "$ns" ]; do
+ newconf="${newconf}\tforward-addr: ${ns%%,*}\n"
+ [ "$ns" = "${ns#*,}" ] && break
+ ns="${ns#*,}"
+ done
+done
+
+if [ -n "$NAMESERVERS" ]; then
+ newconf="${newconf}\nforward-zone:\n\tname: \".\"\n"
+ for n in $NAMESERVERS; do
+ newconf="${newconf}\tforward-addr: $n\n"
+ done
+fi
+
+if [ ! -f "$unbound_conf" ] || \
+ [ "$(cat "$unbound_conf")" != "$(printf "$newconf")" ]
+then
+ printf "$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
+ eval $unbound_restart
+ fi
+ else
+ eval $unbound_restart
+ fi
+fi