1#!/bin/sh 2# 3# PROVIDE: netwait 4# REQUIRE: devd ipfw pf routing 5# 6# The netwait script helps handle three situations: 7# - Systems with USB or other late-attaching network hardware which 8# is initialized by devd events. The script waits for all the 9# interfaces named in the netwait_if list to appear. 10# - Systems with IPv6 addresses, especially jails, where we need to 11# wait for DAD to complete before starting daemons, as they will 12# otherwise fail to bind to IN6ADDR_ANY. 13# - Systems with statically-configured IP addresses in rc.conf(5). 14# The IP addresses in the netwait_ip list are pinged. The script 15# waits for any single IP in the list to respond to the ping. If your 16# system uses DHCP, you should probably use synchronous_dhclient="YES" 17# in your /etc/rc.conf instead of netwait_ip. 18# Either or both of the wait lists can be used (at least one must be 19# non-empty if netwait is enabled). 20 21. /etc/rc.subr 22 23name="netwait" 24desc="Wait for network devices or the network being up" 25rcvar="netwait_enable" 26 27start_cmd="${name}_start" 28stop_cmd=":" 29 30netwait_start() 31{ 32 local ip rc count output link wait_if got_if any_error 33 34 if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ] && 35 ! checkyesno netwait_dad ; then 36 err 1 "Nothing to wait for" 37 fi 38 39 if ! [ "${netwait_if_timeout:=0}" -ge 1 ]; then 40 err 1 "netwait_if_timeout must be >= 1" 41 fi 42 if ! check_kern_features inet6; then 43 netwait_dad="NO" 44 elif ! [ "${netwait_dad_timeout:=0}" -ge 1 ]; then 45 netwait_dad_timeout=$(($(sysctl -n net.inet6.ip6.dad_count)+1)) 46 fi 47 if ! [ "${netwait_timeout:=0}" -ge 1 ]; then 48 err 1 "netwait_timeout must be >= 1" 49 fi 50 51 any_error=false 52 53 if [ -n "${netwait_if}" ]; then 54 for wait_if in ${netwait_if}; do 55 echo -n "Waiting for ${wait_if}" 56 link="" 57 got_if=false 58 count=1 59 # Handle SIGINT (Ctrl-C); force abort of while loop 60 trap break SIGINT 61 while [ ${count} -le ${netwait_if_timeout} ]; do 62 if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then 63 if ! ${got_if}; then 64 echo -n ", interface present" 65 got_if=true 66 fi 67 link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` 68 if [ -z "${link}" ]; then 69 echo ', got link.' 70 break 71 fi 72 fi 73 sleep 1 74 count=$((count+1)) 75 done 76 # Restore default SIGINT handler 77 trap - SIGINT 78 if ! ${got_if}; then 79 echo ", wait failed: interface never appeared." 80 any_error=true 81 elif [ -n "${link}" ]; then 82 echo ", wait failed: interface still has no link." 83 any_error=true 84 fi 85 done 86 fi 87 88 if checkyesno netwait_dad; then 89 got_dad=false 90 # Handle SIGINT (Ctrl-C); force abort of while loop 91 trap break SIGINT 92 93 echo -n "Waiting for DAD to complete" 94 count=1 95 while [ ${count} -le ${netwait_dad_timeout} ]; do 96 if ! ifconfig | grep -q 'inet6.*tentative'; then 97 echo ', done.' 98 got_dad=true 99 break 100 fi 101 sleep 1 102 count=$((count+1)) 103 done 104 105 # Restore default SIGINT handler 106 trap - SIGINT 107 108 if ! ${got_dad}; then 109 echo ', timed out.' 110 any_error=true 111 fi 112 fi 113 114 if [ -n "${netwait_ip}" ]; then 115 got_ip=false 116 # Handle SIGINT (Ctrl-C); force abort of for loop 117 trap break SIGINT 118 119 for ip in ${netwait_ip}; do 120 echo -n "Waiting for ${ip} to respond to ICMP ping" 121 122 count=1 123 while [ ${count} -le ${netwait_timeout} ]; do 124 /sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1 125 rc=$? 126 127 if [ $rc -eq 0 ]; then 128 echo ', got response.' 129 got_ip=false 130 break 2 131 fi 132 count=$((count+1)) 133 done 134 echo ', failed: No response from host.' 135 done 136 137 # Restore default SIGINT handler 138 trap - SIGINT 139 140 if ! ${got_ip}; then 141 any_error=true 142 fi 143 fi 144 145 if ${any_error}; then 146 warn "Continuing with startup, but be aware you may not have " 147 warn "a fully functional networking layer at this point." 148 fi 149} 150 151load_rc_config $name 152 153# doesn't make sense to run in a svcj: config setting 154netwait_svcj="NO" 155 156run_rc_command "$1" 157