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