From 8e56b8ee7b703ea5a50492f7ae44294b7e4c39fb Mon Sep 17 00:00:00 2001 From: Hajimu UMEMOTO Date: Fri, 18 Mar 2011 10:35:54 +0000 Subject: [PATCH] Import openresolv-3.4.1. --- Makefile | 66 +++++++ README | 11 ++ configure | 186 +++++++++++++++++++ dnsmasq.in | 125 +++++++++++++ libc.in | 168 +++++++++++++++++ named.in | 94 ++++++++++ pdnsd.in | 153 ++++++++++++++++ resolvconf.8.in | 240 ++++++++++++++++++++++++ resolvconf.conf | 7 + resolvconf.conf.5.in | 187 +++++++++++++++++++ resolvconf.in | 421 +++++++++++++++++++++++++++++++++++++++++++ unbound.in | 69 +++++++ 12 files changed, 1727 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 configure create mode 100644 dnsmasq.in create mode 100644 libc.in create mode 100644 named.in create mode 100644 pdnsd.in create mode 100644 resolvconf.8.in create mode 100644 resolvconf.conf create mode 100644 resolvconf.conf.5.in create mode 100644 resolvconf.in create mode 100644 unbound.in 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 + +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