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}" -ge 1 ]; then 40 err 1 "netwait_if_timeout must be >= 1" 41 fi 42 if ! [ "${netwait_dad_timeout}" -ge 1 ]; then 43 err 1 "netwait_dad_timeout must be >= 1" 44 fi 45 if ! [ "${netwait_timeout}" -ge 1 ]; then 46 err 1 "netwait_timeout must be >= 1" 47 fi 48 49 any_error=false 50 51 if [ -n "${netwait_if}" ]; then 52 for wait_if in ${netwait_if}; do 53 echo -n "Waiting for ${wait_if}" 54 link="" 55 got_if=false 56 count=1 57 # Handle SIGINT (Ctrl-C); force abort of while loop 58 trap break SIGINT 59 while [ ${count} -le ${netwait_if_timeout} ]; do 60 if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then 61 if ! ${got_if}; then 62 echo -n ", interface present" 63 got_if=true 64 fi 65 link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` 66 if [ -z "${link}" ]; then 67 echo ', got link.' 68 break 69 fi 70 fi 71 sleep 1 72 count=$((count+1)) 73 done 74 # Restore default SIGINT handler 75 trap - SIGINT 76 if ! ${got_if}; then 77 echo ", wait failed: interface never appeared." 78 any_error=true 79 elif [ -n "${link}" ]; then 80 echo ", wait failed: interface still has no link." 81 any_error=true 82 fi 83 done 84 fi 85 86 if checkyesno netwait_dad; then 87 got_dad=false 88 # Handle SIGINT (Ctrl-C); force abort of while loop 89 trap break SIGINT 90 91 echo -n "Waiting for DAD to complete" 92 count=1 93 while [ ${count} -le ${netwait_dad_timeout} ]; do 94 if ! ifconfig | grep -q 'inet6.*tentative'; then 95 echo ', done.' 96 got_dad=true 97 break 98 fi 99 sleep 1 100 count=$((count+1)) 101 done 102 103 # Restore default SIGINT handler 104 trap - SIGINT 105 106 if ! ${got_dad}; then 107 echo ', timed out.' 108 any_error=true 109 fi 110 fi 111 112 if [ -n "${netwait_ip}" ]; then 113 got_ip=false 114 # Handle SIGINT (Ctrl-C); force abort of for loop 115 trap break SIGINT 116 117 for ip in ${netwait_ip}; do 118 echo -n "Waiting for ${ip} to respond to ICMP ping" 119 120 count=1 121 while [ ${count} -le ${netwait_timeout} ]; do 122 /sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1 123 rc=$? 124 125 if [ $rc -eq 0 ]; then 126 echo ', got response.' 127 got_ip=false 128 break 2 129 fi 130 count=$((count+1)) 131 done 132 echo ', failed: No response from host.' 133 done 134 135 # Restore default SIGINT handler 136 trap - SIGINT 137 138 if ! ${got_ip}; then 139 any_error=true 140 fi 141 fi 142 143 if ${any_error}; then 144 warn "Continuing with startup, but be aware you may not have " 145 warn "a fully functional networking layer at this point." 146 fi 147} 148 149load_rc_config $name 150 151# doesn't make sense to run in a svcj: config setting 152netwait_svcj="NO" 153 154run_rc_command "$1" 155