Sophie

Sophie

distrib > Fedora > 13 > i386 > by-pkgid > 9d5dee87fca7a146cf4596c7deaa6427 > files > 16

ipsec-tools-0.7.3-4.fc12.src.rpm

#!/bin/bash

#
# manipulate IPSec SA database on behalf of the racoon daemon
# Gabriel Somlo <somlo at cmu edu>, 08/27/2007
#

#FIXME: read this from, e.g., /etc/sysconfig/racoon
NAT_T="yes"


shopt -s nocasematch
umask 0022

PATH=/bin:/sbin:/usr/bin:/usr/sbin
# we must not touch /tmp
TMPDIR="/var/racoon"

# set up NAT-T
case "${NAT_T}" in
  yes|true|on|enable*|1)
    LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
    REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
    ;;
  *)
    LOCAL="${LOCAL_ADDR}"
    REMOTE="${REMOTE_ADDR}"
    ;;
esac

# determine interface and next-hop for our default route
DFLT_RT=$(ip route list | awk '($1 == "default"){print $3 ";" $5}')
DFLT_IF=${DFLT_RT#*;}
DFLT_GW=${DFLT_RT%;*}


# bring up phase1
phase1_up() {
  # check if VPN address already set up on default interface (dupe script call)
  ip addr list ${DFLT_IF} | grep -q "${INTERNAL_ADDR4}/32" && {
    echo "p1_up_down: phase1_up has already run !!!"
    exit 4
  }

  # save current resolv.conf and create new one based on info from VPN server
  [ -f /etc/resolv.conf.prevpn ] || cp /etc/resolv.conf /etc/resolv.conf.prevpn
  {
    echo "# Generated by racoon on $(date)"
    echo "search ${DEFAULT_DOMAIN}"
    for NS in ${INTERNAL_DNS4_LIST}; do
      echo "nameserver ${NS}"
    done
  } > /etc/resolv.conf

  # add VPN address to default interface
  ip addr add dev ${DFLT_IF} ${INTERNAL_ADDR4}/32
  # set up host route to VPN server
  ip route add ${REMOTE_ADDR} via ${DFLT_GW} dev ${DFLT_IF}

  if [ -n "${SPLIT_INCLUDE_CIDR}" ]; then
    # split tunnel: keep existing default, insert specific tunnel routes
    for N in ${SPLIT_INCLUDE_CIDR}; do
      ip route add ${N} via ${DFLT_GW} dev ${DFLT_IF} src ${INTERNAL_ADDR4}
    done
  else
    # full tunnel: set up any applicable exceptions
    for N in ${SPLIT_LOCAL_CIDR}; do
      ip route add ${N} via ${DFLT_GW} dev ${DFLT_IF}
    done
    # ... then replace default route with vpn tunnel
    ip route del default
    ip route add default via ${DFLT_GW} dev ${DFLT_IF} src ${INTERNAL_ADDR4}
  fi

  # update SA database
  setkey -c << EOT
spdadd ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
       esp/tunnel/${LOCAL}-${REMOTE}/require;
spdadd 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
       esp/tunnel/${REMOTE}-${LOCAL}/require;
EOT
}

# bring down phase1
phase1_down() {
  # restore previous resolv.conf
  [ -f /etc/resolv.conf.prevpn ] && mv /etc/resolv.conf.prevpn /etc/resolv.conf

  if [ -n "${SPLIT_INCLUDE_CIDR}" ]; then
    # split tunnel: remove specific tunnel routes
    for N in ${SPLIT_INCLUDE_CIDR}; do
      ip route del ${N}
    done
  else
    # full tunnel: remove any applicable exceptions
    for N in ${SPLIT_LOCAL_CIDR}; do
      ip route del ${N}
    done
    # ... then restore original default route
    ip route del default
    ip route add default via ${DFLT_GW} dev ${DFLT_IF}
  fi

  # remove host route to VPN server
  ip route del ${REMOTE_ADDR}
  # remove VPN address from default interface
  ip addr del dev ${DFLT_IF} ${INTERNAL_ADDR4}/32

  # clean up SA database
  setkey -c << EOT
spddelete ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
          esp/tunnel/${LOCAL}-${REMOTE}/require;
spddelete 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
          esp/tunnel/${REMOTE}-${LOCAL}/require;
deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
deleteall ${LOCAL_ADDR} ${REMOTE_ADDR} esp; 
# deleteall still broken on Linux, using 'flush esp' as workaround:
flush esp;
EOT
}


# print out parameters we received
echo "p1_up_down: $1 starting..."
echo "p1_up_down: LOCAL_ADDR = ${LOCAL_ADDR}"
echo "p1_up_down: LOCAL_PORT = ${LOCAL_PORT}"
echo "p1_up_down: REMOTE_ADDR = ${REMOTE_ADDR}"
echo "p1_up_down: REMOTE_PORT = ${REMOTE_PORT}"
echo "p1_up_down: DFLT_GW = ${DFLT_GW}"
echo "p1_up_down: DFLT_IF = ${DFLT_IF}"
echo "p1_up_down: INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
echo "p1_up_down: INTERNAL_DNS4 = ${INTERNAL_DNS4}"
echo "p1_up_down: DEFAULT_DOMAIN = ${DEFAULT_DOMAIN}"
echo "p1_up_down: SPLIT_INCLUDE_CIDR = ${SPLIT_INCLUDE_CIDR}"
echo "p1_up_down: SPLIT_LOCAL_CIDR = ${SPLIT_LOCAL_CIDR}"

# check for valid VPN address
echo ${INTERNAL_ADDR4} | grep -q '[0-9]' || {
  echo "p1_up_down: error: invalid INTERNAL_ADDR4."
  exit 1
}

# check for valid default nexthop
echo ${DFLT_GW} | grep -q '[0-9]' || {
  echo "p1_up_down: error: invalid DFLT_GW."
  exit 2
}

# main "program"
case "$1" in
  phase1_up)
    phase1_up
    ;;
  phase1_down)
    phase1_down
    ;;
  *)
    echo "p1_up_down: error: must be called by racoon w. arg=phase1_[up|down]"
    exit 3
    ;;
esac

echo "p1_up_down: $1 completed successfully."
exit 0