xref: /openbsd/etc/rc (revision a6445c1d)
1#	$OpenBSD: rc,v 1.444 2014/11/17 18:19:08 deraadt Exp $
2
3# System startup script run by init on autoboot
4# or after single-user.
5# Output and error are redirected to console by init,
6# and the console is the controlling terminal.
7
8# Subroutines (have to come first).
9
10# Strip comments (and leading/trailing whitespace if IFS is set)
11# from a file and spew to stdout
12stripcom() {
13	local _file="$1"
14	local _line
15
16	{
17		while read _line ; do
18			_line=${_line%%#*}		# strip comments
19			test -z "$_line" && continue
20			echo $_line
21		done
22	} < $_file
23}
24
25# Update resource limits when sysctl changes
26# Usage: update_limit -X loginconf_name
27update_limit() {
28	local _fl="$1"	# ulimit flag
29	local _lc="$2"	# login.conf name
30	local _new _suf
31
32	for _suf in "" -cur -max; do
33		_new=`getcap -f /etc/login.conf -s ${_lc}${_suf} daemon 2>/dev/null`
34		if [ X"$_new" != X"" ]; then
35			if [ X"$_new" = X"infinity" ]; then
36				_new=unlimited
37			fi
38			case "$_suf" in
39			-cur)
40				ulimit -S $_fl $_new
41				;;
42			-max)
43				ulimit -H $_fl $_new
44				;;
45			*)
46				ulimit $_fl $_new
47				return
48				;;
49			esac
50		fi
51	done
52}
53
54sysctl_conf() {
55	test -s /etc/sysctl.conf || return
56
57	# delete comments and blank lines
58	set -- `stripcom /etc/sysctl.conf`
59	while [ $# -ge 1 ] ; do
60		sysctl $1
61		# update limits if needed
62		case $1 in
63		kern.maxproc=*)
64			update_limit -p maxproc
65			;;
66		kern.maxfiles=*)
67			update_limit -n openfiles
68			;;
69		esac
70		shift
71	done
72}
73
74mixerctl_conf()
75{
76	test -s /etc/mixerctl.conf || return
77
78	# delete comments and blank lines
79	set -- `stripcom /etc/mixerctl.conf`
80	while [ $# -ge 1 ] ; do
81		mixerctl -q $1 > /dev/null 2>&1
82		shift
83	done
84}
85
86wsconsctl_conf()
87{
88	local save_IFS="$IFS"
89
90	test -x /sbin/wsconsctl -a -s /etc/wsconsctl.conf || return
91	# delete comments and blank lines
92	IFS="
93"
94	set -- `stripcom /etc/wsconsctl.conf`
95	IFS="$save_IFS"
96	while [ $# -ge 1 ] ; do
97		eval wsconsctl $1
98		shift
99	done
100}
101
102random_seed()
103{
104	# push the old seed into the kernel
105	dd if=/var/db/host.random of=/dev/random bs=65536 count=1 status=none
106	chmod 600 /var/db/host.random
107	# ... and create a future seed
108	dd if=/dev/random of=/var/db/host.random bs=65536 count=1 status=none
109	# and create a seed file for the boot-loader
110	dd if=/dev/random of=/etc/random.seed bs=512 count=1 status=none
111	chmod 600 /etc/random.seed
112}
113
114fill_baddynamic()
115{
116	local _service=$1
117	local _sysctl="net.inet.${_service}.baddynamic"
118	stripcom /etc/services |
119	{
120		# Variables are local
121		while IFS=" 	/" read _name _port _srv _junk; do
122			[ "x${_srv}" = "x${_service}" ] || continue
123			_ban="${_ban:+${_ban},}+${_port}"
124			# Flush before argv gets too long
125			if [ ${#_ban} -gt 1024 ]; then
126				sysctl -q ${_sysctl}=${_ban}
127				_ban=""
128			fi
129		done
130		[ "${_ban}" ] && sysctl -q ${_sysctl}=${_ban}
131	}
132}
133
134start_daemon()
135{
136	local _n
137	for _n; do
138		eval _do=\${${_n}_flags}
139		if [ X"${_do}" != X"NO" ]; then
140			/etc/rc.d/${_n} start
141		fi
142	done
143}
144
145make_keys()
146{
147	if [ ! -f /etc/isakmpd/private/local.key ]; then
148		echo -n "openssl: generating isakmpd/iked RSA key... "
149		if openssl genrsa -out /etc/isakmpd/private/local.key 2048 \
150		    >/dev/null 2>&1; then
151			chmod 600 /etc/isakmpd/private/local.key
152			openssl rsa -out /etc/isakmpd/local.pub -in \
153			    /etc/isakmpd/private/local.key -pubout \
154			    >/dev/null 2>&1
155			echo done.
156		else
157			echo failed.
158		fi
159	fi
160
161	if [ ! -f /etc/iked/private/local.key ]; then
162		# Just copy the generated isakmpd key
163		cp /etc/isakmpd/private/local.key /etc/iked/private/local.key
164		chmod 600 /etc/iked/private/local.key
165		cp /etc/isakmpd/local.pub /etc/iked/local.pub
166	fi
167
168	ssh-keygen -A
169}
170
171# create Unix sockets directories for X if needed and make sure they have
172# correct permissions
173setup_X_sockets()
174{
175	if [ -d /usr/X11R6/lib ]; then
176		for d in /tmp/.X11-unix /tmp/.ICE-unix ; do
177			if [ -d $d ]; then
178				if [ `ls -ld $d | cut -d' ' -f4` \
179				    != root ]; then
180					chown root $d
181				fi
182				if [ `ls -ld $d | cut -d' ' -f1` \
183				    != drwxrwxrwt ]; then
184					chmod 1777 $d
185				fi
186			elif [ -e $d ]; then
187				echo "Error: $d exists and isn't a directory."
188			else
189				mkdir -m 1777 $d
190			fi
191		done
192	fi
193}
194
195do_fsck()
196{
197	local _flags=$1
198
199	fsck -p $_flags
200	case $? in
201	0)
202		;;
203	2)
204		exit 1
205		;;
206	4)
207		echo "Rebooting..."
208		reboot
209		echo "Reboot failed; help!"
210		exit 1
211		;;
212	8)
213		echo "Automatic file system check failed; help!"
214		exit 1
215		;;
216	12)
217		echo "Boot interrupted."
218		exit 1
219		;;
220	130)
221		# interrupt before catcher installed
222		exit 1
223		;;
224	*)
225		echo "Unknown error; help!"
226		exit 1
227		;;
228	esac
229}
230
231# End subroutines
232
233stty status '^T'
234
235# Set shell to ignore SIGINT (2), but not children;
236# shell catches SIGQUIT (3) and returns to single user after fsck.
237trap : 2
238trap : 3	# shouldn't be needed
239
240HOME=/; export HOME
241INRC=1; export INRC
242PATH=/sbin:/bin:/usr/sbin:/usr/bin
243export PATH
244
245# must set the domainname before rc.conf, so YP startup choices can be made
246if [ -f /etc/defaultdomain ]; then
247	domainname `stripcom /etc/defaultdomain`
248fi
249
250# need to get local functions from rc.subr
251FUNCS_ONLY=1 . /etc/rc.d/rc.subr
252
253# load rc.conf into scope
254_rc_parse_conf
255
256if [ X"$1" = X"shutdown" ]; then
257	if echo 2>/dev/null >>/var/db/host.random || \
258	    echo 2>/dev/null >>/etc/random.seed; then
259		random_seed
260	else
261		echo warning: cannot write random seed to disk
262	fi
263
264	# If we are in secure level 0, assume single user mode.
265	if [ `sysctl -n kern.securelevel` -ne 0 ]; then
266		pkg_scripts=${pkg_scripts%%*( )}
267		if [ -n "${pkg_scripts}" ]; then
268			echo -n 'stopping package daemons:'
269			while [ -n "${pkg_scripts}" ]; do
270				_r=${pkg_scripts##* }
271				pkg_scripts=${pkg_scripts%%*( )${_r}}
272				[ -x /etc/rc.d/${_r} ] && /etc/rc.d/${_r} stop
273			done
274			echo '.'
275		fi
276
277		[ -f /etc/rc.shutdown ] && sh /etc/rc.shutdown
278	else
279		echo single user: not running shutdown scripts
280	fi
281
282	# bring carp interfaces down gracefully
283	ifconfig | while read a b; do
284		case $a in
285		carp+([0-9]):) ifconfig ${a%:} down ;;
286		esac
287	done
288
289	exit 0
290fi
291
292swapctl -A -t blk
293
294if [ -e /fastboot ]; then
295	echo "Fast boot: skipping disk checks."
296elif [ X"$1" = X"autoboot" ]; then
297	echo "Automatic boot in progress: starting file system checks."
298	do_fsck
299fi
300
301trap "echo 'Boot interrupted.'; exit 1" 3
302
303umount -a >/dev/null 2>&1
304mount -a -t nonfs,vnd
305mount -uw /		# root on nfs requires this, others aren't hurt
306rm -f /fastboot		# XXX (root now writeable)
307
308# set flags on ttys.  (do early, in case they use tty for SLIP in netstart)
309echo 'setting tty flags'
310ttyflags -a
311
312if [ -f /sbin/kbd -a -f /etc/kbdtype ]; then
313	kbd `cat /etc/kbdtype`
314fi
315
316wsconsctl_conf
317
318if [ X"${pf}" != X"NO" ]; then
319	RULES="block all"
320	RULES="$RULES\npass on lo0"
321	RULES="$RULES\npass in proto tcp from any to any port 22 keep state"
322	RULES="$RULES\npass out proto { tcp, udp } from any to any port 53 keep state"
323	RULES="$RULES\npass out inet proto icmp all icmp-type echoreq keep state"
324	RULES="$RULES\npass out inet proto udp from any port bootpc to any port bootps"
325	RULES="$RULES\npass in inet proto udp from any port bootps to any port bootpc"
326	if ifconfig lo0 inet6 >/dev/null 2>&1; then
327		RULES="$RULES\npass out inet6 proto icmp6 all icmp6-type neighbrsol"
328		RULES="$RULES\npass in inet6 proto icmp6 all icmp6-type neighbradv"
329		RULES="$RULES\npass out inet6 proto icmp6 all icmp6-type routersol"
330		RULES="$RULES\npass in inet6 proto icmp6 all icmp6-type routeradv"
331		RULES="$RULES\npass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server"
332		RULES="$RULES\npass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client"
333	fi
334	RULES="$RULES\npass in proto carp keep state (no-sync)"
335	RULES="$RULES\npass out proto carp !received-on any keep state (no-sync)"
336	case `sysctl vfs.mounts.nfs 2>/dev/null` in
337	*[1-9]*)
338		# don't kill NFS
339		RULES="set reassemble yes no-df\n$RULES"
340		RULES="$RULES\npass in proto { tcp, udp } from any port { 111, 2049 } to any"
341		RULES="$RULES\npass out proto { tcp, udp } from any to any port { 111, 2049 } !received-on any"
342		;;
343	esac
344	echo $RULES | pfctl -f -
345	pfctl -e
346fi
347
348# Fill net.inet.(tcp|udp).baddynamic lists from /etc/services
349fill_baddynamic udp
350fill_baddynamic tcp
351
352sysctl_conf
353
354# set hostname, turn on network
355echo 'starting network'
356ifconfig -g carp carpdemote 128
357if [ -f /etc/resolv.conf.save ]; then
358	mv -f /etc/resolv.conf.save /etc/resolv.conf
359	touch /etc/resolv.conf
360fi
361sh /etc/netstart
362dmesg > /dev/random	# any write triggers an RC4 rekey
363
364if [ X"${pf}" != X"NO" ]; then
365	if [ -f ${pf_rules} ]; then
366		pfctl -f ${pf_rules}
367	fi
368	# bring up pfsync after the working ruleset has been loaded
369	if [ -f /etc/hostname.pfsync0 ]; then
370		sh /etc/netstart pfsync0
371	fi
372fi
373
374mount -s /usr >/dev/null 2>&1
375mount -s /var >/dev/null 2>&1
376
377random_seed
378
379# clean up left-over files
380rm -f /etc/nologin /var/spool/lock/LCK.* /var/spool/uucp/STST/*
381(cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; })
382(cd /var/authpf && rm -rf -- *)
383
384# save a copy of the boot messages
385dmesg >/var/run/dmesg.boot
386
387make_keys
388
389echo -n 'starting early daemons:'
390start_daemon syslogd ldattach pflogd nsd unbound ntpd
391start_daemon iscsid isakmpd iked sasyncd ldapd npppd
392echo '.'
393
394if [ X"${ipsec}" != X"NO" ]; then
395	if [ -f ${ipsec_rules} ]; then
396		ipsecctl -f ${ipsec_rules}
397	fi
398fi
399
400echo -n 'starting RPC daemons:'
401start_daemon portmap ypldap
402if [ X"`domainname`" != X"" ]; then
403	start_daemon ypserv ypbind yppasswdd
404fi
405start_daemon mountd nfsd lockd statd amd
406echo '.'
407
408mount -a
409swapctl -A -t noblk
410
411# check and mount networked filesystems
412do_fsck -N
413mount -a -N
414
415# /var/crash should be a directory or a symbolic link
416# to the crash directory if core dumps are to be saved.
417if [ -d /var/crash ]; then
418	savecore ${savecore_flags} /var/crash
419fi
420
421if [ X"${check_quotas}" = X"YES" ]; then
422	echo -n 'checking quotas:'
423	quotacheck -a
424	echo ' done.'
425	quotaon -a
426fi
427
428kvm_mkdb			# build kvm(3) databases
429dev_mkdb
430chmod 666 /dev/tty[pqrstuvwxyzPQRST]*
431chown root:wheel /dev/tty[pqrstuvwxyzPQRST]*
432
433# check the password temp/lock file
434if [ -f /etc/ptmp ]; then
435	logger -s -p auth.err \
436	    'password file may be incorrect -- /etc/ptmp exists'
437fi
438
439echo clearing /tmp
440
441# prune quickly with one rm, then use find to clean up /tmp/[lqv]*
442# (not needed with mfs /tmp, but doesn't hurt there...)
443(cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*)
444(cd /tmp &&
445    find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \
446	! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;)
447
448setup_X_sockets
449
450[ -f /etc/rc.securelevel ] && sh /etc/rc.securelevel
451# rc.securelevel did not specifically set -1 or 2, so select the default: 1
452if [ `sysctl -n kern.securelevel` -eq 0 ]; then
453	sysctl kern.securelevel=1
454fi
455
456# patch /etc/motd
457if [ ! -f /etc/motd ]; then
458	install -c -o root -g wheel -m 664 /dev/null /etc/motd
459fi
460if T=`mktemp /tmp/_motd.XXXXXXXXXX`; then
461	sysctl -n kern.version | sed 1q > $T
462	echo "" >> $T
463	sed '1,/^$/d' < /etc/motd >> $T
464	cmp -s $T /etc/motd || cp $T /etc/motd
465	rm -f $T
466fi
467
468if [ X"${accounting}" = X"YES" ]; then
469	if [ ! -f /var/account/acct ]; then
470		touch /var/account/acct
471	fi
472	echo 'turning on accounting';	accton /var/account/acct
473fi
474
475if [ -f /sbin/ldconfig ]; then
476	echo 'creating runtime link editor directory cache.'
477	if [ -d /usr/local/lib ]; then
478		shlib_dirs="/usr/local/lib $shlib_dirs"
479	fi
480	if [ -d /usr/X11R6/lib ]; then
481		shlib_dirs="/usr/X11R6/lib $shlib_dirs"
482	fi
483	ldconfig $shlib_dirs
484fi
485
486echo 'preserving editor files.';	/usr/libexec/vi.recover
487
488echo -n 'starting network daemons:'
489start_daemon ldomd sshd snmpd ldpd ripd ospfd ospf6d bgpd ifstated
490start_daemon relayd dhcpd dhcrelay mrouted dvmrpd
491
492if ifconfig lo0 inet6 >/dev/null 2>&1; then
493	fw=`sysctl -n net.inet6.ip6.forwarding`
494	if [ X"${fw}" = X"0" ]; then
495		start_daemon rtsold
496	else
497		start_daemon route6d rtadvd
498	fi
499fi
500
501start_daemon hostapd lpd smtpd slowcgi httpd ftpd
502start_daemon ftpproxy tftpd tftpproxy identd inetd rarpd bootparamd
503start_daemon rbootd mopd spamd spamlogd sndiod
504echo '.'
505
506# If rc.firstime exists, run it just once, and make sure it is deleted
507if [ -f /etc/rc.firsttime ]; then
508	mv /etc/rc.firsttime /etc/rc.firsttime.run
509	. /etc/rc.firsttime.run 2>&1 | tee /dev/tty |
510		mail -Es "`hostname` rc.firsttime output" root >/dev/null
511fi
512rm -f /etc/rc.firsttime.run
513
514# Run rc.d(8) scripts from packages
515if [ -n "${pkg_scripts}" ]; then
516	echo -n 'starting package daemons:'
517	for _r in $pkg_scripts; do
518		if [ -x /etc/rc.d/${_r} ]; then
519			start_daemon ${_r}
520		else
521			echo -n " ${_r}(absent)"
522		fi
523	done
524	echo '.'
525fi
526
527[ -f /etc/rc.local ] && sh /etc/rc.local
528
529ifconfig -g carp -carpdemote 128	# disable carp interlock
530
531mixerctl_conf
532echo -n 'starting local daemons:'
533start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xdm
534echo '.'
535
536date
537exit 0
538