178344Sobrien#!/bin/sh
278344Sobrien#
398184Sgordon# $FreeBSD$
478344Sobrien#
578344Sobrien
678344Sobrien# PROVIDE: named
7242153Sobrien# REQUIRE: SERVERS FILESYSTEMS
8139075Speadar# KEYWORD: shutdown
978344Sobrien
1078344Sobrien. /etc/rc.subr
1178344Sobrien
1278344Sobrienname="named"
13155595Sdougbrcvar=named_enable
14155595Sdougb
15155595Sdougbextra_commands="reload"
16155595Sdougb
17200448Sdougbstart_precmd="named_prestart"
18192215Sdougbstart_postcmd="named_poststart"
19155595Sdougbreload_cmd="named_reload"
20155595Sdougbstop_cmd="named_stop"
21139066Speadarstop_postcmd="named_poststop"
2278344Sobrien
2398184Sgordon# If running in a chroot cage, ensure that the appropriate files
2498184Sgordon# exist inside the cage, as well as helper symlinks into the cage
2598184Sgordon# from outside.
2698184Sgordon#
2798184Sgordon# As this is called after the is_running and required_dir checks
2898184Sgordon# are made in run_rc_command(), we can safely assume ${named_chrootdir}
2998184Sgordon# exists and named isn't running at this point (unless forcestart
3098184Sgordon# is used).
3198184Sgordon#
3298184Sgordonchroot_autoupdate()
3398184Sgordon{
34181114Sdougb	local file
35181114Sdougb
36135875Sdougb	# Create (or update) the chroot directory structure
37104980Sschweikh	#
38155595Sdougb	if [ -r /etc/mtree/BIND.chroot.dist ]; then
39135875Sdougb		mtree -deU -f /etc/mtree/BIND.chroot.dist \
40135875Sdougb		    -p ${named_chrootdir}
41135875Sdougb	else
42135875Sdougb		warn "/etc/mtree/BIND.chroot.dist missing,"
43135875Sdougb		warn "chroot directory structure not updated"
44104980Sschweikh	fi
45135875Sdougb
46201367Sdougb	# Create (or update) the configuration directory symlink
47135875Sdougb	#
48201367Sdougb	if [ ! -L "${named_conf%/*}" ]; then
49201367Sdougb		if [ -d "${named_conf%/*}" ]; then
50201367Sdougb			warn "named chroot: ${named_conf%/*} is a directory!"
51201367Sdougb		elif [ -e "${named_conf%/*}" ]; then
52201367Sdougb			warn "named chroot: ${named_conf%/*} exists!"
53135875Sdougb		else
54201367Sdougb			ln -s ${named_confdir} ${named_conf%/*}
55135875Sdougb		fi
56139015Sphk	else
57139015Sphk		# Make sure it points to the right place.
58201367Sdougb		ln -shf ${named_confdir} ${named_conf%/*}
59135703Sdougb	fi
6098184Sgordon
61135875Sdougb	# Mount a devfs in the chroot directory if needed
62104980Sschweikh	#
63188293Sbz	if [ `${SYSCTL_N} security.jail.jailed` -eq 0 ]; then
64188293Sbz		umount ${named_chrootdir}/dev 2>/dev/null
65188293Sbz		devfs_domount ${named_chrootdir}/dev devfsrules_hide_all
66188293Sbz		devfs -m ${named_chrootdir}/dev rule apply path null unhide
67188293Sbz		devfs -m ${named_chrootdir}/dev rule apply path random unhide
68188293Sbz	else
69188293Sbz		if [ -c ${named_chrootdir}/dev/null -a \
70188293Sbz		    -c ${named_chrootdir}/dev/random ]; then
71188293Sbz			info "named chroot: using pre-mounted devfs."
72188293Sbz		else
73188293Sbz			err 1 "named chroot: devfs cannot be mounted from" \
74188293Sbz			    "within a jail. Thus a chrooted named cannot" \
75188293Sbz			    "be run from within a jail." \
76188293Sbz			    "To run named without chrooting it, set" \
77188293Sbz			    "named_chrootdir=\"\" in /etc/rc.conf."
78188293Sbz		fi
79188293Sbz	fi
80135875Sdougb
81192210Sdougb	# Copy and/or update key files to the chroot /etc
82135875Sdougb	#
83181114Sdougb	for file in localtime protocols services; do
84181114Sdougb		if [ -r /etc/$file ]; then
85181114Sdougb			cmp -s /etc/$file "${named_chrootdir}/etc/$file" ||
86181114Sdougb			    cp -p /etc/$file "${named_chrootdir}/etc/$file"
87181114Sdougb		fi
88181114Sdougb	done
8998184Sgordon}
9098184Sgordon
91135703Sdougb# Make symlinks to the correct pid file
9298184Sgordon#
9398184Sgordonmake_symlinks()
9498184Sgordon{
95135703Sdougb	checkyesno named_symlink_enable &&
96155595Sdougb	    ln -fs "${named_chrootdir}${pidfile}" ${pidfile}
9798184Sgordon}
9898184Sgordon
99192215Sdougbnamed_poststart () {
100192215Sdougb	make_symlinks
101192215Sdougb
102192215Sdougb	if checkyesno named_wait; then
103192215Sdougb		until ${command%/sbin/named}/bin/host $named_wait_host >/dev/null 2>&1; do
104192215Sdougb			echo "	Waiting for nameserver to resolve $named_wait_host"
105192215Sdougb			sleep 1
106192215Sdougb		done
107192215Sdougb	fi
108192215Sdougb}
109192215Sdougb
110155595Sdougbnamed_reload()
111155595Sdougb{
112172877Sdougb	${command%/named}/rndc reload
113155595Sdougb}
114155595Sdougb
115220962Sdougbfind_pidfile()
116220962Sdougb{
117220962Sdougb	if get_pidfile_from_conf pid-file $named_conf; then
118220962Sdougb		pidfile="$_pidfile_from_conf"
119220962Sdougb	else
120220962Sdougb		pidfile="/var/run/named/pid"
121220962Sdougb	fi
122220962Sdougb}
123220962Sdougb
124155595Sdougbnamed_stop()
125155595Sdougb{
126220962Sdougb	find_pidfile
127220962Sdougb
128172877Sdougb	# This duplicates an undesirably large amount of code from the stop
129172877Sdougb	# routine in rc.subr in order to use rndc to shut down the process,
130172877Sdougb	# and to give it a second chance in case rndc fails.
131172877Sdougb	rc_pid=$(check_pidfile $pidfile $command)
132172877Sdougb	if [ -z "$rc_pid" ]; then
133172877Sdougb		[ -n "$rc_fast" ] && return 0
134172877Sdougb		_run_rc_notrunning
135172877Sdougb		return 1
136172877Sdougb	fi
137172877Sdougb	echo 'Stopping named.'
138172877Sdougb	if ${command%/named}/rndc stop 2>/dev/null; then
139172877Sdougb		wait_for_pids $rc_pid
140155595Sdougb	else
141172877Sdougb		echo -n 'rndc failed, trying kill: '
142172877Sdougb		kill -TERM $rc_pid
143172877Sdougb		wait_for_pids $rc_pid
144172877Sdougb  	fi
145155595Sdougb}
146155595Sdougb
147139066Speadarnamed_poststop()
148139066Speadar{
149155595Sdougb	if [ -n "${named_chrootdir}" -a -c ${named_chrootdir}/dev/null ]; then
150188293Sbz		if [ `${SYSCTL_N} security.jail.jailed` -eq 0 ]; then
151188293Sbz			umount ${named_chrootdir}/dev 2>/dev/null || true
152188293Sbz		else
153188293Sbz			warn "named chroot:" \
154188293Sbz			    "cannot unmount devfs from inside jail!"
155188293Sbz		fi
156139066Speadar	fi
157139066Speadar}
158139066Speadar
159192215Sdougbcreate_file () {
160192215Sdougb	if [ -e "$1" ]; then
161192215Sdougb		unlink $1
162192215Sdougb	fi
163192215Sdougb	> $1
164192215Sdougb	chown root:wheel $1
165192215Sdougb	chmod 644 $1
166192215Sdougb}
167192215Sdougb
168200448Sdougbnamed_prestart()
16998184Sgordon{
170220962Sdougb	find_pidfile
171220962Sdougb
172220962Sdougb	if [ -n "$named_pidfile" ]; then
173220962Sdougb		warn 'named_pidfile: now determined from the conf file'
174220962Sdougb	fi
175220962Sdougb
176200448Sdougb	command_args="-u ${named_uid:=root}"
177200448Sdougb
178200448Sdougb	if [ ! "$named_conf" = '/etc/namedb/named.conf' ]; then
179200448Sdougb		case "$named_flags" in
180200448Sdougb		-c*|*' -c'*) ;;		# No need to add it
181200448Sdougb		*) command_args="-c $named_conf $command_args" ;;
182200448Sdougb		esac
183200448Sdougb	fi
184200448Sdougb
185192215Sdougb	local line nsip firstns
186192215Sdougb
187124622Smtm	# Is the user using a sandbox?
188135875Sdougb	#
189126978Sdougb	if [ -n "$named_chrootdir" ]; then
190126978Sdougb		rc_flags="$rc_flags -t $named_chrootdir"
191126978Sdougb		checkyesno named_chroot_autoupdate && chroot_autoupdate
192135777Sdougb	else
193135777Sdougb		named_symlink_enable=NO
194124622Smtm	fi
195135703Sdougb
196135703Sdougb	# Create an rndc.key file for the user if none exists
197135875Sdougb	#
198200448Sdougb	confgen_command="${command%/named}/rndc-confgen -a -b256 -u $named_uid \
199201367Sdougb	    -c ${named_confdir}/rndc.key"
200201367Sdougb	if [ -s "${named_confdir}/rndc.conf" ]; then
201200448Sdougb		unset confgen_command
202135703Sdougb	fi
203201370Sdougb	if [ -s "${named_confdir}/rndc.key" ]; then
204201370Sdougb		case `stat -f%Su ${named_confdir}/rndc.key` in
205172877Sdougb		root|$named_uid) ;;
206172877Sdougb		*) $confgen_command ;;
207172877Sdougb		esac
208155595Sdougb	else
209155595Sdougb		$confgen_command
210155595Sdougb	fi
211192215Sdougb
212207346Sdougb	local checkconf
213207346Sdougb
214207346Sdougb	checkconf="${command%/named}/named-checkconf"
215207346Sdougb	if ! checkyesno named_chroot_autoupdate && [ -n "$named_chrootdir" ]; then
216207346Sdougb		checkconf="$checkconf -t $named_chrootdir"
217207346Sdougb	fi
218207346Sdougb
219192215Sdougb	# Create a forwarder configuration based on /etc/resolv.conf
220192215Sdougb	if checkyesno named_auto_forward; then
221192215Sdougb		if [ ! -s /etc/resolv.conf ]; then
222192215Sdougb			warn "named_auto_forward enabled, but no /etc/resolv.conf"
223192215Sdougb
224192215Sdougb			# Empty the file in case it is included in named.conf
225201367Sdougb			[ -s "${named_confdir}/auto_forward.conf" ] &&
226201367Sdougb			    create_file ${named_confdir}/auto_forward.conf
227192215Sdougb
228207346Sdougb			$checkconf $named_conf ||
229192215Sdougb			    err 3 'named-checkconf for $named_conf failed'
230192215Sdougb			return
231192215Sdougb		fi
232192215Sdougb
233192215Sdougb		create_file /var/run/naf-resolv.conf
234192215Sdougb		create_file /var/run/auto_forward.conf
235192215Sdougb
236192215Sdougb		echo '	forwarders {' > /var/run/auto_forward.conf
237192215Sdougb
238192215Sdougb		while read line; do
239192215Sdougb			case "$line" in
240192215Sdougb			'nameserver '*|'nameserver	'*)
241192215Sdougb				nsip=${line##nameserver[         ]}
242192215Sdougb
243192215Sdougb				if [ -z "$firstns" ]; then
244192215Sdougb					if [ ! "$nsip" = '127.0.0.1' ]; then
245192215Sdougb						echo 'nameserver 127.0.0.1'
246192215Sdougb						echo "		${nsip};" >> /var/run/auto_forward.conf
247192215Sdougb					fi
248192215Sdougb
249192215Sdougb					firstns=1
250192215Sdougb				else
251192215Sdougb					[ "$nsip" = '127.0.0.1' ] && continue
252192215Sdougb					echo "		${nsip};" >> /var/run/auto_forward.conf
253192215Sdougb				fi
254192215Sdougb				;;
255192215Sdougb			esac
256192215Sdougb
257192215Sdougb			echo $line
258192215Sdougb		done < /etc/resolv.conf > /var/run/naf-resolv.conf
259192215Sdougb
260192215Sdougb		echo '	};' >> /var/run/auto_forward.conf
261192215Sdougb		echo '' >> /var/run/auto_forward.conf
262192215Sdougb		if checkyesno named_auto_forward_only; then
263192215Sdougb			echo "	forward only;" >> /var/run/auto_forward.conf
264192215Sdougb		else
265192215Sdougb			echo "	forward first;" >> /var/run/auto_forward.conf
266192215Sdougb		fi
267192215Sdougb
268192215Sdougb		if cmp -s /etc/resolv.conf /var/run/naf-resolv.conf; then
269192215Sdougb			unlink /var/run/naf-resolv.conf
270192215Sdougb		else
271192215Sdougb			[ -e /etc/resolv.conf ] && unlink /etc/resolv.conf
272192215Sdougb			mv /var/run/naf-resolv.conf /etc/resolv.conf
273192215Sdougb		fi
274192215Sdougb
275201367Sdougb		if cmp -s ${named_confdir}/auto_forward.conf \
276192215Sdougb		    /var/run/auto_forward.conf; then
277192215Sdougb			unlink /var/run/auto_forward.conf
278192215Sdougb		else
279201367Sdougb			[ -e "${named_confdir}/auto_forward.conf" ] &&
280201367Sdougb			    unlink ${named_confdir}/auto_forward.conf
281192215Sdougb			mv /var/run/auto_forward.conf \
282201367Sdougb			    ${named_confdir}/auto_forward.conf
283192215Sdougb		fi
284192215Sdougb	else
285192215Sdougb		# Empty the file in case it is included in named.conf
286201367Sdougb		[ -s "${named_confdir}/auto_forward.conf" ] &&
287201367Sdougb		    create_file ${named_confdir}/auto_forward.conf
288192215Sdougb	fi
289192215Sdougb
290207346Sdougb	$checkconf $named_conf || err 3 'named-checkconf for $named_conf failed'
29198184Sgordon}
29298184Sgordon
29378344Sobrienload_rc_config $name
294200448Sdougb
295155595Sdougb# Updating the following variables requires that rc.conf be loaded first
29698184Sgordon#
29798184Sgordonrequired_dirs="$named_chrootdir"	# if it is set, it must exist
298207346Sdougb
299201367Sdougbnamed_confdir="${named_chrootdir}${named_conf%/*}"
30098184Sgordon
30178344Sobrienrun_rc_command "$1"
302