#!/bin/sh

LC_ALL=C export LC # avoid non-ASCII surprises

# vi(1) :se tabstop=4

# For domain(s) - given as arguments or defalut set,
# check (not all fully implemented yet):
# o relevant authority/additional(/"glue") records
# o check NS & related A and AAAA records
# o check SOA records from each authoritative nameserver NS IP (A & AAAA)

# tigger: mpaoli.net f.6.7.0.7.6.0.0.0.7.4.0.1.0.0.2.ip6.arpa  
# BALUG: balug.org sf-lug.org sf-lug.com sflug.org sflug.com sflug.net sf-lug.net berkeleylug.com digitalwitness.org savingthedolph.in e.9.1.0.5.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
default_domains='

mpaoli.net
f.6.7.0.7.6.0.0.0.7.4.0.1.0.0.2.ip6.arpa

balug.org
e.9.1.0.5.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa

sf-lug.org sf-lug.com sflug.org sflug.com sflug.net sf-lug.net

berkeleylug.com

digitalwitness.org

savingthedolph.in
'

[ "$#" -ge 1 ] || set -- $default_domains

# dig(1) options to always use:
DIG_OPTS='+nomultiline +nosplit'

tmpd=$(mktemp -d) || exit

rc=0 # return code / exit value

# Our cleanups:
trap "trap - 0; rm -rf $tmpd; exit "'"$rc"' 0
for sig in 1 2 3 15
do
	trap '
		trap - 0
		rm -rf '"$tmpd"' || exit
		trap - '"$sig"'
		kill -'"$sig"' "$$"
	' "$sig"
done

