#!/bin/sh
# Copyright 2007 Roy Marples <roy@marples.name>
# All rights reserved

# named updater 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.

# 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.

# 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

NAMEDOPTIONS="${NAMEDB}/resolvconf-options.conf"
NAMEDZONES="${NAMEDB}/resolvconf-zones.conf"

# If we only have domain information then put it in search too
[ -z "${NEWSEARCH}" -a -z "${NEWNS}" ] && NEWSEARCH="${NEWDOMAIN}"

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};";;
	esac
done
if [ -n "${FORWARD}" ]; then
	NEWOPTIONS="${NEWOPTIONS}\nforward first;\nforwarders {${FORWARD}\n};\n"
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#*,};"
done
[ -n "${ZONES}" ] && NEWZONES="${NEWZONES}${ZONES}\n\t};\n};\n"

# 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"
	fi
else
	printf "${NEWOPTIONS}" > "${NAMEDOPTIONS}"
	RELOAD="yes"
fi
if [ -e "${NAMEDZONES}" ]; then
	if [ "$(cat "${NAMEDZONES}")" != "$(printf "${NEWZONES}")" ]; then
		printf "${NEWZONES}" > "${NAMEDZONES}"
		RELOAD="yes"
	fi
else
	printf "${NEWZONES}" > "${NAMEDZONES}"
	RELOAD="yes"
fi

[ "${RELOAD}" = "yes" ] && resolvconf -s named restart

exit 0
