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