#! /bin/sh
#
# network: start or stop networking services for either every interface or
# a specified one
#
#  HOW IT WORKS
#  The directory ${NETDIR} contains a file for every interface that we
#  might want to do networking on.  That file is a collection of shell
#  variables that either describe the interface or tell network that
#  the interface is automatically configured.  When we do `network start'
#  or a `network start <device>', these files are read and used to set up
#  the interface:
#
#	CONF=			-- MANUAL, DISABLED, BOOTP, DHCP; this
#				   interface is ignored if it's not set.
#	MANUAL CONFIGURATION PARAMETERS:
#	ADDRESS=		-- the address of the interface (REQD)
#	NETMASK=		-- the netmask for the interface (REQD)
#  	NETWORK=		-- the network for the interface
#				   (can be derived from netmask.)
#	BROADCAST=		-- the broadcast address for the
#				   interface, if not the all-ones
#				   address.
#	GATEWAY=		-- this interface attaches to the
#				   default network gateway.
#	BOOTP CONFIGURATION PARAMETERS:
#	ASKSERVER=		-- the server to ask for bootp info
#				   (if not set, defaults to the
#				    universal broadcast address.)
#	SYSTEM=			-- if set, configure hostname, dns,
#				   and yellowpages (mounts and lpr?)
#
# dhcp can only meaningfully be enabled for one interface, because it
# manipulates dns and yellowpages.  Ditto for bootp with SYSTEM set.
#

IFCONFIG=/sbin/ifconfig
ROUTE=/sbin/route
BOOTP=/usr/sbin/bootpc
DHCP=/sbin/dhclient

CONFIG=/etc/rc.d/sysconfig
NETDIR=/etc/rc.d/net.cf

RESOLV=/etc/resolv.conf
YPCONF=/etc/yp.conf

# new_dns() builds /etc/resolv.conf from the parameters that
# bootp returns.  It drops a magic cookie into /etc/resolv.conf to
# tell the admin tools to BACK OFF and not edit these files.
#
new_dns() {
    DEVICE=$1; shift

    (   echo "# generated by bootp on `date`"
	echo "#"
	echo "magic cookie"
	[ "$SEARCH" ] && echo "search $SEARCH"
	for x in $*; do
	    echo "nameserver $x"
	done
    ) > $RESOLV
} # new_dns


# new_yellowpages() sets up yellow pages from YPSRVR and YPDOMAIN
#
new_yellowpages() {
    /usr/bin/grep -v `^(DOMAINNAME|YPMASTER)=` < $CONFIG > /tmp/$$
    (   /bin/cat /tmp/$$
	echo "DOMAINNAME=$YPDOMAIN" ) > $CONFIG
    rm -f /tmp/$$

    if [ "$YPSRVR" ]; then
	(   echo "#"
	    echo "# generated by bootp on `date`"
	    echo "#"
	    echo "magic cookie"
	    echo "ypserver $YPSRVR" ) > $YPCONF
    fi
    need yellowpages

} # new_yellowpages


