1228753Smm#!/bin/sh
2228753Smm
3228753Smm# $FreeBSD$
4228753Smm#
5228753Smm# PROVIDE: netwait
6228753Smm# REQUIRE: devd ipfilter ipfw pf routing
7228753Smm# KEYWORD: nojail
8228753Smm#
9228753Smm# The netwait script helps handle two situations:
10228753Smm#  - Systems with USB or other late-attaching network hardware which
11228753Smm#    is initialized by devd events.  The script waits for all the
12228753Smm#    interfaces named in the netwait_if list to appear.
13228753Smm#  - Systems with statically-configured IP addresses in rc.conf(5).
14228753Smm#    The IP addresses in the netwait_ip list are pinged.  The script
15228753Smm#    waits for any single IP in the list to respond to the ping.  If your
16228753Smm#    system uses DHCP, you should probably use synchronous_dhclient="YES"
17228753Smm#    in your /etc/rc.conf instead of netwait_ip.
18228753Smm# Either or both of the wait lists can be used (at least one must be
19228753Smm# non-empty if netwait is enabled).
20228753Smm
21228753Smm. /etc/rc.subr
22228753Smm
23228753Smmname="netwait"
24228753Smmrcvar="netwait_enable"
25228763Smm
26228753Smmstart_cmd="${name}_start"
27228753Smmstop_cmd=":"
28228753Smm
29228753Smmnetwait_start()
30228753Smm{
31228753Smm	local ip rc count output link wait_if got_if any_error
32228753Smm
33228753Smm	if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ]; then
34228753Smm		err 1 "No interface or IP addresses listed, nothing to wait for"
35228753Smm	fi
36228753Smm
37228753Smm	if [ ${netwait_timeout} -lt 1 ]; then
38228753Smm		err 1 "netwait_timeout must be >= 1"
39228753Smm	fi
40228753Smm
41228753Smm	if [ -n "${netwait_if}" ]; then
42228753Smm		any_error=0
43228753Smm		for wait_if in ${netwait_if}; do
44228753Smm			echo -n "Waiting for ${wait_if}"
45302001Smm			link=""
46302001Smm			got_if=0
47302001Smm			count=1
48302001Smm			# Handle SIGINT (Ctrl-C); force abort of while() loop
49228753Smm			trap break SIGINT
50228753Smm			while [ ${count} -le ${netwait_if_timeout} ]; do
51228753Smm				if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then
52228753Smm					if [ ${got_if} -eq 0 ]; then
53228753Smm						echo -n ", interface present"
54228753Smm						got_if=1
55228753Smm					fi
56228753Smm					link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'`
57228753Smm					if [ -z "${link}" ]; then
58228753Smm						echo ', got link.'
59228753Smm						break
60228753Smm					fi
61228753Smm				fi
62228753Smm				sleep 1
63228753Smm				count=$((count+1))
64228753Smm			done
65228753Smm			# Restore default SIGINT handler
66228753Smm			trap - SIGINT
67228753Smm			if [ ${got_if} -eq 0 ]; then
68228753Smm				echo ", wait failed: interface never appeared."
69228753Smm				any_error=1
70228753Smm			elif [ -n "${link}" ]; then
71228753Smm				echo ", wait failed: interface still has no link."
72228753Smm				any_error=1
73228753Smm			fi
74228753Smm		done
75228753Smm		if [ ${any_error} -eq 1 ]; then
76228753Smm		    warn "Continuing with startup, but be aware you may not have "
77228753Smm		    warn "a fully functional networking layer at this point."
78		fi
79	fi
80	
81	if [ -n "${netwait_ip}" ]; then
82		# Handle SIGINT (Ctrl-C); force abort of for() loop
83		trap break SIGINT
84
85		for ip in ${netwait_ip}; do
86			echo -n "Waiting for ${ip} to respond to ICMP ping"
87
88			count=1
89			while [ ${count} -le ${netwait_timeout} ]; do
90				/sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1
91				rc=$?
92
93				if [ $rc -eq 0 ]; then
94					# Restore default SIGINT handler
95					trap - SIGINT
96
97					echo ', got response.'
98					return
99				fi
100				count=$((count+1))
101			done
102			echo ', failed: No response from host.'
103		done
104
105		# Restore default SIGINT handler
106		trap - SIGINT
107
108		warn "Exhausted IP list.  Continuing with startup, but be aware you may"
109		warn "not have a fully functional networking layer at this point."
110	fi
111
112}
113
114load_rc_config $name
115run_rc_command "$1"
116