#!/bin/sh # KLIPS startup script # Copyright (C) 1998, 1999, 2001, 2002 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 . # # 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. # # RCSID $Id: _startklips,v 1.6.2.1 2002/04/09 21:34:56 mcr Exp $ me='ipsec _startklips' # for messages # KLIPS-related paths sysflags=/proc/sys/net/ipsec modules=/proc/modules # full rp_filter path is $rpfilter1/interface/$rpfilter2 rpfilter1=/proc/sys/net/ipv4/conf rpfilter2=rp_filter ipsecversion=/proc/net/ipsec_version modulesdir=/lib/modules/ipsec moduleplace=/lib/modules/`uname -r`/kernel/net/ipsec modulename=ipsec.o 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 ;; --default) packetdefault="$2" ; shift ;; --) shift ; break ;; -*) echo "$me: unknown option \`$1'" >&2 ; exit 2 ;; *) break ;; esac shift done # some shell functions, to clarify the actual code # set up a system flag based on a variable # sysflag value shortname default flagname sysflag() { case "$1" in '') v="$3" ;; *) v="$1" ;; esac if test ! -f $sysflags/$4 then if test " $v" != " $3" then echo "cannot do $2=$v, $sysflags/$4 does not exist" exit 1 else return # can't set, but it's the default anyway fi fi case "$v" in yes|no) ;; *) echo "unknown (not yes/no) $2 value \`$1'" exit 1 ;; esac case "$v" in yes) echo 1 >$sysflags/$4 ;; no) echo 0 >$sysflags/$4 ;; esac } # set up a Klips interface klipsinterface() { # pull apart the interface spec virt=`expr $1 : '\([^=]*\)=.*'` phys=`expr $1 : '[^=]*=\(.*\)'` case "$virt" in ipsec[0-9]) ;; *) echo "invalid interface \`$virt' in \`$1'" ; exit 1 ;; esac # figure out ifconfig for interface addr= eval `ifconfig $phys | awk '$1 == "inet" && $2 ~ /^addr:/ && $NF ~ /^Mask:/ { gsub(/:/, " ", $0) print "addr=" $3 other = $5 if ($4 == "Bcast") print "type=broadcast" else if ($4 == "P-t-P") print "type=pointopoint" else if (NF == 5) { print "type=" other = "" } else print "type=unknown" print "otheraddr=" other print "mask=" $NF }'` if test " $addr" = " " then echo "unable to determine address of \`$phys'" exit 1 fi if test " $type" = " unknown" then echo "\`$phys' is of an unknown type" exit 1 fi if test " $omtu" != " " then mtu="mtu $omtu" else mtu= fi echo "KLIPS $virt on $phys $addr/$mask $type $otheraddr $mtu" | logonly # attach the interface and bring it up ipsec tncfg --attach --virtual $virt --physical $phys ifconfig $virt inet $addr $type $otheraddr netmask $mask $mtu # if %defaultroute, note the facts if test " $2" != " " then ( echo "defaultroutephys=$phys" echo "defaultroutevirt=$virt" echo "defaultrouteaddr=$addr" if test " $2" != " 0.0.0.0" then echo "defaultroutenexthop=$2" fi ) >>$info else echo '#dr: no default route' >>$info fi # check for rp_filter trouble checkif $phys # thought to be a problem only on phys } # check an interface for problems checkif() { rpf=$rpfilter1/$1/$rpfilter2 if test -f $rpf then r="`cat $rpf`" if test " $r" != " 0" then echo "WARNING: $1 has route filtering turned on, KLIPS may not work" echo " ($rpf = \`$r', should be 0)" fi fi } # interfaces=%defaultroute: put ipsec0 on top of default route's interface defaultinterface() { phys=`netstat -nr | awk '$1 == "0.0.0.0" && $3 == "0.0.0.0" { print $NF }'` if test " $phys" = " " then echo "no default route, %defaultroute cannot cope!!!" exit 1 fi if test `echo " $phys" | wc -l` -gt 1 then echo "multiple default routes, %defaultroute cannot cope!!!" exit 1 fi next=`netstat -nr | awk '$1 == "0.0.0.0" && $3 == "0.0.0.0" { print $2 }'` klipsinterface "ipsec0=$phys" $next } # log only to syslog, not to stdout/stderr logonly() { logger -p $log -t ipsec_setup } # sort out which module is appropriate, changing it if necessary setmodule() { if test ! -d $modulesdir then return # nothing we can do anyway fi wantgoo="`sed -n '/ netif_rx_R/s/.*_R//p' /proc/ksyms`" module=$moduleplace/$modulename if test -f $module then goo="`nm -ug $module | sed -n '/ netif_rx_R/s/.*_//p'`" if test " $wantgoo" = " $goo" then return # looks right fi fi if test -f $modulesdir/$wantgoo then echo "KLIPS module needed changing (to $wantgoo)" | logonly rm -f $module mkdir -p $moduleplace cp -p $modulesdir/$wantgoo $module # "depmod -a" gets done by caller fi } # main line # load module if necessary if test ! -f $ipsecversion then if test -r $modules # kernel does have modules then setmodule unset MODPATH MODULECONF # no user overrides! depmod -a >/dev/null 2>&1 && modprobe ipsec fi if test ! -f $ipsecversion then echo "kernel appears to lack KLIPS" exit 1 fi fi # figure out debugging flags case "$debug" in '') debug=none ;; esac if test -r /proc/net/ipsec_klipsdebug then echo "KLIPS debug \`$debug'" | logonly case "$debug" in none) ipsec klipsdebug --none ;; all) ipsec klipsdebug --all ;; *) ipsec klipsdebug --none for d in $debug do ipsec klipsdebug --set $d done ;; esac else if test " $debug" != " none" then echo "klipsdebug=\`$debug' ignored, KLIPS lacks debug facilities" fi fi # figure out misc. kernel config if test -d $sysflags then sysflag "$fragicmp" "fragicmp" yes icmp echo 1 >$sysflags/inbound_policy_check # no debate sysflag no "no_eroute_pass" no no_eroute_pass # obsolete parm sysflag no "opportunistic" no opportunistic # obsolete parm sysflag "$hidetos" "hidetos" yes tos else echo "WARNING: cannot adjust KLIPS flags, no $sysflags directory!" # carry on fi # clear tables out in case dregs have been left over ipsec eroute --clear ipsec spi --clear # figure out interfaces for i do case "$i" in ipsec*=?*) klipsinterface "$i" ;; %defaultroute) defaultinterface ;; *) echo "interface \`$i' not understood" exit 1 ;; esac done # set up default eroute if necessary case "$packetdefault" in pass|reject) ipsec eroute --label "packetdefault" --replace --eraf inet \ --src 0/0 --dst 0/0 --said "%$packetdefault" ;; drop) ;; # default *) echo "unknown packetdefault value \`$packetdefault'" exit 1 ;; esac exit 0