Harden the locking mechanism
[openresolv] / named.in
old mode 100755 (executable)
new mode 100644 (file)
index d002e1e..3301896
--- a/named.in
+++ b/named.in
@@ -1,9 +1,8 @@
 #!/bin/sh
-# Copyright 2006 Gentoo Foundation
-# Copyright 2007 Roy Marples <roy@marples.name>
+# Copyright (c) 2007-2020 Roy Marples
 # All rights reserved
 
-# named updater for resolvconf
+# named subscriber for resolvconf
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# This is very important!
-# We assume that we are a local dns cache - after all, why would a server
-# use resolvconf?
-# Now that we have assumed this, we also assume that generic DHCP clients
-# will enter their domains and search domains ONLY in the "search" field
-# in their resolv.confs and VPN clients will put the domain they are for
-# into the domain field only.
-# This allows bind to forward domains for a specific VPN domain to the
-# VPN nameserver and everything else to the standard name servers.
+[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
+. "@SYSCONFDIR@/resolvconf.conf" || exit 1
+[ -z "${named_zones}${named_options}" ] && exit 0
+[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
+NL="
+"
 
-# The bind config needs to be setup to include our file
-#options {
-#   include "resolvconf-options.conf";
-#};
-#include "resolvconf-zones.conf";
-
-# The last step is to configure dns configuration for /etc/resolv.conf
-#echo "nameserver 127.0.0.1" > /etc/resolvconf/resolv.conf.d/base
-# On some platforms, like FreeBSD, resolvconf is in /usr/local so it becomes
-#echo "nameserver 127.0.0.1" > /usr/local/etc/resolvconf/resolv.conf.d/base
-
-# Load our variables from resolvconf
-VARS="$(resolvconf -v)"
-eval "${VARS}"
-
-# If our dir doesn't exist then don't do anything
-NAMEDB=/etc/namedb
-[ -d "${NAMEDB}" ] || NAMEDB="/etc/bind"
-[ -d "${NAMEDB}" ] || exit 0
+# Platform specific kludges
+if [ -z "${named_service}${named_restart}" ] &&
+   [ -d "$RCDIR" ] && ! [ -x "$RCDIR"/named ]
+then
+       if [ -x "$RCDIR"/bind9 ]; then
+               # Debian and derivatives
+               named_service=bind9
+       elif [ -x "$RCDIR"/rc.bind ]; then
+               # Slackware
+               named_service=rc.bind
+       fi
+fi
+: ${named_service:=named}
 
-NAMEDOPTIONS="${NAMEDB}/resolvconf-options.conf"
-NAMEDZONES="${NAMEDB}/resolvconf-zones.conf"
+: ${named_pid:=/var/run/$named_service.pid}
+[ -s "$named_pid" ] || named_pid=/var/run/$named_service/$named_service.pid
+[ -s "$named_pid" ] || unset named_pid
 
-# If we only have domain information then put it in search too
-[ -z "${NEWSEARCH}" -a -z "${NEWNS}" ] && NEWSEARCH="${NEWDOMAIN}"
+newoptions="# Generated by resolvconf$NL"
+newzones="$newoptions"
 
-NEWOPTIONS="# Generated by resolvconf\n"
-NEWZONES="${NEWOPTIONS}"
-FORWARD=
-for N in ${NEWSEARCH}; do
-       case "${FORWARD}" in
-               *"\n\t${N#*,};"*);;
-               *) FORWARD="${FORWARD}\n\t${N#*,};";;
-       esac
-done
-for N in ${NEWNS}; do
-       case "${FORWARD}" in
-               *"\n\t${N};"*);;
-               *) FORWARD="${FORWARD}\n\t${N};";;
+forward=
+for n in $NAMESERVERS; do
+       case "$forward" in
+       *"$NL   $n;"*);;
+       *) forward="$forward$NL $n;";;
        esac
 done
