#!/bin/sh

# vi(1) :se tabstop=4

# For [www.]pi.berkeleylug.com. check DNS for fallback,
# if not fallback, check http://pi.berkeleylug.com/ and if that fails
# then set DNS to fallback.
# Note that when crontab driven, timing intevals between crontab
# settings and timing settings in program should reasonably correlate -
# most notably to generally avoid multiple instances of the program
# running at the same time.

TTL=300 # TTL we'll use when (re)setting our DNS records.

# how many seconds we wait on unresponsive website before DNS reset:
awhile="$TTL"

# How many seconds to wait between rechecks:
recheck_wait_seconds=15

# authoritative NS for berkeleylug.com (should be MNAME if we can use
# that):
NS=ns0.berkeleylug.com.

Nsupdate=/home/piberk/bin/Nsupdate

# Check our DNS for [www.]pi.berkeleylug.com.  If there's nothing to
# (re)set (we're already there), then there's nothing for us to do.

# Check that http://pi.berkeleylug.com/ responds.  If it responds,
# then there's nothing for us to do.  If it doesn't for $awhile, then
# (re)set our DNS.

# look up our target IP address(es), in case they change:
target_IPs=$(
	dig @"$NS" +short \
		berkeleylug.com. A \
		berkeleylug.com. AAAA \
		www.berkeleylug.com. A \
		www.berkeleylug.com. AAAA \
	|
	sed -e 's/[A-Z]/\l&/g' |
	sort -u
)
# sanity check target_IPs
[ -n "$target_IPs" ] || {
	echo "$0: failed to determine target_IPs, aborting" 1>&2
	exit 1
}

# Is our DNS already set to target_IPs?
# Don't specify NS here, as NS might be delegated
pi_ips=$(dig pi.berkeleylug.com. A pi.berkeleylug.com. AAAA +short |
	sed -e 's/[A-Z]/\l&/g' |
	sort -u
)
www_pi_ips=$(dig www.pi.berkeleylug.com. A \
	www.pi.berkeleylug.com. AAAA +short |
	sed -e 's/[A-Z]/\l&/g' |
	sort -u
)
{
	[ "$pi_ips" != "$target_IPs" ] ||
	[ "$www_pi_ips" != "$target_IPs" ]
} || {
	# Nothing to do, the IPs already match
	exit 0
}

# Is http://pi.berkeleylug.com/ responsive?
# We wait up to awhile.
# If we don't get response from it, we reset DNS to fallback.
timestamp1=$(date +%s) # seconds since epoch
while :
do
	timestamp2=$(date +%s) # seconds since epoch
	[ $(expr "$timestamp1" + "$awhile") -ge "$timestamp2" ] || {
		# We've waited $awhile, and still haven't gotten response
		# from http://pi.berkeleylug.com/
		# So, revert DNS.
		# first build up the part we'll add:
		DNS_add=
		for IP in $target_IPs; do
			case "$IP" in
				*.*.*.*)
					RR_type=A
				;;
				*:*)
					RR_type=AAAA
				;;
				*)
					echo "$0: unable to determine RR_type for IP $IP," \
						"aborting" 1>&2
					exit 1
				;;
			esac
			DNS_add="${DNS_add:+$DNS_add
}update add pi.berkeleylug.com. $TTL IN $RR_type $IP"
			DNS_add="${DNS_add:+$DNS_add
}update add www.pi.berkeleylug.com. $TTL IN $RR_type $IP"
		done
		# Remove potentially conflicting records and
		# add our basic reference/fallback records:
		"$Nsupdate" <<- __EOT__
			update del pi.berkeleylug.com. IN NS
			update del pi.berkeleylug.com. IN DS
			update del pi.berkeleylug.com. IN A
			update del pi.berkeleylug.com. IN AAAA
			update del pi.berkeleylug.com. IN CNAME
			update del www.pi.berkeleylug.com. IN A
			update del www.pi.berkeleylug.com. IN AAAA
			update del www.pi.berkeleylug.com. IN CNAME
			$DNS_add
			send
		__EOT__
		exit
	}

	# Can we even connect to it?
	nc -vz pi.berkeleylug.com. 80 >>/dev/null 2>&1 && {
		# Connected
		curl -I http://pi.berkeleylug.com/ >>/dev/null 2>&1 &&
		# We got some reasonable response, so it appears okay, nothing
		# to do
		exit 0
	}

	sleep "$recheck_wait_seconds"
done
