diff options
Diffstat (limited to 'libexec/rc/rc.d/netwait')
-rwxr-xr-x | libexec/rc/rc.d/netwait | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/libexec/rc/rc.d/netwait b/libexec/rc/rc.d/netwait new file mode 100755 index 000000000000..05874552cf1c --- /dev/null +++ b/libexec/rc/rc.d/netwait @@ -0,0 +1,156 @@ +#!/bin/sh +# +# PROVIDE: netwait +# REQUIRE: devd ipfw pf routing +# +# The netwait script helps handle three situations: +# - Systems with USB or other late-attaching network hardware which +# is initialized by devd events. The script waits for all the +# interfaces named in the netwait_if list to appear. +# - Systems with IPv6 addresses, especially jails, where we need to +# wait for DAD to complete before starting daemons, as they will +# otherwise fail to bind to IN6ADDR_ANY. +# - Systems with statically-configured IP addresses in rc.conf(5). +# The IP addresses in the netwait_ip list are pinged. The script +# waits for any single IP in the list to respond to the ping. If your +# system uses DHCP, you should probably use synchronous_dhclient="YES" +# in your /etc/rc.conf instead of netwait_ip. +# Either or both of the wait lists can be used (at least one must be +# non-empty if netwait is enabled). + +. /etc/rc.subr + +name="netwait" +desc="Wait for network devices or the network being up" +rcvar="netwait_enable" + +start_cmd="${name}_start" +stop_cmd=":" + +netwait_start() +{ + local ip rc count output link wait_if got_if any_error + + if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ] && + ! checkyesno netwait_dad ; then + err 1 "Nothing to wait for" + fi + + if ! [ "${netwait_if_timeout:=0}" -ge 1 ]; then + err 1 "netwait_if_timeout must be >= 1" + fi + if ! check_kern_features inet6; then + netwait_dad="NO" + elif ! [ "${netwait_dad_timeout:=0}" -ge 1 ]; then + netwait_dad_timeout=$(($(sysctl -n net.inet6.ip6.dad_count)+1)) + fi + if ! [ "${netwait_timeout:=0}" -ge 1 ]; then + err 1 "netwait_timeout must be >= 1" + fi + + any_error=false + + if [ -n "${netwait_if}" ]; then + for wait_if in ${netwait_if}; do + echo -n "Waiting for ${wait_if}" + link="" + got_if=false + count=1 + # Handle SIGINT (Ctrl-C); force abort of while loop + trap break SIGINT + while [ ${count} -le ${netwait_if_timeout} ]; do + if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then + if ! ${got_if}; then + echo -n ", interface present" + got_if=true + fi + link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` + if [ -z "${link}" ]; then + echo ', got link.' + break + fi + fi + sleep 1 + count=$((count+1)) + done + # Restore default SIGINT handler + trap - SIGINT + if ! ${got_if}; then + echo ", wait failed: interface never appeared." + any_error=true + elif [ -n "${link}" ]; then + echo ", wait failed: interface still has no link." + any_error=true + fi + done + fi + + if checkyesno netwait_dad; then + got_dad=false + # Handle SIGINT (Ctrl-C); force abort of while loop + trap break SIGINT + + echo -n "Waiting for DAD to complete" + count=1 + while [ ${count} -le ${netwait_dad_timeout} ]; do + if ! ifconfig | grep -q 'inet6.*tentative'; then + echo ', done.' + got_dad=true + break + fi + sleep 1 + count=$((count+1)) + done + + # Restore default SIGINT handler + trap - SIGINT + + if ! ${got_dad}; then + echo ', timed out.' + any_error=true + fi + fi + + if [ -n "${netwait_ip}" ]; then + got_ip=false + # Handle SIGINT (Ctrl-C); force abort of for loop + trap break SIGINT + + for ip in ${netwait_ip}; do + echo -n "Waiting for ${ip} to respond to ICMP ping" + + count=1 + while [ ${count} -le ${netwait_timeout} ]; do + /sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1 + rc=$? + + if [ $rc -eq 0 ]; then + echo ', got response.' + got_ip=false + break 2 + fi + count=$((count+1)) + done + echo ', failed: No response from host.' + done + + # Restore default SIGINT handler + trap - SIGINT + + if ! ${got_ip}; then + any_error=true + fi + fi + + if ${any_error}; then + warn "Continuing with startup, but be aware you may not have " + warn "a fully functional networking layer at this point." + fi +} + +load_rc_config $name + +# doesn't make sense to run in a svcj: config setting +netwait_svcj="NO" + +run_rc_command "$1" |