aboutsummaryrefslogtreecommitdiff
path: root/libexec/rc/rc.d/netwait
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/rc/rc.d/netwait')
-rwxr-xr-xlibexec/rc/rc.d/netwait156
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"