-if [ -n "${FORWARD}" ]; then
-       NEWOPTIONS="${NEWOPTIONS}\nforward first;\nforwarders {${FORWARD}\n};\n"
+if [ -n "$forward" ]; then
+       newoptions="${newoptions}forward first;${NL}forwarders {$forward${NL}};$NL"
 fi
 
-LASTDN=
-ZONES=
-for DN in $(printf "%s\n" ${NEWDOMAIN} | sort -u); do
-       case "${LASTDN}" in
-               "${DN%,*}");;
-               *)
-               [ -n "${ZONES}" ] && ZONES="${NEWZONES}\n\t};\n};\n"
-               ZONES="${ZONES}\nzone \"${DN%,*}\" {\n"
-               ZONES="${ZONES}\ttype forward;\n"
-               ZONES="${ZONES}\tforward first;\n"
-               ZONES="${ZONES}\tforwarders {"
-               ;;
-       esac
-       ZONES="${ZONES}\n\t\t${DN#*,};"
+for d in $DOMAINS; do
+       newzones="${newzones}zone \"${d%%:*}\" {$NL"
+       newzones="$newzones     type forward;$NL"
+       newzones="$newzones     forward first;$NL       forwarders {$NL"
+       ns="${d#*:}"
+       while [ -n "$ns" ]; do
+               newzones="$newzones             ${ns%%,*};$NL"
+               [ "$ns" = "${ns#*,}" ] && break
+               ns="${ns#*,}"
+       done
+       newzones="$newzones     };$NL};$NL"
 done
-[ -n "${ZONES}" ] && NEWZONES="${NEWZONES}${ZONES}\n\t};\n};\n"
+
+# Try to ensure that config dirs exist
+if type config_mkdirs >/dev/null 2>&1; then
+       config_mkdirs "$named_options" "$named_zones"
+else
+       @SBINDIR@/resolvconf -D "$named_options" "$named_zones"
+fi
 
 # No point in changing files or reloading bind if the end result has not
 # changed
-RELOAD="no"
-if [ -e "${NAMEDOPTIONS}" ]; then 
-       if [ "$(cat "${NAMEDOPTIONS}")" != "$(printf "${NEWOPTIONS}")" ]; then
-               printf "${NEWOPTIONS}" > "${NAMEDOPTIONS}"
-               RELOAD="yes"
+changed=false
+if [ -n "$named_options" ]; then
+       if [ ! -f "$named_options" ] || \
+               [ "$(cat "$named_options")" != "$(printf %s "$newoptions")" ]
+       then
+               printf %s "$newoptions" >"$named_options"
+               changed=true
        fi
-else
-       printf "${NEWOPTIONS}" > "${NAMEDOPTIONS}"
-       RELOAD="yes"
 fi
-if [ -e "${NAMEDZONES}" ]; then
-       if [ "$(cat "${NAMEDZONES}")" != "$(printf "${NEWZONES}")" ]; then
-               printf "${NEWZONES}" > "${NAMEDZONES}"
-               RELOAD="yes"
+if [ -n "$named_zones" ]; then
+       if [ ! -f "$named_zones" ] || \
+               [ "$(cat "$named_zones")" != "$(printf %s "$newzones")" ]
+       then
+               printf %s "$newzones" >"$named_zones"
+               changed=true
        fi
-else
-       printf "${NEWZONES}" > "${NAMEDZONES}"
-       RELOAD="yes"
 fi
 
-[ "${RELOAD}" = "yes" ] && resolvconf -s named restart
-
-exit 0
+# named does not seem to work with SIGHUP which is a same
+if $changed; then
+       if [ -n "$named_restart" ]; then
+               eval $named_restart
+       elif [ -n "$RESTARTCMD" ]; then
+               set -- ${named_service}
+               eval "$RESTARTCMD"
+       else
+               @SBINDIR@/resolvconf -r ${named_service}
+       fi
+fi