#! /bin/sh
# user interface to automatic keying and Pluto in general
# Copyright (C) 1998, 1999, 2000  Henry Spencer.
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
# 
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.

me='ipsec auto'
usage="Usage:
	$me [--showonly] [--asynchronous] --up connectionname
	$me [--showonly] --{add|delete|replace|down} connectionname
	$me [--showonly] --{route|unroute} connectionname
	$me [--showonly] --{ready|status|rereadsecrets|rereadgroups}
        $me [--showonly] --{rereadcacerts|rereadaacerts}
        $me [--showonly] --{rereadacerts|rereadcrls|rereadall}
        $me [--showonly] [--utc] --{listpubkeys|listcerts}
        $me [--showonly] [--utc] --checkpubkeys
        $me [--showonly] [--utc] --{listcacerts|listaacerts}
        $me [--showonly] [--utc] --{listacerts|listgroups}
        $me [--showonly] [--utc] --{listcrls|listall}

	other options: [--config ipsecconfigfile] [--verbose] [--show]"

showonly=
config=
shopts=
async=
logfilter='$1 != "002"'
op=
argc=
utc=

for dummy
do
	case "$1" in
	--help)		echo "$usage" ; exit 0	;;
	--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
	--show)		shopts=-x		;;
	--showonly)	showonly=yes		;;
	--utc)		utc="$1"		;;
	--config)	config="--config $2" ; shift	;;
	--asynchronous)	async="--asynchronous"	;;
	--verbose)	logfilter='1'		;;
	--up|--down|--add|--delete|--replace|--route|--unroute)
			if test " $op" != " "
			then
				echo "$usage" >&2
				exit 2
			fi
			op="$1"
			argc=1
			;;
	--ready|--status|--rereadsecrets|--rereadgroups|\
        --rereadcacerts|--rereadaacerts|\
        --rereadacerts|--rereadcrls|--rereadall|\
        --listpubkeys|--listcerts|\
        --checkpubkeys|\
        --listcacerts|--listaacerts|\
        --listacerts|--listgroups|\
        --listcrls|--listall)
			if test " $op" != " "
			then
				echo "$usage" >&2
				exit 2
			fi
			op="$1"
			argc=0
			;;
	--)		shift ; break		;;
	-*)		echo "$me: unknown option \`$1'" >&2 ; exit 2 ;;
	*)		break			;;
	esac
	shift
done

names=
case "$op$#:$1:$2" in
2:*:up|2:*:down|2:*:add|2:*:delete|2:*:replace|2:*:route|2:*:unroute)
		echo "$me: warning: obsolete command syntax used" >&2
		names="$1"
		op="--$2"
		;;
1:ready:|1:status:|1:rereadsecrets:|\
1:rereadcacerts:|1:rereadaacerts:|\
1:rereadacerts:|1:rereadcrls:|1:rereadall:\
1:listpubkeys:|1:listcerts:|\
1:listcacerts:|1:listaacerts:|\
1:listacerts:|1:listgroups:|\
1:listcrls:|1:listall:)
		echo "$me: warning: obsolete command syntax used" >&2
		op="--$1"
		;;
--*)		if test " $argc" -ne $#
		then
			echo "$usage" >&2
			exit 2
		fi
		names="$*"
		;;
*)		echo "$usage" >&2 ; exit 2	;;
esac

# before we go any further, duplicate stdin/stdout to fds 3/4
exec 3<&0
exec 4>&1

runit() {
	if test "$showonly"
	then
		cat
	else
		(
		    echo '('
		    echo 'exec <&3'     # regain stdin
		    cat
		    echo ');'
		) | sh $shopts |
			awk "/^= / { exit \$2 } $logfilter { print }"
	fi
}

