:
# NAME:
#	named - start,stop,check named
#
# DESCRIPTION:
#	This start/stop script also serves as a check script.
#	We go to great pains to ensure that named is running.
#
# FILES:
#	/etc/named.boot		named configuration
#	/etc/named.conf		bind-8 configuration
#
# AUTHOR:
#	Simon J. Gerraty <sjg@crufty.net>

# RCSid:
#	$Id: named,v 1.26 2022/09/10 04:50:48 sjg Exp $
#
#	@(#) Copyright (c) 1994 Simon J. Gerraty
#
#	This file is provided in the hope that it will
#	be of use.  There is absolutely NO WARRANTY.
#	Permission to copy, redistribute or otherwise
#	use this file is hereby granted provided that 
#	the above copyright notice and this notice are
#	left intact. 
#      
#	Please send copies of changes and bug-fixes to:
#	sjg@crufty.net
#

# pick up zap(), Which() etc
RC_D=${RC_D:-/etc/rc_d}
. $RC_D/dnsfuncs.sh

[ -s .namedrc ] && . ./.namedrc

OS=${OS:-`uname`}
case "$OS" in
NetBSD) LOCALBASE=${LOCALBASE:-/usr/pkg};;
esac
LOCALBASE=${LOCALBASE:-/usr/local}

# bind9 lives in /usr/pkg/sbin (on netbsd anyway)
# bind8 lives in /usr/local/sbin/named or /usr/sbin
# bind4.9 lives in /usr/local/libexec
# if in doubt, set NAMED before hand.
binddirs=${LOCALBASE}/sbin:${LOCALBASE}/libexec:/usr/sbin:${LOCALBASE}/etc:/usr/etc
NAMED=${NAMED:-`Which named $binddirs:$PATH`}
NAMED=${NAMED:-`Which in.named $binddirs:$PATH`}

test "$NAMED" || exit 0

NAME=`basename $NAMED`

Start() {
	case $NDBOOT in
	/etc/named.boot|/etc/named.conf) ;;
	*) ND_OPTS="$ND_OPTS $NDBOOT";;
	esac
	$ECHO $NAMED $ND_OPTS
	echo $N " $NAME $C"
}

waitPort() {
	port=$1
		
	m="waiting for port $port"
	for i in 1 2 4 8 16 32 64
	do
		nl=`netstat -na | egrep "$LISTEN_RE\.$port[^0-9].*LISTEN" | wc -l`
		nl=`echo $nl`
		case $nl in
		0) break;;
		esac
		echo $N "$m$C"
		m=.
		sleep $i
	done
	echo
}

is_alive() {
	ok=`LANG=C LC_ALL=C kill -0 $1 2>&1`
	case "$ok" in
	*such*) return 1;;
	esac
	return 0
}

# a bit like zap()
Stop() {
	pid=${1:-`dnsPid`}
	if test "$pid"; then
		case "$BINDVERS" in
		9*)	$RNDC stop
			tmout=60
			while [ $tmout -gt 0 ]
			do
				is_alive $pid || break
				sleep 1
				tmout=`expr $tmout - 1`
			done
			return
			;;
		esac
		case "$cmd" in
		restart) s="-s 120";;
		*) s= ;;
		esac 
		Zap -v -k 30 -t 3 $s $pid
	fi
}

Reload() {
        echo Reloading $NAME
	case "$BINDVERS" in
	9*)	$RNDC $cmd;;
	*)	kill -HUP $pid;;
	esac
}

# rather than re-invent the wheel
# leverage $NDC if it exists for start,stop and reload
if [ -x $LOCALBASE/etc/rc.d/named ]; then
	NDC=${NDC:-$LOCALBASE/etc/rc.d/named}
fi
if [ -x ${NDC:-/dev/null} ]; then
	Start() { $NDC start; }
	Stop() { $NDC stop; }
	Reload() { $NDC reload; }
fi

Check() {
	pid=`dnsPid`

	ok="No such process"
	[ "$pid" ] && ok=`LANG=C LC_ALL=C kill -0 $pid 2>&1`

	case "$ok" in
	*permitted*)
		echo $ok
		exit 1
		;;
	*such*)
		# ok, before we just try and start a new one we need to
		# be reasonably sure that there is not an old one tying up
		# port 53, otherwise the new one will abort or worse - run
		# and not do anything useful.
		KILL_LIST=${KILL_LIST:-"named in.named lbnamed"}
		for l in 1 2
		do
			waitPort 53
			case $nl in
			0) break;;
			*)
				echo something is still listening on port 53.
				echo finding it - and killing it.
				pids=`get_pids $KILL_LIST`
				if [ "$pids" ]; then
					$ECHO kill $pids
					$ECHO sleep 6
					$ECHO kill -9 $pids 2>/dev/null
				fi
				;;
			esac
		done
		
		echo $N "restarting$C"
		Start 
		echo
		case "$cmd" in
		check|restart) exit;;
		esac
		pid=`dnsPid`
		;;
	esac
}

case "$0" in
*check*) cmd=check;;
*)	cmd=$1;;
esac

case "$cmd" in
fstart)
	Start
	exit
	;;
""|start)
	Check
	exit
	;;
restart)
	echo Stopping $NAME
	Stop
	Check
	exit
	;;	
stop)
	echo Stopping $NAME
	Stop
	exit
	;;
esac

# everything else requires named running, so make sure it is
Check

# bind9 needs this
RNDC=${RNDC:-rndc}

case "$cmd" in
reload) Reload;;
dump*)
	echo Dumping $NAME
	case "$BINDVERS" in
	9*)	# versions prior to 9.3 will ignore the extra arg
		$RNDC dumpdb ${BIND9_DUMPDB_MODE:--all};;
	*)	kill -INT $pid;;
	esac
	;;
stats)
	echo Dumping $NAME stats
	case "$BINDVERS" in
	9*)	$RNDC $cmd;;
	*)	kill -ILL $pid;;
	esac
	;;
trace)
	echo Increment $NAME trace level
	case "$BINDVERS" in
	9*)	$RNDC $cmd;;
	*)	kill -USR1 $pid;;
	esac
	;;
notrace)
	echo Cleared $NAME trace level
	case "$BINDVERS" in
	9*)	$RNDC $cmd;;
	*)	kill -USR2 $pid;;
	esac
	;;
q*rylog)
	echo Querylog toggled
	case "$BINDVERS" in
	9*)	$RNDC $cmd;;
	*)	kill -WINCH $pid;;
	esac
	;;
esac