for FQDN
do
	# nominalize to lowercase and with ending .:
	FQDN=$(echo "$FQDN" | sed -e 's/[A-Z]/\l&/g;s/[^.]$/&./')

	echo FQDN: "$FQDN":

	# work our way up as needed to find NS records:
	NS_domain=
	a=
	b="$FQDN"
	> "$tmpd"/nameservers
	while :
	do
		dig +noall +answer $DIG_OPTS "$b" NS |
		awk '
			{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
		' |
		sort -fi +5b \
		> "$tmpd"/nameservers
		[ -s "$tmpd"/nameservers ] && {
			# found nameservers
			# try direct nonrecursive against what should be authoritative
			for NS in $(sed -e 's/^.*[ 	]//' "$tmpd"/nameservers)
			do
				dig @"$NS" +noall +norecurse +answer $DIG_OPTS "$b" NS |
				awk '
					{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
				' |
				sort -fi +5b \
				> "$tmpd"/nameservers
				[ -s "$tmpd"/nameservers ] && break
			done
			[ -s "$tmpd"/nameservers ] || {
				# if we failed to get data from any authoritative nameserver:
				rc=1
				echo "$0: failed to find NS data from authoritative nameservers for $FQDN ... --> $b" 1>&2
				continue 2 # try next FQDN
			}

			NS_domain="$b" # domain where we found the nameservers
			#echo "$NS_domain" #####
			#sed -e 's/[ 	][ 	]*/ /g' "$tmpd"/nameservers #####
			break
		}

		case "$b" in
			.)
				# failed to find nameservers
				rc=1
				echo "$0: failed to find nameservers for $FQDN ... --> $b" 1>&2
				continue 2 # try next FQDN
			;;
		esac

		# (try to) split at first dot (.):
		set -- $(
			echo "$b" |
			sed -e 's/^\([^\.]\{1,\}\)\.\(.*\)$/\1 \2/'
		)
		case "$#" in
			2)
				b="$2"
			;;
			1)
				b=.
			;;
			*)
				rc=1
				echo "$0: failed to find parent of $b" 1>&2
				continue 2 # try next FQDN
			;;
		esac
	done

	# work our way up as needed to find delegating parent NS records:
	NS_parent_domain=
	a=
	b="$NS_domain"
	> "$tmpd"/parentnameservers
	[ . != "$b" ] &&
	# only do this part if there's an "up" from here:
	while :
	do
		# (try to) split at first dot (.):
		set -- $(
			echo "$b" |
			sed -e 's/^\([^\.]\{1,\}\)\.\(.*\)$/\1 \2/'
		)
		case "$#" in
			2)
				b="$2"
			;;
			1)
				b=.
			;;
			*)
				rc=1
				exit 1
			;;
		esac

		dig +noall +answer $DIG_OPTS "$b" NS |
		awk '
			{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
		' |
		sort -fi +5b \
		> "$tmpd"/parentnameservers
		[ -s "$tmpd"/parentnameservers ] && {
			# found parent nameservers
			# try direct nonrecursive against what should be authoritative
			for NS in $(sed -e 's/^.*[ 	]//' "$tmpd"/parentnameservers)
			do
				dig @"$NS" +noall +norecurse +answer $DIG_OPTS "$b" NS |
				awk '
					{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
				' |
				sort -fi +5b \
				> "$tmpd"/parentnameservers
				[ -s "$tmpd"/parentnameservers ] && break
			done
			[ -s "$tmpd"/parentnameservers ] || {
				# if we failed to get data from any authoritative nameserver:
				rc=1
				echo "$0: failed to find NS data from authoritative nameservers for parent of $NS_domain ... --> $b" 1>&2
				continue 2 # try next FQDN
			}
			NS_parent_domain="$b" # parent domain where we found nameservers
			#echo "$NS_parent_domain" #####
			#sed -e 's/[ 	][ 	]*/ /g' "$tmpd"/parentnameservers #####
			break
		}

		case "$b" in
			.)
				# failed to find nameservers
				echo "$0: failed to find nameservers for parent of $NS_domain ... --> $b" 1>&2
	
				rc=1
				continue 2 # try next FQDN
			;;
		esac
	done

	[ -s "$tmpd"/parentnameservers ] || {
		# Should have been caught earlier?  But "just in case":
		rc=1
		echo "$0: failed to find nameservers for parent of $NS_domain ... --> $b" 1>&2
		continue
	}
	[ -s "$tmpd"/parentnameservers ] && {
		for NS in $(<"$tmpd"/parentnameservers sed -e 's/^.*[ 	]//' | sort -R)
		do
			# try answer first, then if not that, authority
			dig @"$NS" +noall +norecurse +answer $DIG_OPTS \
				"$NS_domain" NS |
			awk '
				{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
			' |
			sort -fi +5b \
			> "$tmpd"/parentanswer
			[ -s "$tmpd"/parentanswer ] ||
			dig @"$NS" +noall +norecurse +authority $DIG_OPTS \
				"$NS_domain" NS |
			awk '
				{if(($3~/^[Ii][Nn]$/)&&($4~/^[Nn][Ss]$/)){print}}
			' |
			sort -fi +5b \
			> "$tmpd"/authority
		done
	}

	if [ -s "$tmpd"/parentanswer ]; then
		echo parentanswer:
		sed -e 's/[ 	][ 	]*/ /g' "$tmpd"/parentanswer

		for NS in $(sed -e 's/^.*[ 	]//' "$tmpd"/nameservers)
		do
			for IP in $(
				dig +short $DIG_OPTS "$NS" A "$NS" AAAA
			)
			do
				#echo "$FQDN $NS $IP"
				echo $(dig @"$IP" +noall +answer +norecurse $DIG_OPTS "$NS_domain" SOA) '@'"$IP"' ('"$NS"')'
			done
		done
	elif [ -s "$tmpd"/authority ]; then
		echo authority:
		sed -e 's/[ 	][ 	]*/ /g' "$tmpd"/authority

		for NS in $(sed -e 's/^.*[ 	]//' "$tmpd"/nameservers)
		do
			for IP in $(
				dig +short $DIG_OPTS "$NS" A "$NS" AAAA
			)
			do
				#echo "$FQDN $NS $IP"
				echo $(dig @"$IP" +noall +answer +norecurse $DIG_OPTS "$NS_domain" SOA) '@'"$IP"' ('"$NS"')'
			done
		done
	fi
done
