#!/bin/sh
# Netkey startup script
# Copyright (C) 2007 Ken Bantoft <ken@xelerance.com>
# Copyright (C) 2007 - 2008 Paul Wouters <paul@xelerance.com>
# 
# 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 _startnetkey'		# for messages

modules=/proc/modules
# full rp_filter path is $rpfilter1/interface/$rpfilter2
rpfilter1=/proc/sys/net/ipv4/conf
rpfilter2=rp_filter
# %unchanged or setting (0, 1, or 2)
rpfiltercontrol=0
kamepfkey=/proc/net/pfkey
ipsecpfkey=/proc/net/ipsec/version

info=/dev/null
log=daemon.error
for dummy
do
	case "$1" in
	--log)		log="$2" ; shift	;;
	--info)		info="$2" ; shift	;;
	--debug)	debug="$2" ; shift	;;
	--omtu)		omtu="$2" ; shift	;;
	--fragicmp)	fragicmp="$2" ; shift	;;
	--hidetos)	hidetos="$2" ; shift	;;
	--rpfilter)	rpfiltercontrol="$2" ; shift	;;
	--)	shift ; break	;;
	-*)	echo "$me: unknown option \`$1'" >&2 ; exit 2	;;
	*)	break	;;
	esac
	shift
done


logger -p $log -t ipsec_setup "Using NETKEY(XFRM) stack"


# log only to syslog, not to stdout/stderr
logonly() {
	logger -p $log -t ipsec_setup
}

defaultinterface() {
	phys=`ip ro li 0.0.0.0/0 | awk '{print $5;}'`
	next=`ip ro li 0.0.0.0/0 | awk '{print $3;}'`
	if test `echo " $phys" | wc -l` -gt 1
        then
		phys=`echo "$phys"|head -1`
		next=`echo "$next"|head -1`
                echo "multiple default routes, %defaultroute using: $next on $phys"
        fi
	# determine type
	ipline=`ip addr show dev $phys`
	if test -n "`echo " $ipline " | grep POINTOPOINT`"
	then
		type="pointopoint"
	elif test -n "`echo " $ipline " | grep BROADCAST`"
	then
		type="broadcast"
	else
		type="unknown"
	fi
	defaultip=`echo " $ipline " | grep inet|head -1 | awk '{print $2;}'| sed "s/\/.*$//"`
	# simulate old silly output
	echo "defaultroutephys=$phys" >> $info
	echo "defaultroutevirt=none" >> $info
	echo "defaultrouteaddr=$defaultip" >> $info
	echo "defaultroutenexthop=$next" >> $info
}

# main line

# since klips/mast now calls _startklips, we know we're called to use netkey
# so if we find klips/mast, try to unload it or die
if test -f $ipsecpfkey
then
	echo "Warning: found KLIPS/MAST stack loaded"
	echo -n Trying to unload KLIPS/MAST module:
	rmmod ipsec 2> /dev/null

	if test -f $ipsecpfkey
	then
		echo "FAILURE to unload KLIPS/MAST module. Use protostack=klips or protostack=mast, or recompile kernel without builtin KLIPS/MAST support"
                exit 1
        fi
fi

	if test -f $modules
	then
		# load hardware random related modules - some changed names over time
		modprobe -q hw_random 2>/dev/null
		modprobe -q hwrng 2>/dev/null
		modprobe -q amd-rng 2>/dev/null
		modprobe -q intel-rng 2>/dev/null

		# load all NETKEY modules
		for mod in xfrm6_tunnel xfrm6_mode_tunnel xfrm6_mode_beet xfrm6_mode_ro \
			xfrm6_mode_transport xfrm4_mode_transport xfrm4_mode_tunnel \
			xfrm4_tunnel xfrm4_mode_beet esp4 esp6 ah4 ah6 ipcomp ipcomp6 af_key
		   do
			#echo -n "$mod "
			modprobe -q $mod 2> /dev/null
		   done
		echo

		# xfrm_user is the old name for xfrm4_tunnel - backwards compatibility
		modprobe -q xfrm_user 2> /dev/null

		# padlock must load before aes module
		modprobe -q padlock 2>/dev/null

		# load the most common ciphers/algo's
		# aes-x86_64 has higher priority in via crypto api
		for crypto in aes-x86_64 aes des sha512 sha256 md5 cbc xcbc ecb twofish blowfish serpent ccm
		   do
			#echo -n "$crypto "
			modprobe -q $crypto 2> /dev/null
		   done
		echo
	fi


	if ip xfrm state > /dev/null 2>&1
	then
		ip xfrm state flush
		ip xfrm policy flush
	elif type setkey > /dev/null 2>&1
	then
	 	# Check that the setkey command is available.
         	setkeycmd= 	 
         	PATH=$PATH:/usr/local/sbin 	 
         	for dir in `echo $PATH | tr ':' ' '` 	 
         	do 	 
                	if test -f $dir/setkey -a -x $dir/setkey 	 
                 	then
                         	setkeycmd=$dir/setkey
                         	break                   # NOTE BREAK OUT 
                	fi
         	done
        	$setkeycmd -F
        	$setkeycmd -FP
	else
	
        	echo "WARNING: cannot flush state/policy database -- \`$1'. Install a newer version of iproute/iproute2 or install the ipsec-tools package to obtain the setkey command." |
                	logger -s -p daemon.error -t ipsec_setup
	fi

# figure out interfaces for defaultroute
for i
do
        case "$i" in
        %defaultroute)  defaultinterface        ;;
        *)      echo "interface \`$i' not understood"
                exit 1
                ;;
        esac
done

exit 0