# start_if() starts networking on a single interface.
#
start_if() {
    DEVICE=$1

    # first check to see if the device exists; if not, no need to
    # bring up the interface
    #
    $IFCONFIG $DEVICE >/dev/null || return

    # then handle our two types of interface
    #
    if [ "$DEVICE" = "lo" ]; then
	# Loopback is a special case
	$IFCONFIG lo up 127.0.0.1
	$ROUTE add 127.0.0.1
	$ROUTE add -net 127.0.0.0
    elif [ -r ${NETDIR}/$DEVICE ]; then
	unset CONF ADDRESS NETWORK NETMASK GATEWAY BROADCAST SERVER SYSTEM
	. ${NETDIR}/$DEVICE
	if [ "$CONF" ]; then
	    case "$CONF" in
	    BOOTP|bootp)
		echo -n "configuring networking on $DEVICE ... "
		unset IPADDR NETMASK BROADCAST GATEWAYS NETWORK
		eval `$BOOTP --dev $DEVICE --server ${SERVER:-255.255.255.255}`

		if [ "$IPADDR" ]; then
		    echo "$IPADDR"
		    ifconfig $DEVICE up $IPADDR ${NETMASK:+netmask $NETMASK} \
					  ${BROADCAST:+broadcast $BROADCAST}

		    [ "$NETWORK" ] && route add -net $NETWORK
		    route add $IPADDR ${NETWORK:+network $NETWORK}
		    if [ "$GATEWAYS" ]; then
			set - $GATEWAYS; GATEWAY=$1
			route add default gw $GATEWAY
		    fi

		    if [ "$SYSTEM" ]; then
			hostname $HOSTNAME
			new_dns $DEVICE $DNSSRVS $DNS_1 $DNS_2 $DNS_3

			[ "$YPDOMAIN" ] && new_yellowpages $DEVICE $YPSRVR
		    fi
		else
		    echo "failed!"
		fi
		;;
	    DHCP|dhcp)
		echo -n "starting dhcp for $DEVICE: "
		if $DHCP $DEVICE; then
		    hostname --fqdn
		else
		    echo "no answer from dhcp server"
		fi
		;;
	    MANUAL|manual)
		if [ "$ADDRESS" -a "$NETMASK" ]; then
		    $IFCONFIG $DEVICE up $ADDRESS netmask $NETMASK \
				         ${BROADCAST:+broadcast $BROADCAST}
		    $ROUTE add $ADDRESS dev $DEVICE
		    if [ "$NETWORK" ]; then
			$ROUTE add -net $NETWORK netmask $NETMASK dev $DEVICE
		    fi
		    if [ "$GATEWAY" ]; then
			$ROUTE add default gw $GATEWAY dev $DEVICE
		    fi
		    echo "$DEVICE started"
		else
		    echo "$0: improperly configured $1"
		fi
		;;
	    esac
	fi
    else
	# can't find a configuration file for the desired interface
	return 1
    fi
    return 0
} # start_if


# stop_if() brings down networking on a single interface
#
stop_if() {
    DEVICE=$1
    if [ "$DEVICE" = "lo" ]; then
	# Loopback is, as always, a special case
	$ROUTE del 127.0.0.0
	$ROUTE del 127.0.0.1
    elif [ -r ${NETDIR}/$DEVICE ]; then
	unset CONF GATEWAY NETWORK ADDRESS ASKSERVER SYSTEM
	. ${NETDIR}/$1
	if [ "$CONF" ]; then
	    case "$CONF" in
	    BOOTP|bootp)
		if [ "$SYSTEM" ]; then
		    # kill any generated system files
		    #
		    /usr/bin/grep -q '^magic\> *\<cookie\>' $RESOLV && rm -f $RESOLV
		    if /usr/bin/grep -q '^magic\> *\<cookie\>' $YPCONF; then
			rm -f $YPCONF
			/usr/bin/grep -v '^DOMAINNAME=' < $CONFIG > /tmp/$$
			mv /tmp/$$ $CONFIG
		    fi
		fi
		;;
	    DHCP|dhcp)
		PID=`cat /var/run/dhclient.pid 2>/dev/null`
		if [ "$PID" ]; then
		    kill $PID 2>/dev/null
		    sleep 1
		    kill -0 $PID 2>/dev/null || kill -KILL $PID
		fi
		;;
	    MANUAL|manual)
		[ "$GATEWAY" ] && $ROUTE del default
		[ "$NETWORK" ] && $ROUTE del $NETWORK
		[ "$ADDRESS" ] && $ROUTE del $ADDRESS
		;;
	    esac
	fi
    else
	# can't find configuration for the desired interface
	return 1
    fi
    $IFCONFIG $1 down
    echo "$DEVICE stopped"
} # stop_if


#
# the main code
#
case "$1" in
start)
    need filesystems
    shift

    if [ "$1" ]; then
	for x in $*; do
	    start_if $x
	done
    else
	# set up loopback, then each configured network card
	#
	[ -d ${NETDIR} ] && DEV=`cd ${NETDIR}; ls [a-z]*`
	DEV="lo $DEV"
	for x in $DEV; do
	    start_if $x
	done
    fi ;;

stop)
    shift
    if [ "$1" ]; then
	for x in $*; do
	    stop_if $x
	done
    else
	# unset each configured network card, then loopback
	#
	[ -d ${NETDIR} ] && DEV=`cd ${NETDIR};ls [a-z]*`
	DEV="$DEV lo"
	for x in $DEV; do
	    stop_if $x
	done
    fi ;;

*)
    echo "usage: $0 {start|stop} [interface]" 1>&2
    exit 1 ;;
esac
exit 0
