#! /bin/sh
#
# customized updown script
#

# logging of VPN connections
#
# tag put in front of each log entry:
TAG=vpn
#
# syslog facility and priority used:
FAC_PRIO=local0.notice
#
# to create a special vpn logging file, put the following line into
# the syslog configuration file /etc/syslog.conf:
#
# local0.notice                   -/var/log/vpn
#
# check interface version
case "$PLUTO_VERSION" in
1.[0])	# Older Pluto?!?  Play it safe, script may be using new features.
	echo "$0: obsolete interface version \`$PLUTO_VERSION'," >&2
	echo "$0: 	called by obsolete Pluto?" >&2
	exit 2
	;;
1.*)	;;
*)	echo "$0: unknown interface version \`$PLUTO_VERSION'" >&2
	exit 2
	;;
esac

# check parameter(s)
case "$1:$*" in
':')			# no parameters
	;;
ipfwadm:ipfwadm)	# due to (left/right)firewall; for default script only
	;;
custom:*)		# custom parameters (see above CAUTION comment)
	;;
*)	echo "$0: unknown parameters \`$*'" >&2
	exit 2
	;;
esac

# utility functions for route manipulation
# Meddling with this stuff should not be necessary and requires great care.
uproute() {
	doroute add
}
downroute() {
	doroute del
}
doroute() {
	parms="-net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK"
	parms2="dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP"
	case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
	"0.0.0.0/0.0.0.0")
		# horrible kludge for obscure routing bug with opportunistic
		it="route $1 -net 0.0.0.0 netmask 128.0.0.0 $parms2 &&"
		it="$it route $1 -net 128.0.0.0 netmask 128.0.0.0 $parms2"
		route $1 -net 0.0.0.0 netmask 128.0.0.0 $parms2 &&
			route $1 -net 128.0.0.0 netmask 128.0.0.0 $parms2
		;;
	*)	it="route $1 $parms $parms2"
		route $1 $parms $parms2
		;;
	esac
	st=$?
	if test $st -ne 0
	then
		# route has already given its own cryptic message
		echo "$0: \`$it' failed" >&2
		if test " $1 $st" = " add 7"
		then
			# another totally undocumented interface -- 7 and
			# "SIOCADDRT: Network is unreachable" means that
			# the gateway isn't reachable.
			echo "$0: (incorrect or missing nexthop setting??)" >&2
		fi
	fi
	return $st
}

# are there port numbers?
if [ "$PLUTO_MY_PORT" != 0 ]
then
	S_MY_PORT="--sport $PLUTO_MY_PORT"
	D_MY_PORT="--dport $PLUTO_MY_PORT"
fi
if [ "$PLUTO_PEER_PORT" != 0 ]
then
	S_PEER_PORT="--sport $PLUTO_PEER_PORT"
	D_PEER_PORT="--dport $PLUTO_PEER_PORT"
fi

# the big choice
case "$PLUTO_VERB:$1" in
prepare-host:*|prepare-client:*)
	# delete possibly-existing route (preliminary to adding a route)
	case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
	"0.0.0.0/0.0.0.0")
		# horrible kludge for obscure routing bug with opportunistic
		parms1="-net 0.0.0.0 netmask 128.0.0.0"
		parms2="-net 128.0.0.0 netmask 128.0.0.0"
		it="route del $parms1 2>&1 ; route del $parms2 2>&1"
		oops="`route del $parms1 2>&1 ; route del $parms2 2>&1`"
		;;
	*)
		parms="-net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK"
		it="route del $parms 2>&1"
		oops="`route del $parms 2>&1`"
		;;
	esac
	status="$?"
	if test " $oops" = " " -a " $status" != " 0"
	then
		oops="silent error, exit status $status"
	fi
	case "$oops" in
	'SIOCDELRT: No such process'*)
		# This is what route (currently -- not documented!) gives
		# for "could not find such a route".
		oops=
		status=0
		;;
	esac
	if test " $oops" != " " -o " $status" != " 0"
	then
		echo "$0: \`$it' failed ($oops)" >&2
	fi
	exit $status
	;;
route-host:*|route-client:*)
	# connection to me or my client subnet being routed
	uproute
	;;
unroute-host:*|unroute-client:*)
	# connection to me or my client subnet being unrouted
	downroute
	;;
up-host:*)
	# connection to me coming up
	# If you are doing a custom version, firewall commands go here.
	iptables -I INPUT 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
	    -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
	    -d $PLUTO_ME $D_MY_PORT -j ACCEPT
	iptables -I OUTPUT 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
	    -s $PLUTO_ME $S_MY_PORT \
	    -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
	#
	if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
	then
	  logger -t $TAG -p $FAC_PRIO \
	    "+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
	else
	  logger -t $TAG -p $FAC_PRIO \
	    "+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
	fi
	;;
down-host:*)
	# connection to me going down
	# If you are doing a custom version, firewall commands go here.
	iptables -D INPUT -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
	    -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
	    -d $PLUTO_ME $D_MY_PORT -j ACCEPT
	iptables -D OUTPUT -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
	    -s $PLUTO_ME $S_MY_PORT \
	    -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
	#
	if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
	then
	  logger -t $TAG -p $FAC_PRIO -- \
	    "- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
	else
	  logger -t $TAG -p $FAC_PRIO -- \
	  "- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
	fi
	;;
up-client:)
        # connection to my client subnet coming up
	# If you are doing a custom version, firewall commands go here.
	iptables -I FORWARD 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
	    -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
	    -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
	iptables -I FORWARD 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
	    -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
	    -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT -j ACCEPT
	#
	if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
	then
	  logger -t $TAG -p $FAC_PRIO \
	    "+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
	else
	  logger -t $TAG -p $FAC_PRIO \
	    "+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
	fi
	;;
down-client:)
        # connection to my client subnet going down
        # If you are doing a custom version, firewall commands go here.
	iptables -D FORWARD -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
	    -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
	    -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
	iptables -D FORWARD -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
	    -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
	    -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT -j ACCEPT
	#
	if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
	then
	  logger -t $TAG -p $FAC_PRIO -- \
	    "- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
	else
	  logger -t $TAG -p $FAC_PRIO -- \
	    "- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
	fi
	;;
up-client:ipfwadm)
	# connection to client subnet, with (left/right)firewall=yes, coming up
	# This is used only by the default updown script, not by your custom
	# ones, so do not mess with it; see CAUTION comment up at top.
	ipfwadm -F -i accept -b -S $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
		-D $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
	;;
down-client:ipfwadm)
	# connection to client subnet, with (left/right)firewall=yes, going down
	# This is used only by the default updown script, not by your custom
	# ones, so do not mess with it; see CAUTION comment up at top.
	ipfwadm -F -d accept -b -S $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
		-D $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
	;;
*)	echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2
	exit 1
	;;
esac
