#!/usr/bin/env bash
# manage the .core DNS zone

. lib.bash || exit

Fzone='core'
Rzone='7.147.10.in-addr.arpa'

UpdateKey='/etc/rndc.key'
Bindhost='10.147.7.1'
Bindport='40054'

Ffile="/var/named/core.zone"
Rfile="/var/named/arpa-10.147.7.zone"

zone=$Fzone
file=$Ffile

do_nsupdate() {
	local zone=$1; shift
	printf "%s\n" \
		"server $Bindhost $Bindport"	\
		"zone $zone"					\
		"$@"							\
		"send"							\
	| nsupdate -k "$UpdateKey"
}

do_dig() {
	dig "@$Bindhost" -p "$Bindport" +domain="$zone" "$@"
}

do_lookup() {
	do_dig +noall +answer +nocl "$@"
}

do_axfr() {
	do_dig +noall +answer +nocl -t AXFR -q "$1."
}

do_edit() {
	local zone=$1 file=$2

	rndc thaw "$zone"
	do_nsupdate "$zone" "del $zone 0 PTR ."

	rndc freeze "$zone"
	sudoedit "$file"

	rndc thaw "$zone"
	do_nsupdate "$zone" "add $zone 0 PTR ."
}

do_journal() {
	local file=$1 num=${2:-15}
	echo -e "\e[1mShowing $num latest entries:\e[m"
	named-journalprint "$file" | awk '$5 != "SOA"' | tail -$num \
	| while read -r a b c; do
		printf '%s %-26s %s\n' "$a" "$b" "$c"
	done \
	| sed 's/^add/\x1B[32m&\x1B[m/; s/^del/\x1B[31m&\x1B[m/; s/$/\x1B[m/'
}

ttl() {
	echo ${ttl:=$(do_dig +short "$zone." SOA | awk '{print $7}')}
}

cmd=$1; shift; case $cmd in
	help|--help)
		echo "add <name> <type> <data>"
		echo "set <name> <type> <data>"
		echo "del|rm <name> [<type> [<data>]]"
		echo "set-ptr <ip> <name>"
		echo "del-ptr <ip>"
		echo "log|tail, rlog|rtail"
		echo "syslog"
		echo "ls, rls"
		echo "dig"
		echo "edit, redit"
		echo "update, rupdate"
		echo "sync|flush"
		echo "soa"
		echo "ttl"
		;;
	add)
		name=$1 type=$2 data=$3
		[[ $name ]] || die "missing record name, type, data"
		[[ $type ]] || die "missing record type, data"
		[[ $data ]] || die "missing record data"
		do_nsupdate "$Fzone" \
			"add $name $(ttl) $type $data" ;;
	set)
		name=$1 type=$2 data=$3
		[[ $name ]] || die "missing record name, type, data"
		[[ $type ]] || die "missing record type, data"
		[[ $data ]] || die "missing record data"
		do_nsupdate "$Fzone" \
			"del $name" \
			"add $name $(ttl) $type $data" ;;
	del|rm)
		name=$1 type=$2 data=$3
		[[ $name ]] || die "missing record name"
		do_nsupdate "$Fzone" \
			"del $name $(ttl) $type $data" ;;
	dhcp-add)
		duid=$1 ip=$2 host=$3 dom=$4
		do_nsupdate "$Fzone" \
			"del $host.$Fzone" \
			"add $host.$Fzone $(ttl) A $ip" ;;
	set-ptr)
		ip=$1 name=$2
		[[ $ip ]] || die "missing IP address"
		[[ $name ]] || die "missing pointer name"
		iparpa=$(arpaname $ip)
		do_nsupdate "$Rzone" \
			"del $iparpa" \
			"add $iparpa $(ttl) PTR $name" ;;
	del-ptr)
		ip=$1
		[[ $ip ]] || die "missing IP address"
		iparpa=$(arpaname $ip)
		do_nsupdate "$Rzone" \
			"del $iparpa" ;;
	log|tail)
		do_journal "$Ffile.jnl" ;;
	rlog|rtail)
		do_journal "$Rfile.jnl" ;;
	syslog)
		journalctl -fau named.service ;;
	ls)
		do_axfr "$Fzone" "$@" ;;
	rls)
		do_axfr "$Rzone" "$@" ;;
	dig)
		do_dig "$@" ;;
	edit)
		do_edit "$Fzone" "$Ffile" ;;
	redit)
		do_edit "$Rzone" "$Rfile" ;;
	update)
		do_nsupdate "$Fzone" "$@" ;;
	rupdate)
		do_nsupdate "$Rzone" "$@" ;;
	sync|flush)
		rndc sync "$Fzone" &&
		rndc sync "$Rzone" ;;
	poke)
		rndc reconfig ;;
	soa)
		do_lookup "$Fzone." SOA &&
		do_lookup "$Rzone." SOA ;;
	ttl)
		ttl ;;
	'')
		die "missing command" ;;
	*)
		die "unknown command '$cmd'" ;;
esac

# vim: ts=4:sw=4
