#!/bin/sh
#
# Script to update BIND Zonefiles with nsupdate. User must provide own TSIG
# host-key file. This script solves the problem of having a domain hosted
# on a dynamic IP and havnig to use a free dynamic DNS service provider. This
# will update a selection of 'A' records for the root domain, and mail.domain.
# It is up to the user of this script to write a base zonefile to include
# appropriate CNAMEs and other 'A' records as desired.
#
# Written by Stewart Honsberger (http://www.snerk.org/)
# This script is freely available to be publically distributed, dissected,
# used, and re-distributed at will, but please leave the attribution intact.

###
# Some flags
DEBUG=0			# Output debug mesages to STDOUT? (1 = Yes)
UPDATE_MAIL=1		# Update mail.domain for all domains? (1 = Yes)
CLEAN_TEMP=1		# Delete temp file? Set this to 0 if you want to
			# see what this script is generating, for further
			# debugging purposes. (1 = Yes)

###
# Space-separated list of domains to update. Each of these domains must share
# space on the same server, and use the same TSIG key.
UPDATE_ZONES="example.zone anotherzone.tld thirdone.zne"

###
# Temp file to write domain updates to. I've used mktemp for simplicity,
# but this could create a race condition. Use with caution.
TEMP_FILE=`mktemp /tmp/temp.XXXXXX`

###
# Name server to update to. This should be the primary DNS server (master)
# for all zones slated for update.
NAME_SERVER='ns1.snerk.org'

###
# Keyfile name. This filename should follow the convention;
# K{name}.+157.+{random}.private
# Consult dnssec-keygen(8) for instructions on how to create / use this
# keyfile
KEY_FILENAME="$HOME/Nsupdate/Kzonefile_update.+157+74383.private"

###
# Cache file to store current IP address. This file should remain static, and
# be in a location that can be cleared on re-boot of the server. This prevents
# the zones from being needlessly updated when no change is due.
IP_CACHE_FILE='/var/run/ip.cache'

###
# Current IP address of the server. If you're behind a firewall / Internet
# router, this will give you your present outgoing IP address without having
# to store your router's password in cleartext in this script file.
#
# Other possible sources of the same information are;
#
# http://checkip.dyndns.org/
# http://www.whatsmyip.com/
IP_ADDRESS=`lynx -dump http://checkip.snerk.org/ | grep IP | awk -F '[ :]+' '{ print \$4 }'`

###
# If your Internet connection is present on a local interface, comment-out
# the above and use the following instead;
#

###
# Local, external interface name
#EXT_INT="ppp0"

###
# IP Address of $EXT_INT
#IP_ADDRESS=`ifconfig $EXT_INT | grep inet | awk -F '[ :]+' '{print $4}'`

###
# Expiry time (in seconds) for domain names. If your IP changes frequently,
# you should set this to a low value, otherwise if your IP is fairly reliable,
# set it to a higher value to allow for longer cacheing of your domain names.
TIME_TO_LIVE='3600'

###############################################################################
# # # # # # # # # # # # # # # #  Code Section # # # # # # # # # # # # # # # # #
###############################################################################
# You shouldn't need to modify anything below this line, but if you do please #
# do so very carefully!                                                       #
###############################################################################
# # # # # # # # # # # # # # # #  Code Section # # # # # # # # # # # # # # # # #
###############################################################################

add_domain () {
	if [ $DEBUG -eq 1 ]; then
		echo "Updating zone $DOMAIN to $TEMP_FILE ... "
	fi
	echo "zone $DOMAIN." >> $TEMP_FILE
	echo "update delete $DOMAIN." >> $TEMP_FILE
	echo "update add $DOMAIN. $TIME_TO_LIVE A $IP_ADDRESS" >> $TEMP_FILE
	if [ $UPDATE_MAIL -eq 1 ]; then
		echo "update delete mail.$DOMAIN." >> $TEMP_FILE
		echo "update add mail.$DOMAIN. $TIME_TO_LIVE A $IP_ADDRESS" >> $TEMP_FILE
	fi
	echo "send" >> $TEMP_FILE
}

if [ -f $IP_CACHE_FILE ]; then
	CACHED_IP=`cat $IP_CACHE_FILE`
	if [ $CACHED_IP == $IP_ADDRESS ]; then
		rm $TEMP_FILE
		if [ $DEBUG -eq 1 ]; then
			echo "IP Address Unchanged, exiting ... "
		fi
		exit 0
	fi
fi

echo "server $NAME_SERVER" > $TEMP_FILE
for DOMAIN in $UPDATE_ZONES; do
	add_domain $DOMAIN
done

nsupdate -k $KEY_FILENAME $TEMP_FILE
echo -n $IP_ADDRESS > $IP_CACHE_FILE
if [ $CLEAN_TEMP -eq 1 ]; then
	rm $TEMP_FILE
fi

# EOF