case "$op" in
--ready)          echo "ipsec whack --listen"                | runit ; exit ;;
--rereadsecrets)   echo "ipsec whack --rereadsecrets"        | runit ; exit ;;
--rereadgroups)           echo "ipsec whack --listen"                | runit ; exit ;;
--rereadcacerts)   echo "ipsec whack --rereadcacerts"         | runit ; exit ;;
--rereadaacerts)   echo "ipsec whack --rereadaacerts"         | runit ; exit ;;
--rereadacerts)    echo "ipsec whack --rereadacerts"          | runit ; exit ;;
--rereadcrls)     echo "ipsec whack --rereadcrls"            | runit ; exit ;;
--rereadall)      echo "ipsec whack --rereadall"             | runit ; exit ;;
--listpubkeys)    echo "ipsec whack $utc --listpubkeys"      | runit ; exit ;;
--checkpubkeys)   echo "ipsec whack $utc --checkpubkeys"     | runit ; exit ;;
--listcerts)      echo "ipsec whack $utc --listcerts"        | runit ; exit ;;
--listcacerts)    echo "ipsec whack $utc --listcacerts"      | runit ; exit ;;
--listaacerts)    echo "ipsec whack $utc --listaacerts"      | runit ; exit ;;
--listacerts)     echo "ipsec whack $utc --listacerts"       | runit ; exit ;;
--listgroups)     echo "ipsec whack $utc --listgroups"       | runit ; exit ;; 
--listcrls)       echo "ipsec whack $utc --listcrls"         | runit ; exit ;; 
--listall)        echo "ipsec whack $utc --listall"          | runit ; exit ;;
--up)  echo "ipsec whack $async --name $names --initiate"    | runit ; exit ;;
--down)        echo "ipsec whack --name $names --terminate"          | runit ; exit ;;
--delete)         echo "ipsec whack --name $names --delete"  | runit ; exit ;; 
--route)          echo "ipsec whack --name $names --route"   | runit ; exit ;;
--unroute)        echo "ipsec whack --name $names --unroute" | runit ; exit ;; 
--status)         echo "ipsec whack --status"                | runit ; exit ;; 
esac

	getphysdev=
	getifaddr=
	addr=
	phys=
	next=
	multiaddr=
	multidefault=

	getphysdev() {
	    local phys next addr
	    phys=
	    next=
	    addr=
	    while test $# -gt 0
	      do
	      case $1 in
		  dev)
		      phys=$2
		      shift; shift;
		      ;;
		  via)
		      next=$2
		      shift; shift;
		      ;;
		  src)
		      addr=$2
		      shift; shift
		      ;;
		  *)
		      shift
		      ;;
	      esac
	    done
	    echo "phys=$phys"
	    echo "next=$next"
	    echo "addr=$addr"
	}

	getifaddr() {
	    local addr peer
	    addr=
	    peer=
	    while test $# -gt 0
	      do
	      case $1 in
		  inet)
		      addr=$2
		      shift; shift
		      ;;
		  peer)
		      peer=$2
		      shift; shift
		      ;;
		  *)
		      shift
		      ;;
	      esac
	    done
	    if test -n "$peer"
	    then
		echo "next=${peer%/*}"
	    fi
	    echo "addr=${addr%/*}"
	}

	iproutedefault=`ip route list 0.0.0.0/0`
	if test -n "$iproutedefault"
	then
	  if test `echo "$iproutedefault" | wc -l` -gt 1
	  then
	    multidefault=1
	    iproutedefault=`echo "$iproutedefault" | head -1`
	  fi
	  eval `getphysdev $iproutedefault`
	  if test -z "$next" -o -z "$addr" -a -n "$phys"
	  then
	    ipaddrlist=`ip -o -f inet addr list dev $phys` 
	    if test `echo "$ipaddrlist" | wc -l` -gt 1
	    then
	      multiaddr=1
	      ipaddrlist=`echo "$ipaddrlist" | head -1`
	    fi
	    eval `getifaddr $ipaddrlist`
	  fi
	  if test -n "$multidefault"
	  then
	    echo "multiple default routes, using $next on $phys"
	  fi
	  if test -n "$multiaddr"
	  then
	    echo "multiple ip addresses, using  $addr on $phys"
	  fi
	else
	  echo "no default routes detected"
	fi
	defaultroutephys=$phys
	defaultroutenexthop=$next

echo "ipsec addconn $config $options $names"             | runit
exit 
 

