diff options
author | ume <ume@FreeBSD.org> | 2011-03-18 10:35:54 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2011-03-18 10:35:54 +0000 |
commit | e1520c69ccc9c503f85e049de8117e9e7fdb97c4 (patch) | |
tree | a283bc9f3750e7f183fc809cf8c630ab9959eb82 | |
download | FreeBSD-src-e1520c69ccc9c503f85e049de8117e9e7fdb97c4.zip FreeBSD-src-e1520c69ccc9c503f85e049de8117e9e7fdb97c4.tar.gz |
Import openresolv-3.4.1.
-rw-r--r-- | Makefile | 66 | ||||
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | configure | 186 | ||||
-rw-r--r-- | dnsmasq.in | 125 | ||||
-rw-r--r-- | libc.in | 168 | ||||
-rw-r--r-- | named.in | 94 | ||||
-rw-r--r-- | pdnsd.in | 153 | ||||
-rw-r--r-- | resolvconf.8.in | 240 | ||||
-rw-r--r-- | resolvconf.conf | 7 | ||||
-rw-r--r-- | resolvconf.conf.5.in | 187 | ||||
-rw-r--r-- | resolvconf.in | 421 | ||||
-rw-r--r-- | unbound.in | 69 |
12 files changed, 1727 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e4e3498 --- /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 @@ -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 0000000..39bdddb --- /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 0000000..1678866 --- /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 @@ -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 0000000..6448961 --- /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 0000000..ff3b9b2 --- /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 0000000..4e6f59a --- /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 0000000..607f6af --- /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 0000000..9a47a1c --- /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 0000000..c3a1aa33 --- /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 0000000..b5fb7ec --- /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 |