# $OpenBSD: rc,v 1.463 2015/09/13 13:29:22 rpe Exp $ # System startup script run by init on autoboot or after single-user. # Output and error are redirected to console by init, and the console is the # controlling terminal. # Turn off Strict Bourne shell. set +o sh # Subroutines (have to come first). # Strip in- and whole-line comments from a file. # Strip leading and trailing whitespace if IFS is set. # Usage: stripcom /path/to/file stripcom() { local _file=$1 _line [[ -s $_file ]] || return while read _line ; do _line=${_line%%#*} [[ -n $_line ]] && print -r -- "$_line" done <$_file } # Update resource limits based on login.conf settings. # Usage: update_limit -flag capability update_limit() { local _flag=$1 # ulimit flag local _cap=$2 _val # login.conf capability and its value local _suffix for _suffix in {,-cur,-max}; do _val=$(getcap -f /etc/login.conf -s ${_cap}${_suffix} daemon 2>/dev/null) [[ -n $_val ]] || continue [[ $_val == infinity ]] && _val=unlimited case $_suffix in -cur) ulimit -S $_flag $_val ;; -max) ulimit -H $_flag $_val ;; *) ulimit $_flag $_val return ;; esac done } # Apply sysctl.conf(5) settings. sysctl_conf() { stripcom /etc/sysctl.conf | while read _line; do sysctl "$_line" case $_line in kern.maxproc=*) update_limit -p maxproc;; kern.maxfiles=*) update_limit -n openfiles;; esac done } # Apply mixerctl.conf(5) settings. mixerctl_conf() { stripcom /etc/mixerctl.conf | while read _line; do mixerctl -q "$_line" 2>/dev/null done } # Apply wsconsctl.conf(5) settings. wsconsctl_conf() { [[ -x /sbin/wsconsctl ]] || return stripcom /etc/wsconsctl.conf | while read _line; do eval "wsconsctl $_line" done } random_seed() { # push the old seed into the kernel dd if=/var/db/host.random of=/dev/random bs=65536 count=1 status=none chmod 600 /var/db/host.random # ... and create a future seed dd if=/dev/random of=/var/db/host.random bs=65536 count=1 status=none # and create a seed file for the boot-loader dd if=/dev/random of=/etc/random.seed bs=512 count=1 status=none chmod 600 /etc/random.seed } # Populate net.inet.(tcp|udp).baddynamic with the contents of /etc/services so # as to avoid randomly allocating source ports that correspond to well-known # services. # Usage: fill_baddynamic tcp|udp fill_baddynamic() { local _service=$1 local _sysctl="net.inet.${_service}.baddynamic" stripcom /etc/services | { _ban= while IFS=" /" read _name _port _srv _junk; do [[ $_srv == $_service ]] || continue _ban="${_ban:+$_ban,}+$_port" # Flush before argv gets too long if ((${#_ban} > 1024)); then sysctl -q "$_sysctl=$_ban" _ban= fi done [[ -n $_ban ]] && sysctl -q "$_sysctl=$_ban" } } # Start daemon using the rc.d daemon control scripts. # Usage: start_daemon daemon1 daemon2 daemon3 start_daemon() { local _daemon for _daemon; do eval "_do=\${${_daemon}_flags}" [[ $_do != NO ]] && /etc/rc.d/${_daemon} start done } # Generate keys for isakmpd, iked and sshd if the don't exist yet. make_keys() { local _isakmpd_key=/etc/isakmpd/private/local.key local _isakmpd_pub=/etc/isakmpd/local.pub local _iked_key=/etc/iked/private/local.key local _iked_pub=/etc/iked/local.pub if [[ ! -f $_isakmpd_key ]]; then echo -n "openssl: generating isakmpd/iked RSA keys... " if openssl genrsa -out $_isakmpd_key 2048 >/dev/null 2>&1 && chmod 600 $_isakmpd_key && openssl rsa -out $_isakmpd_pub -in $_isakmpd_key \ -pubout >/dev/null 2>&1; then echo done. else echo failed. fi fi if [[ ! -f $_iked_key ]]; then # Just copy the generated isakmpd key cp $_isakmpd_key $_iked_key chmod 600 $_iked_key cp $_isakmpd_pub $_iked_pub fi ssh-keygen -A } # Check filesystems, optionally by using a fsck(8) flag. # Usage: do_fsck [-flag] do_fsck() { fsck -p "$@" case $? in 0) ;; 2) exit 1 ;; 4) echo "Rebooting..." reboot echo "Reboot failed; help!" exit 1 ;; 8) echo "Automatic file system check failed; help!" exit 1 ;; 12) echo "Boot interrupted." exit 1 ;; 130) # Interrupt before catcher installed. exit 1 ;; *) echo "Unknown error; help!" exit 1 ;; esac } # End subroutines. stty status '^T' # Set shell to ignore SIGINT (2), but not children; shell catches SIGQUIT (3) # and returns to single user after fsck. trap : 2 trap : 3 # Shouldn't be needed. export HOME=/ export INRC=1 export PATH=/sbin:/bin:/usr/sbin:/usr/bin # Must set the domainname before rc.conf, so YP startup choices can be made. if [[ -s /etc/defaultdomain ]]; then domainname "$(stripcom /etc/defaultdomain)" fi # Need to get local functions from rc.subr. FUNCS_ONLY=1 . /etc/rc.d/rc.subr # Load rc.conf into scope. _rc_parse_conf if [[ $1 == shutdown ]]; then if echo 2>/dev/null >>/var/db/host.random || \ echo 2>/dev/null >>/etc/random.seed; then random_seed else echo warning: cannot write random seed to disk fi # If we are in secure level 0, asume single user mode. if (($(sysctl -n kern.securelevel) == 0)); then echo 'single user: not running shutdown scripts' else pkg_scripts=${pkg_scripts%%*( )} if [[ -n $pkg_scripts ]]; then echo -n 'stopping package daemons:' while [[ -n $pkg_scripts ]]; do _d=${pkg_scripts##* } pkg_scripts=${pkg_scripts%%*( )$_d} [[ -x /etc/rc.d/$_d ]] && /etc/rc.d/$_d stop done echo '.' fi [[ -f /etc/rc.shutdown ]] && sh /etc/rc.shutdown fi # Bring carp interfaces down gracefully. ifconfig | while read _if _junk; do case $_if in carp+([0-9]):) ifconfig ${_if%:} down ;; esac done exit 0 fi # Add swap block-devices. swapctl -A -t blk if [[ -e /fastboot ]]; then echo "Fast boot: skipping disk checks." elif [[ $1 == autoboot ]]; then echo "Automatic boot in progress: starting file system checks." do_fsck fi trap "echo 'Boot interrupted.'; exit 1" 3 umount -a >/dev/null 2>&1 mount -a -t nonfs,vnd mount -uw / # root on nfs requires this, others aren't hurt. rm -f /fastboot # XXX (root now writeable) # Set flags on ttys. (Do early, in case they use tty for SLIP in netstart.) echo 'setting tty flags' ttyflags -a if [ -f /sbin/kbd -a -f /etc/kbdtype ]; then kbd `cat /etc/kbdtype` fi wsconsctl_conf if [ X"${pf}" != X"NO" ]; then RULES="block all" RULES="$RULES\npass on lo0" RULES="$RULES\npass in proto tcp from any to any port ssh keep state" RULES="$RULES\npass out proto { tcp, udp } from any to any port domain keep state" RULES="$RULES\npass out inet proto icmp all icmp-type echoreq keep state" RULES="$RULES\npass out inet proto udp from any port bootpc to any port bootps" RULES="$RULES\npass in inet proto udp from any port bootps to any port bootpc" if ifconfig lo0 inet6 >/dev/null 2>&1; then RULES="$RULES\npass out inet6 proto icmp6 all icmp6-type neighbrsol" RULES="$RULES\npass in inet6 proto icmp6 all icmp6-type neighbradv" RULES="$RULES\npass out inet6 proto icmp6 all icmp6-type routersol" RULES="$RULES\npass in inet6 proto icmp6 all icmp6-type routeradv" RULES="$RULES\npass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server" RULES="$RULES\npass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client" fi RULES="$RULES\npass in proto carp keep state (no-sync)" RULES="$RULES\npass out proto carp !received-on any keep state (no-sync)" case `sysctl vfs.mounts.nfs 2>/dev/null` in *[1-9]*) # Don't kill NFS. RULES="set reassemble yes no-df\n$RULES" RULES="$RULES\npass in proto { tcp, udp } from any port { sunrpc, nfsd } to any" RULES="$RULES\npass out proto { tcp, udp } from any to any port { sunrpc, nfsd } !received-on any" ;; esac echo $RULES | pfctl -f - pfctl -e fi # Fill net.inet.(tcp|udp).baddynamic lists from /etc/services. fill_baddynamic udp fill_baddynamic tcp sysctl_conf # Set hostname, turn on network. echo 'starting network' ifconfig -g carp carpdemote 128 if [ -f /etc/resolv.conf.save ]; then mv -f /etc/resolv.conf.save /etc/resolv.conf touch /etc/resolv.conf fi sh /etc/netstart dmesg >/dev/random # Any write triggers a rekey. # Load pf rules and bring up pfsync interface. if [ X"${pf}" != X"NO" ]; then if [ -f /etc/pf.conf ]; then pfctl -f /etc/pf.conf fi # Bring up pfsync after the working ruleset has been loaded. if [ -f /etc/hostname.pfsync0 ]; then sh /etc/netstart pfsync0 fi fi mount -s /usr >/dev/null 2>&1 mount -s /var >/dev/null 2>&1 random_seed # Clean up left-over files. rm -f /etc/nologin /var/spool/lock/LCK.* /var/spool/uucp/STST/* (cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; }) (cd /var/authpf && rm -rf -- *) # Save a copy of the boot messages. dmesg >/var/run/dmesg.boot make_keys echo -n 'starting early daemons:' start_daemon syslogd ldattach pflogd nsd unbound ntpd start_daemon iscsid isakmpd iked sasyncd ldapd npppd echo '.' # Load IPsec rules. if [ X"${ipsec}" != X"NO" ]; then if [ -f /etc/ipsec.conf ]; then ipsecctl -f /etc/ipsec.conf fi fi echo -n 'starting RPC daemons:' start_daemon portmap ypldap if [ X"`domainname`" != X"" ]; then start_daemon ypserv ypbind yppasswdd fi start_daemon mountd nfsd lockd statd amd echo '.' mount -a swapctl -A -t noblk # Check and mount networked filesystems. do_fsck -N mount -a -N # /var/crash should be a directory or a symbolic link to the crash directory # if core dumps are to be saved. if [ -d /var/crash ]; then savecore ${savecore_flags} /var/crash fi if [ X"${check_quotas}" = X"YES" ]; then echo -n 'checking quotas:' quotacheck -a echo ' done.' quotaon -a fi kvm_mkdb # build kvm(3) databases dev_mkdb chmod 666 /dev/tty[pqrstuvwxyzPQRST]* chown root:wheel /dev/tty[pqrstuvwxyzPQRST]* # Check the password temp/lock file. if [ -f /etc/ptmp ]; then logger -s -p auth.err \ 'password file may be incorrect -- /etc/ptmp exists' fi echo clearing /tmp # Prune quickly with one rm, then use find to clean up /tmp/[lqv]* # (not needed with mfs /tmp, but doesn't hurt there...). (cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*) (cd /tmp && find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \ ! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;) # Create Unix sockets directories for X if needed and make sure they have # correct permissions. [[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix [ -f /etc/rc.securelevel ] && sh /etc/rc.securelevel # rc.securelevel did not specifically set -1 or 2, so select the default: 1. if [ `sysctl -n kern.securelevel` -eq 0 ]; then sysctl kern.securelevel=1 fi # Patch /etc/motd. if [ ! -f /etc/motd ]; then install -c -o root -g wheel -m 664 /dev/null /etc/motd fi if T=`mktemp /tmp/_motd.XXXXXXXXXX`; then sysctl -n kern.version | sed 1q >$T echo "" >>$T sed '1,/^$/d' >$T cmp -s $T /etc/motd || cp $T /etc/motd rm -f $T fi if [ X"${accounting}" = X"YES" ]; then if [ ! -f /var/account/acct ]; then touch /var/account/acct fi echo 'turning on accounting'; accton /var/account/acct fi if [ -f /sbin/ldconfig ]; then echo 'creating runtime link editor directory cache.' if [ -d /usr/local/lib ]; then shlib_dirs="/usr/local/lib $shlib_dirs" fi if [ -d /usr/X11R6/lib ]; then shlib_dirs="/usr/X11R6/lib $shlib_dirs" fi ldconfig $shlib_dirs fi echo 'preserving editor files.'; /usr/libexec/vi.recover echo -n 'starting network daemons:' start_daemon ldomd sshd snmpd ldpd ripd ospfd ospf6d bgpd ifstated start_daemon relayd dhcpd dhcrelay mrouted dvmrpd radiusd if ifconfig lo0 inet6 >/dev/null 2>&1; then fw=`sysctl -n net.inet6.ip6.forwarding` if [ X"${fw}" = X"1" ]; then start_daemon route6d rtadvd fi fi start_daemon hostapd lpd smtpd slowcgi httpd ftpd start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd start_daemon rbootd mopd spamd spamlogd sndiod echo '.' # If rc.firsttime exists, run it just once, and make sure it is deleted. if [ -f /etc/rc.firsttime ]; then mv /etc/rc.firsttime /etc/rc.firsttime.run . /etc/rc.firsttime.run 2>&1 | tee /dev/tty | mail -Es "`hostname` rc.firsttime output" root >/dev/null fi rm -f /etc/rc.firsttime.run # Run rc.d(8) scripts from packages. if [ -n "${pkg_scripts}" ]; then echo -n 'starting package daemons:' for _r in $pkg_scripts; do if [ -x /etc/rc.d/${_r} ]; then start_daemon ${_r} else echo -n " ${_r}(absent)" fi done echo '.' fi [ -f /etc/rc.local ] && sh /etc/rc.local ifconfig -g carp -carpdemote 128 # disable carp interlock mixerctl_conf echo -n 'starting local daemons:' start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xdm echo '.' date exit 0