Re: The rc.d mess strikes back

From: David Horn <dhorn2000_at_gmail.com>
Date: Wed, 18 Mar 2009 03:52:10 -0400
On Sun, Mar 8, 2009 at 5:27 PM, Doug Barton <dougb_at_freebsd.org> wrote:
> Garrett Wollman wrote:
>> I've generally solved this by hacking a little script into the order
>> just after named to hold back the boot until named is able to resolve
>> an external hostname.
>
> I've been following this thread (and thinking about your previous
> posts on this topic Garrett) and I'm starting to think that having
> this as an option in the base is the Right AnswerTM. Off hand I'd say
> that we would need options for what hostname to ping, and whether to
> use the local name server or just what's in resolv.conf, but that is
> trivial stuff. Can I trouble you to post your script?

In case anyone is interested, here is my version of the "wait until
the network works" rc.d script:

#!/bin/sh
#
# Copyright (c) 2009 The FreeBSD Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE PROJECT ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#

# PROVIDE: network_is_working
# REQUIRE: NETWORKING
# BEFORE: DAEMON
# KEYWORD: nojail

. /etc/rc.subr

name="network_is_working"
rcvar=`set_rcvar network_is_working`
start_cmd="isworking_start"

# rc.conf variables:
#network_is_working_enable="YES"
#network_is_working_timeout="90"
#network_is_working_test="dns"
#network_is_working_host="www.freebsd.org"

# DNS test is the most basic, and can use ipv4 or ipv6 for transport, but is
# rarely blocked by firewalls, so is the default for this script. ipv4/ipv6
# selection is based upon the user /etc/resolv.conf, so not in control of
# this script.  Also the slowest test, and does not respond well to ^C
# Of course dns does not stress a central server, which is a plus.
dns_test()
{
	up="`host -W 1 -t A $host >/dev/null && echo -n "true"`"
}

# PING test is setup to be ipv4 only in this script, but also checks dns of
# course.  icmp can be blocked by firewalls.
ping_test()
{
	up="`ping -c1 -W 1 $host >/dev/null 2>&1 && echo -n "true"`"
}

# TCP test is the most robust, as it checks the default route, dns, and can
# automatically function with either ipv4 or ipv6, but of course the user must
# have a clear outbound connection to the net on port 80.  While netcat (nc)
# can support proxies, no effort has been made to auto-detect, or use/pass
# proxy in this script.
tcp_test()
{
	up="`echo "^D" | nc -w 1 $host 80 >/dev/null 2>&1 && echo -n "true"`"
}


isworking_start()
{
up="false"

num_nameservers="`grep -c "nameserver" /etc/resolv.conf`"
if [ $num_nameservers -eq 0 ]; then
	echo ""
	warn "No nameservers defined in /etc/resolv.conf"
	exit 1
fi
if [ -z "`ifconfig -lu | tr " " "\n" | grep -v 'lo0'`" ]; then
	echo ""
	warn "No interfaces properly configured and up."
	exit 1
fi

if [ -z $network_is_working_timeout ]; then
	network_is_working_timeout="90"
fi

if [ -z $network_is_working_test ]; then
	network_is_working_test="dns"
fi
# Use a dns name that has ipv4 host (A) record and ipv6 host (AAAA) record
# Use a host that allows both ipv4 and ipv6 ping
# Use a host that listens on tcp port 80 on both ipv4 and ipv6
if [ -z "$network_is_working_host" ]; then
	network_is_working_host="www.freebsd.org"
fi
host="$network_is_working_host"


case $network_is_working_test in
	[Pp][Ii][Nn][Gg])
		func=ping_test
		;;
	[Dd][Nn][Ss])
		func=dns_test
		# host command takes longer, so adjust timeout
		# (~ 2 sec per query per nameserver)
		network_is_working_timeout=`expr "$network_is_working_timeout" / 2`
		network_is_working_timeout=`expr "$network_is_working_timeout" /
"$num_nameservers"`
		;;
	[Tt][Cc][Pp])
		func=tcp_test
		;;
esac

debug "Now testing using: $func"
$func
if [ "${up}" != "true" ]; then
	echo -n "Hit Ctrl+C to Abort waiting for network to come alive.."
fi
while [ "${up}" != "true" ]; do
	debug "waiting for $func to return true"
 	$func	
	sleep 1 && echo -n "."
	
	network_is_working_timeout=`expr $network_is_working_timeout - 1`
	if [ "$network_is_working_timeout" -le 0 ]; then
		echo ""
		warn "Timeout while waiting for network to respond."
		exit 1
		break
	fi
done
exit 0
}

load_rc_config $name
run_rc_command "$1"


Feel free to use/abuse/alter/trash/ignore as needed.

--Thanks!

--Dave
Received on Wed Mar 18 2009 - 06:52:11 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:44 UTC