xref: /freebsd/libexec/rc/rc.d/netwait (revision 7899f917b1c0ea178f1d2be0cfb452086d079d23)
1#!/bin/sh
2#
3# PROVIDE: netwait
4# REQUIRE: devd ipfw pf routing
5# KEYWORD: nojail
6#
7# The netwait script helps handle two situations:
8#  - Systems with USB or other late-attaching network hardware which
9#    is initialized by devd events.  The script waits for all the
10#    interfaces named in the netwait_if list to appear.
11#  - Systems with statically-configured IP addresses in rc.conf(5).
12#    The IP addresses in the netwait_ip list are pinged.  The script
13#    waits for any single IP in the list to respond to the ping.  If your
14#    system uses DHCP, you should probably use synchronous_dhclient="YES"
15#    in your /etc/rc.conf instead of netwait_ip.
16# Either or both of the wait lists can be used (at least one must be
17# non-empty if netwait is enabled).
18
19. /etc/rc.subr
20
21name="netwait"
22desc="Wait for network devices or the network being up"
23rcvar="netwait_enable"
24
25start_cmd="${name}_start"
26stop_cmd=":"
27
28netwait_start()
29{
30	local ip rc count output link wait_if got_if any_error
31
32	if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ]; then
33		err 1 "No interface or IP addresses listed, nothing to wait for"
34	fi
35
36	if [ ${netwait_timeout} -lt 1 ]; then
37		err 1 "netwait_timeout must be >= 1"
38	fi
39
40	if [ -n "${netwait_if}" ]; then
41		any_error=0
42		for wait_if in ${netwait_if}; do
43			echo -n "Waiting for ${wait_if}"
44			link=""
45			got_if=0
46			count=1
47			# Handle SIGINT (Ctrl-C); force abort of while() loop
48			trap break SIGINT
49			while [ ${count} -le ${netwait_if_timeout} ]; do
50				if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then
51					if [ ${got_if} -eq 0 ]; then
52						echo -n ", interface present"
53						got_if=1
54					fi
55					link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'`
56					if [ -z "${link}" ]; then
57						echo ', got link.'
58						break
59					fi
60				fi
61				sleep 1
62				count=$((count+1))
63			done
64			# Restore default SIGINT handler
65			trap - SIGINT
66			if [ ${got_if} -eq 0 ]; then
67				echo ", wait failed: interface never appeared."
68				any_error=1
69			elif [ -n "${link}" ]; then
70				echo ", wait failed: interface still has no link."
71				any_error=1
72			fi
73		done
74		if [ ${any_error} -eq 1 ]; then
75		    warn "Continuing with startup, but be aware you may not have "
76		    warn "a fully functional networking layer at this point."
77		fi
78	fi
79
80	if [ -n "${netwait_ip}" ]; then
81		# Handle SIGINT (Ctrl-C); force abort of for() loop
82		trap break SIGINT
83
84		for ip in ${netwait_ip}; do
85			echo -n "Waiting for ${ip} to respond to ICMP ping"
86
87			count=1
88			while [ ${count} -le ${netwait_timeout} ]; do
89				/sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1
90				rc=$?
91
92				if [ $rc -eq 0 ]; then
93					# Restore default SIGINT handler
94					trap - SIGINT
95
96					echo ', got response.'
97					return
98				fi
99				count=$((count+1))
100			done
101			echo ', failed: No response from host.'
102		done
103
104		# Restore default SIGINT handler
105		trap - SIGINT
106
107		warn "Exhausted IP list.  Continuing with startup, but be aware you may"
108		warn "not have a fully functional networking layer at this point."
109	fi
110
111}
112
113load_rc_config $name
114
115# doesn't make sense to run in a svcj: config setting
116netwait_svcj="NO"
117
118run_rc_command "$1"
119