#!/bin/sh

# ARAnyM - bridging network
# STanda (c) 2004
#
# description: TUN/TAP driver using transparent bridge networking setup
#
# dependencies: tun module, tunctl (uml-utilities),
#               bridge module, brctl (bridge-utils)
#
# processname: arabridge 
# chkconfig: - 62 18


# source function library
# . /etc/rc.d/init.d/functions

# CHANGE THIS TO YOUR 'id'
USER=joy

TAPS=tap0
BRIDGE=br0
NIF=eth0

for tool in ifconfig route tunctl brctl modprobe; do
	eval $tool=
	for dir in /sbin /usr/sbin /bin /usr/bin; do
		if test -x "$dir/$tool"; then
			eval $tool="$dir/$tool"
			break
		fi
	done
	eval test \"\$$tool\" = \"\" && { echo "$tool not found" >&2; exit 1; }
done


LOCK=/var/lock/subsys/arabridge

# make sure grep in ifconfig output works
LC_ALL=C
export LC_ALL

# defaultroute's nif
DR_NIF=$($route -n 2>/dev/null | awk '/^0\.0\.0\.0/ {print $8}')
DEFGW=$($route -n 2>/dev/null | awk '/^0\.0\.0\.0/ {print $2}')

# do we have the default route NIF?
DEF_ROUTE=0
if [ -n "$DR_NIF" -a "$NIF" = "$DR_NIF" -a -n "$DEFGW" ]; then
	DEF_ROUTE=1
	echo "Playing with default route at $DR_NIF with gateway to $DEFGW"
fi

success()
{
	echo "[OK]"
}

failure()
{
	echo "[FAILED]"
}

status()
{
	echo "arabridge is $1"
}

start_tap()
{
    TAP="$1"
    $ifconfig $TAP 1>/dev/null 2>/dev/null
    if [ $? -ne 0 ]; then
        echo "Creating device $TAP..."
        $tunctl -t $TAP -u $USER
    fi
}

case "$1" in
  start)
	echo -n "Starting TUN/TAP bridging: "

	# save the NIF name
	echo $NIF >$LOCK

	IP=$($ifconfig $NIF | sed -n 's/^.*\(inet \|inet addr:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')
	BCAST=$($ifconfig $NIF | sed -n 's/^.*\(broadcast \|Bcast:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')
	NETMASK=$($ifconfig $NIF | sed -n 's/^.*\(netmask \|Mask:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')
	echo "NIF=$NIF IP=$IP, BCAST=$BCAST, NETMASK=$NETMASK, DEFGW=$DEFGW"

	$modprobe tun
	$modprobe bridge

	# echo "Changing owner of /dev/net/tun..."
	# [ -c /dev/net/tun ] && chown $USER /dev/net/tun

	echo "Setting up bridge $BRIDGE..."
	$brctl addbr $BRIDGE
	$brctl stp $BRIDGE off
	$brctl setfd $BRIDGE 1
	$brctl sethello $BRIDGE 1

	# add NIF to the bridge
	$ifconfig $NIF 0.0.0.0
	$brctl addif $BRIDGE $NIF
        if [ $? -ne 0 ]; then
        	echo -n "... ERROR: wrong NIF type";
		failure; echo

		$brctl delbr $BRIDGE
		rm -f $LOCK
		$ifconfig $NIF $IP
		exit 1 
        fi
	echo

	# add all the tap devices
	for tap in $TAPS; do
		start_tap $tap
		$brctl addif $BRIDGE $tap
		$ifconfig $tap 0.0.0.0 promisc up
	done

	# setup the bridge parameters
	$ifconfig $BRIDGE $IP netmask $NETMASK broadcast $BCAST

	# ifconfig needs to be called twice here after some delay
	# I don't really know what is going on :(
	# if not slept enough then the IP, NETMASK and BCAST setting
	# are cleared 8-| 
	sleep 1

	$ifconfig $NIF 0.0.0.0 promisc up

	# bring the bridge up
	$ifconfig $BRIDGE $IP netmask $NETMASK broadcast $BCAST up
	if [ $DEF_ROUTE -eq 0 ]; then
	   echo "adding normal route"
	   $route add default dev $BRIDGE
	else
	   echo "adding gateway route"
	   $route add default dev $BRIDGE gw $DEFGW
	fi

	echo
        success
	echo
	;;
  stop)
	echo -n "Shutting down arabridge: "

	NIF=$(cat $LOCK 2>/dev/null)
	if [ -z "$NIF" ]; then
        	echo -n "... already stopped";
		success;
		echo;
		exit 0
        fi
	echo

	IP=$($ifconfig $BRIDGE 2>/dev/null| sed -n 's/^.*\(inet \|inet addr:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')
	BCAST=$($ifconfig $BRIDGE 2>/dev/null| sed -n 's/^.*\(broadcast \|Bcast:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')
	NETMASK=$($ifconfig $BRIDGE 2>/dev/null| sed -n 's/^.*\(netmask \|Mask:\)[^0-9]*\([0-9][.0-9]*\).*$/\2/p')

	# if not slept long enough then the IP, NETMASK and BCAST setting
	# are not fetched properly 8-| 
	sleep 1

	echo "NIF=$NIF IP=$IP, BCAST=$BCAST, NETMASK=$NETMASK, DEFGW=$DEFGW"

	# bring the previous network nif back
	$ifconfig $NIF $IP netmask $NETMASK broadcast $BCAST up
	if [ $DEF_ROUTE -eq 0 ]; then
	   $route add default dev $NIF
	else
	   $route add default dev $NIF gw $DEFGW
	fi


	# get the bridge down
	$ifconfig $BRIDGE down

	for tap in $TAPS; do
		$brctl delif $BRIDGE $tap
		$ifconfig $tap down
		echo
		$tunctl -d $tap
	done
	$brctl delbr $BRIDGE
	rm -f $LOCK
	echo
	;;
  restart)
        $0 stop
        $0 start
        ;;
  status)
	if $brctl show $BRIDGE 2>/dev/null; then
		NIF=$(cat $LOCK 2>/dev/null)
		if [ -z "$NIF" ]; then
		        status up
		else
		        status "up on $NIF"
		fi
	else
	        status down
	fi
        ;;
  *)
	echo "Usage: arabridge {start|stop|restart|status}"
	exit 1
esac

exit 0
