#!/bin/bash
# script will update DNS in conjunction 
# whether a host is reachable or not
# it will comment hosts which aren't reachable 
# and remove the comment if they become reachable 
# again.
# It can be used to manage effectively DNS round 
# robin records.
# developed by thorko (2008)

init_file=/etc/init.d/bind9

function print_help () {
	echo "Usage: $0 <path to dns zone file> <fast|slow>"
	echo -e "\tThis script will udpate the DNS file"
	echo -e "\tif it finds a host which isn't reachable"
	echo -e "\tIt will comment this line, update the"
	echo -e "\tserial and reload the config"
	echo -e "\tNote: Please consider to use \"; Serial\" "
	echo -e "\t      behind the serial number"
	echo -e ""
	echo -e "\tfast: will only check A records which aren't commented"
	echo -e ""
	echo -e "\tslow: will check for A records which are commented whether they"
	echo -e "\t      are reachable again"
}

function reload () {
	diff -q $conf_file /tmp/file > /dev/null
	if [ $? != 0 ]; then
		# file has changed update serial
		cat /tmp/file | awk '
			/Serial/{ 
				sERIAL=$1+1
				print "\t\t\t"sERIAL"\t; Serial" 
			}
			! /Serial/{ print $line }
		' > $conf_file
		# rm temp file
		rm /tmp/file
		# reload config
		$init_file reload
	else
		# don't update the dns file
		# just remove the temp file
		rm /tmp/file
	fi
}

if [ "$1" = "-h" ]; then
	print_help
	exit 0
elif [ "x$1" = "x" -o "x$2" = "x" ]; then
	echo "Usage: $0 [-h] <path to dns zone file> <fast|slow>"
	exit 1
fi

if [ ! -f $1 ]; then
	echo "Couldn't find file: $1"
	exit 1
fi

conf_file=$1
temp_file=/tmp/db.local

# check if comment serial exists 
# otherwise exit
cat $conf_file | grep "Serial" > /dev/null
if [ $? != 0 ]; then
	echo "ERROR: Couldn't find line \"; Serial\" which marks the serial number"
	exit 1
fi

# check for hosts which aren't reachable by a ping 
# ping ones with timeout 2
cat $conf_file | awk '
	# match anything not starting with ; and an A surrounded by tabs
	/^[^;].*[\t| ]A[\t| ]/ {
		cMD="ping -c 1 -q -W 2 "$4" > /dev/null 2>&1"
		if (system(cMD)) {
			print ";"$line
		}
		else {
			print $line	
		}
	}

	! /^[^;].*[\t| ]A[\t| ]/ {
		print $line
	}
' > /tmp/file

reload

if [ "$2" = "fast" ]; then
	exit 0
fi

cat $conf_file | awk '
	# match anything starting with ; and an A surrounded by tabs
	/^;.*[\t| ]A[\t| ]/ {
		cMD="ping -c 1 -q -W 2 "$4" > /dev/null 2>&1"
		#print cMD
		if (!system(cMD)) {
			new_Line=substr($line, 2, length($line))
			print new_Line
		}
		else {
			print $line
		}
	}
	
	! /^;.*[\t| ]A[\t ]/ {
		print $line
	}
' > /tmp/file

reload

