xref: /freebsd/libexec/rc/rc.d/netwait (revision ec6ad605ecea5c4a76d2e744df0265cc3f3a01b9)
10696600cSBjoern A. Zeeb#!/bin/sh
20696600cSBjoern A. Zeeb#
30696600cSBjoern A. Zeeb# PROVIDE: netwait
451da4b19SCy Schubert# REQUIRE: devd ipfw pf routing
50696600cSBjoern A. Zeeb#
65ead817cSDag-Erling Smørgrav# The netwait script helps handle three situations:
70696600cSBjoern A. Zeeb#  - Systems with USB or other late-attaching network hardware which
80696600cSBjoern A. Zeeb#    is initialized by devd events.  The script waits for all the
90696600cSBjoern A. Zeeb#    interfaces named in the netwait_if list to appear.
105ead817cSDag-Erling Smørgrav#  - Systems with IPv6 addresses, especially jails, where we need to
115ead817cSDag-Erling Smørgrav#    wait for DAD to complete before starting daemons, as they will
125ead817cSDag-Erling Smørgrav#    otherwise fail to bind to IN6ADDR_ANY.
130696600cSBjoern A. Zeeb#  - Systems with statically-configured IP addresses in rc.conf(5).
140696600cSBjoern A. Zeeb#    The IP addresses in the netwait_ip list are pinged.  The script
150696600cSBjoern A. Zeeb#    waits for any single IP in the list to respond to the ping.  If your
160696600cSBjoern A. Zeeb#    system uses DHCP, you should probably use synchronous_dhclient="YES"
170696600cSBjoern A. Zeeb#    in your /etc/rc.conf instead of netwait_ip.
180696600cSBjoern A. Zeeb# Either or both of the wait lists can be used (at least one must be
190696600cSBjoern A. Zeeb# non-empty if netwait is enabled).
200696600cSBjoern A. Zeeb
210696600cSBjoern A. Zeeb. /etc/rc.subr
220696600cSBjoern A. Zeeb
230696600cSBjoern A. Zeebname="netwait"
240696600cSBjoern A. Zeebdesc="Wait for network devices or the network being up"
250696600cSBjoern A. Zeebrcvar="netwait_enable"
260696600cSBjoern A. Zeeb
270696600cSBjoern A. Zeebstart_cmd="${name}_start"
280696600cSBjoern A. Zeebstop_cmd=":"
290696600cSBjoern A. Zeeb
300696600cSBjoern A. Zeebnetwait_start()
310696600cSBjoern A. Zeeb{
320696600cSBjoern A. Zeeb	local ip rc count output link wait_if got_if any_error
330696600cSBjoern A. Zeeb
345ead817cSDag-Erling Smørgrav	if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ] &&
355ead817cSDag-Erling Smørgrav	   ! checkyesno netwait_dad ; then
365ead817cSDag-Erling Smørgrav		err 1 "Nothing to wait for"
370696600cSBjoern A. Zeeb	fi
380696600cSBjoern A. Zeeb
39*ec6ad605SDag-Erling Smørgrav	if ! [ "${netwait_if_timeout:=0}" -ge 1 ]; then
405ead817cSDag-Erling Smørgrav		err 1 "netwait_if_timeout must be >= 1"
415ead817cSDag-Erling Smørgrav	fi
42*ec6ad605SDag-Erling Smørgrav	if ! check_kern_features inet6; then
43*ec6ad605SDag-Erling Smørgrav		netwait_dad="NO"
44*ec6ad605SDag-Erling Smørgrav	elif ! [ "${netwait_dad_timeout:=0}" -ge 1 ]; then
45*ec6ad605SDag-Erling Smørgrav		netwait_dad_timeout=$(($(sysctl -n net.inet6.ip6.dad_count)+1))
465ead817cSDag-Erling Smørgrav	fi
47*ec6ad605SDag-Erling Smørgrav	if ! [ "${netwait_timeout:=0}" -ge 1 ]; then
480696600cSBjoern A. Zeeb		err 1 "netwait_timeout must be >= 1"
490696600cSBjoern A. Zeeb	fi
500696600cSBjoern A. Zeeb
515ead817cSDag-Erling Smørgrav	any_error=false
525ead817cSDag-Erling Smørgrav
530696600cSBjoern A. Zeeb	if [ -n "${netwait_if}" ]; then
540696600cSBjoern A. Zeeb		for wait_if in ${netwait_if}; do
550696600cSBjoern A. Zeeb			echo -n "Waiting for ${wait_if}"
560696600cSBjoern A. Zeeb			link=""
575ead817cSDag-Erling Smørgrav			got_if=false
580696600cSBjoern A. Zeeb			count=1
595ead817cSDag-Erling Smørgrav			# Handle SIGINT (Ctrl-C); force abort of while loop
600696600cSBjoern A. Zeeb			trap break SIGINT
610696600cSBjoern A. Zeeb			while [ ${count} -le ${netwait_if_timeout} ]; do
620696600cSBjoern A. Zeeb				if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then
635ead817cSDag-Erling Smørgrav					if ! ${got_if}; then
640696600cSBjoern A. Zeeb						echo -n ", interface present"
655ead817cSDag-Erling Smørgrav						got_if=true
660696600cSBjoern A. Zeeb					fi
670696600cSBjoern A. Zeeb					link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'`
680696600cSBjoern A. Zeeb					if [ -z "${link}" ]; then
690696600cSBjoern A. Zeeb						echo ', got link.'
700696600cSBjoern A. Zeeb						break
710696600cSBjoern A. Zeeb					fi
720696600cSBjoern A. Zeeb				fi
730696600cSBjoern A. Zeeb				sleep 1
740696600cSBjoern A. Zeeb				count=$((count+1))
750696600cSBjoern A. Zeeb			done
760696600cSBjoern A. Zeeb			# Restore default SIGINT handler
770696600cSBjoern A. Zeeb			trap - SIGINT
785ead817cSDag-Erling Smørgrav			if ! ${got_if}; then
790696600cSBjoern A. Zeeb				echo ", wait failed: interface never appeared."
805ead817cSDag-Erling Smørgrav				any_error=true
810696600cSBjoern A. Zeeb			elif [ -n "${link}" ]; then
820696600cSBjoern A. Zeeb				echo ", wait failed: interface still has no link."
835ead817cSDag-Erling Smørgrav				any_error=true
840696600cSBjoern A. Zeeb			fi
850696600cSBjoern A. Zeeb		done
865ead817cSDag-Erling Smørgrav	fi
875ead817cSDag-Erling Smørgrav
885ead817cSDag-Erling Smørgrav	if checkyesno netwait_dad; then
895ead817cSDag-Erling Smørgrav		got_dad=false
905ead817cSDag-Erling Smørgrav		# Handle SIGINT (Ctrl-C); force abort of while loop
915ead817cSDag-Erling Smørgrav		trap break SIGINT
925ead817cSDag-Erling Smørgrav
935ead817cSDag-Erling Smørgrav		echo -n "Waiting for DAD to complete"
945ead817cSDag-Erling Smørgrav		count=1
955ead817cSDag-Erling Smørgrav		while [ ${count} -le ${netwait_dad_timeout} ]; do
965ead817cSDag-Erling Smørgrav			if ! ifconfig | grep -q 'inet6.*tentative'; then
975ead817cSDag-Erling Smørgrav				echo ', done.'
985ead817cSDag-Erling Smørgrav				got_dad=true
995ead817cSDag-Erling Smørgrav				break
1005ead817cSDag-Erling Smørgrav			fi
1015ead817cSDag-Erling Smørgrav			sleep 1
1025ead817cSDag-Erling Smørgrav			count=$((count+1))
1035ead817cSDag-Erling Smørgrav		done
1045ead817cSDag-Erling Smørgrav
1055ead817cSDag-Erling Smørgrav		# Restore default SIGINT handler
1065ead817cSDag-Erling Smørgrav		trap - SIGINT
1075ead817cSDag-Erling Smørgrav
1085ead817cSDag-Erling Smørgrav		if ! ${got_dad}; then
1095ead817cSDag-Erling Smørgrav			echo ', timed out.'
1105ead817cSDag-Erling Smørgrav			any_error=true
1110696600cSBjoern A. Zeeb		fi
1120696600cSBjoern A. Zeeb	fi
1130696600cSBjoern A. Zeeb
1140696600cSBjoern A. Zeeb	if [ -n "${netwait_ip}" ]; then
1155ead817cSDag-Erling Smørgrav		got_ip=false
1165ead817cSDag-Erling Smørgrav		# Handle SIGINT (Ctrl-C); force abort of for loop
1170696600cSBjoern A. Zeeb		trap break SIGINT
1180696600cSBjoern A. Zeeb
1190696600cSBjoern A. Zeeb		for ip in ${netwait_ip}; do
1200696600cSBjoern A. Zeeb			echo -n "Waiting for ${ip} to respond to ICMP ping"
1210696600cSBjoern A. Zeeb
1220696600cSBjoern A. Zeeb			count=1
1230696600cSBjoern A. Zeeb			while [ ${count} -le ${netwait_timeout} ]; do
1240696600cSBjoern A. Zeeb				/sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1
1250696600cSBjoern A. Zeeb				rc=$?
1260696600cSBjoern A. Zeeb
1270696600cSBjoern A. Zeeb				if [ $rc -eq 0 ]; then
1280696600cSBjoern A. Zeeb					echo ', got response.'
1295ead817cSDag-Erling Smørgrav					got_ip=false
1305ead817cSDag-Erling Smørgrav					break 2
1310696600cSBjoern A. Zeeb				fi
1320696600cSBjoern A. Zeeb				count=$((count+1))
1330696600cSBjoern A. Zeeb			done
1340696600cSBjoern A. Zeeb			echo ', failed: No response from host.'
1350696600cSBjoern A. Zeeb		done
1360696600cSBjoern A. Zeeb
1370696600cSBjoern A. Zeeb		# Restore default SIGINT handler
1380696600cSBjoern A. Zeeb		trap - SIGINT
1390696600cSBjoern A. Zeeb
1405ead817cSDag-Erling Smørgrav		if ! ${got_ip}; then
1415ead817cSDag-Erling Smørgrav			any_error=true
1425ead817cSDag-Erling Smørgrav		fi
1430696600cSBjoern A. Zeeb	fi
1440696600cSBjoern A. Zeeb
1455ead817cSDag-Erling Smørgrav	if ${any_error}; then
1465ead817cSDag-Erling Smørgrav		warn "Continuing with startup, but be aware you may not have "
1475ead817cSDag-Erling Smørgrav		warn "a fully functional networking layer at this point."
1485ead817cSDag-Erling Smørgrav	fi
1490696600cSBjoern A. Zeeb}
1500696600cSBjoern A. Zeeb
1510696600cSBjoern A. Zeebload_rc_config $name
152f99f0ee1SAlexander Leidinger
153f99f0ee1SAlexander Leidinger# doesn't make sense to run in a svcj: config setting
154f99f0ee1SAlexander Leidingernetwait_svcj="NO"
155f99f0ee1SAlexander Leidinger
1560696600cSBjoern A. Zeebrun_rc_command "$1"
157