ipsec-tools: racoon uci integration
authoraTanW <villy@sft.ru>
Tue, 10 Mar 2015 13:24:22 +0000 (16:24 +0300)
committeraTanW <villy@sft.ru>
Thu, 26 Mar 2015 05:25:15 +0000 (08:25 +0300)
Signed-Off-By: Vitaly Protsko <villy@sft.ru>
---
 b/net/ipsec-tools/Makefile            |   16 -
 b/net/ipsec-tools/files/functions.sh  |  137 +++++++++
 b/net/ipsec-tools/files/p1client-down |   41 ++
 b/net/ipsec-tools/files/p1client-up   |   41 ++
 b/net/ipsec-tools/files/racoon        |  109 +++++++
 b/net/ipsec-tools/files/racoon.init   |  478 +++++++++++++++++++++++++++++++++-
 b/net/ipsec-tools/files/vpnctl        |   19 +
 net/ipsec-tools/files/racoon.conf     |   36 --
 8 files changed, 824 insertions(+), 53 deletions(-)

net/ipsec-tools/Makefile
net/ipsec-tools/files/functions.sh [new file with mode: 0644]
net/ipsec-tools/files/p1client-down [new file with mode: 0644]
net/ipsec-tools/files/p1client-up [new file with mode: 0644]
net/ipsec-tools/files/racoon [new file with mode: 0644]
net/ipsec-tools/files/racoon.conf [deleted file]
net/ipsec-tools/files/racoon.init
net/ipsec-tools/files/vpnctl [new file with mode: 0644]

index ae9c83c00d75abea47ef2e1995e0df9aa3c2e663..405a95ee2cfd8e8e49654b8e9002942031f2794e 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Copyright (C) 2006-2011 OpenWrt.org
-#               2014 Noah Meyerhans <frodo@morgul.net>
+#               2014-2015 Noah Meyerhans <frodo@morgul.net>
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=ipsec-tools
 PKG_VERSION:=0.8.2
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 PKG_MAINTAINER := "Noah Meyerhans <frodo@morgul.net>"
 PKG_LICENSE := BSD-3-Clause
 
@@ -76,12 +76,15 @@ endif
 endef
 
 define Package/ipsec-tools/install
-       $(INSTALL_DIR) $(1)/etc
-       $(INSTALL_CONF) ./files/racoon.conf $(1)/etc/racoon.conf
        $(INSTALL_DIR) $(1)/etc/racoon
-       $(INSTALL_CONF) $(PKG_BUILD_DIR)/src/racoon/samples/psk.txt $(1)/etc/racoon/
+       $(INSTALL_CONF) ./files/functions.sh $(1)/etc/racoon/
+       $(INSTALL_BIN) ./files/p1client-up $(1)/etc/racoon/
+       $(INSTALL_BIN) ./files/p1client-down $(1)/etc/racoon/
+       $(INSTALL_BIN) ./files/vpnctl $(1)/etc/racoon/
        $(INSTALL_DIR) $(1)/etc/init.d
        $(INSTALL_BIN) ./files/racoon.init $(1)/etc/init.d/racoon
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_CONF) ./files/racoon $(1)/etc/config/
        $(INSTALL_DIR) $(1)/usr/lib
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/libipsec.so.* $(1)/usr/lib/
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/libracoon.so.* $(1)/usr/lib/
@@ -93,8 +96,7 @@ define Package/ipsec-tools/install
 endef
 
 define Package/ipsec-tools/conffiles
-/etc/racoon.conf
-/etc/racoon/psk.txt
+/etc/config/racoon
 endef
 
 $(eval $(call BuildPackage,ipsec-tools))
diff --git a/net/ipsec-tools/files/functions.sh b/net/ipsec-tools/files/functions.sh
new file mode 100644 (file)
index 0000000..e3e739b
--- /dev/null
@@ -0,0 +1,137 @@
+#!/bin/sh
+#
+# Copyright (C) 2015 Vitaly Protsko <villy@sft.ru>
+
+errno=0
+
+get_fieldval() {
+  local __data="$3"
+  local __rest
+
+  test -z "$1" && return
+
+  while true ; do
+    __rest=${__data#* }
+    test "$__rest" = "$__data" && break
+
+    if [ "${__data/ *}" = "$2" ]; then
+      eval "$1=${__rest/ *}"
+      break
+    fi
+
+    __data="$__rest"
+  done
+}
+
+manage_fw() {
+  local cmd=/usr/sbin/iptables
+  local mode
+  local item
+
+  if [ -z "$4" ]; then
+    $log "Bad usage of manage_fw"
+    errno=3; return 3
+  fi
+
+  case "$1" in
+    add|up|1) mode=A ;;
+    del|down|0) mode=D ;;
+    *) return 3 ;;
+  esac
+
+  for item in $4 ; do
+    $cmd -$mode forwarding_$2_rule -s $item -j ACCEPT
+    $cmd -$mode output_$3_rule -d $item -j ACCEPT
+    $cmd -$mode forwarding_$3_rule -d $item -j ACCEPT
+    $cmd -t nat -$mode postrouting_$3_rule -d $item -j ACCEPT
+  done
+}
+
+manage_sa() {
+  local spdcmd
+  local rtcmd
+  local gate
+  local litem
+  local ritem
+
+  if [ -z "$4" ]; then
+    $log "Bad usage of manage_sa"
+    errno=3; return 3
+  fi
+
+  case "$1" in
+    add|up|1) spdcmd=add; rtcmd=add ;;
+    del|down|0) spdcmd=delete; rtcmd=del ;;
+    *) errno=3; return 3 ;;
+  esac
+
+  get_fieldval gate src "$(/usr/sbin/ip route get $4)"
+  if [ -z "$gate" ]; then
+    $log "Can not find outbound IP for $4"
+    errno=3; return 3
+  fi
+
+
+  for litem in $2 ; do
+    for ritem in $3 ; do
+      echo "
+spd$spdcmd $litem $ritem any -P out ipsec esp/tunnel/$gate-$4/require;
+spd$spdcmd $ritem $litem any -P in ipsec esp/tunnel/$4-$gate/require;
+" | /usr/sbin/setkey -c 1>&2
+    done
+  done
+
+  test -n "$5" && gate=$5
+
+  for ritem in $3 ; do
+    (sleep 3; /usr/sbin/ip route $rtcmd $ritem via $gate) &
+  done
+}
+
+
+. /lib/functions/network.sh
+
+get_zoneiflist() {
+  local item
+  local data
+  local addr
+
+  item=0
+  data=$(uci get firewall.@zone[0].name)
+  while [ -n "$data" ]; do
+    test "$data" = "$1" && break
+    let "item=$item+1"
+    data=$(uci get firewall.@zone[$item].name)
+  done
+
+  if [ -z "$data" ]; then
+    errno=1
+    return $errno
+  fi
+  data=$(uci get firewall.@zone[$item].network)
+
+  echo "$data"
+}
+
+get_zoneiplist() {
+  local item
+  local addr
+  local data
+  local result
+
+  data=$(get_zoneiflist $1)
+  test $? -gt 0 -o $errno -gt 0 -o -z "$data" && return $errno
+
+  for item in $data ; do
+    if network_is_up $item ; then
+      network_get_ipaddrs addr $item
+      test $? -eq 0 && result="$result $addr"
+    fi
+  done
+
+  result=$(echo $result)
+  echo "$result"
+}
+
+
+# EOF /etc/racoon/functions.sh
diff --git a/net/ipsec-tools/files/p1client-down b/net/ipsec-tools/files/p1client-down
new file mode 100644 (file)
index 0000000..8c5a195
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+
+log="logger -t p1client-down[$$]"
+
+. /lib/functions.sh
+. /etc/racoon/functions.sh
+
+if [ -z "$SPLIT_INCLUDE_CIDR" ]; then
+  $log "Connection without server-pushed routing is not supported"
+  exit 1
+fi
+
+$log "Shutting down tunnel to server $REMOTE_ADDR"
+$log "Closing tunnel(-s) to $SPLIT_INCLUDE_CIDR through $INTERNAL_ADDR4"
+
+config_load racoon
+config_get confIntZone racoon int_zone lan
+config_get confExtZone racoon ext_zone wan
+
+manage_fw del $confIntZone $confExtZone "$INTERNAL_ADDR4 $SPLIT_INCLUDE_CIDR"
+
+data=$(get_zoneiflist $confIntZone)
+if [ -n "$data" ]; then
+  for item in $data ; do
+    network_get_subnet locnet $item
+    if [ -n "$locnet" ]; then
+      manage_sa del "$locnet" "$SPLIT_INCLUDE_CIDR" $REMOTE_ADDR $INTERNAL_ADDR4
+    else
+      $log "Can not find subnet on interface $item"
+    fi
+  done
+else
+  $log "Can not find subnets in zone $confIntZone"
+fi
+
+get_fieldval data dev "$(/usr/sbin/ip route get $REMOTE_ADDR)"
+ip address del $INTERNAL_ADDR4/32 dev $data
+
+
+# EOF /etc/racoon/p1client-down
diff --git a/net/ipsec-tools/files/p1client-up b/net/ipsec-tools/files/p1client-up
new file mode 100644 (file)
index 0000000..8a9678a
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+
+log="logger -t p1client-up[$$]"
+
+. /lib/functions.sh
+. /etc/racoon/functions.sh
+
+if [ -z "$SPLIT_INCLUDE_CIDR" ]; then
+  $log "Connection without server-pushed routing is not supported"
+  exit 1
+fi
+
+$log "Setting up tunnel to server $REMOTE_ADDR"
+$log "Making tunnel(-s) to $SPLIT_INCLUDE_CIDR through $INTERNAL_ADDR4"
+
+get_fieldval data dev "$(/usr/sbin/ip route get $REMOTE_ADDR)"
+ip address add $INTERNAL_ADDR4/32 dev $data
+
+config_load racoon
+config_get confIntZone racoon int_zone lan
+config_get confExtZone racoon ext_zone wan
+
+data=$(get_zoneiflist $confIntZone)
+if [ -n "$data" ]; then
+  for item in $data ; do
+    network_get_subnet locnet $item
+    if [ -n "$locnet" ]; then
+      manage_sa add "$locnet" "$SPLIT_INCLUDE_CIDR" $REMOTE_ADDR $INTERNAL_ADDR4
+    else
+      $log "Can not find subnet on interface $item"
+    fi
+  done
+else
+  $log "Can not find interfaces in zone $confIntZone"
+fi
+
+manage_fw add $confIntZone $confExtZone "$INTERNAL_ADDR4 $SPLIT_INCLUDE_CIDR"
+
+
+# EOF /etc/racoon/p1client-up
diff --git a/net/ipsec-tools/files/racoon b/net/ipsec-tools/files/racoon
new file mode 100644 (file)
index 0000000..11cd2f2
--- /dev/null
@@ -0,0 +1,109 @@
+#/etc/config/racoon
+#
+# Copyright 2015 Vitaly Protsko <villy@sft.ru>
+
+# * WARNING: this is "not working" example
+# * Defaults are commented out
+# * Resuting config will appear in /var/racoon/
+
+config racoon
+#      option  debug           0
+#      option  ext_zone        'wan'
+#      option  int_zone        'lan'
+#      option  port            500
+#      option  natt_port       4500
+# following 4 or 6, no default
+#      option  ipversion       4
+
+config p1_proposal 'example_prop1'
+#      option  lifetime        28800
+       option  enc_alg         'aes'
+       option  hash_alg        'sha1'
+       option  auth_method     'rsasig'
+       option  dh_group        2
+
+config p1_proposal 'example_anon'
+#      option  lifetime        28800
+       option  enc_alg         'aes'
+       option  hash_alg        'sha1'
+       option  auth_method     'xauth_rsa_server'
+       option  dh_group        2
+
+config p1_proposal 'example_xauth'
+#      option  lifetime        28800
+       option  enc_alg         'aes'
+       option  hash_alg        'sha1'
+       option  auth_method     'xauth_rsa_client'
+       option  dh_group        2
+
+config p2_proposal 'example_prop2'
+       option  pfs_group       2
+       option  enc_alg         'aes'
+       option  auth_alg        'hmac_sha1'
+
+config p2_proposal 'example_in2'
+       option  pfs_group       2
+#      option  lifetime        14400
+       option  enc_alg         'aes'
+       option  auth_alg        'hmac_sha1'
+
+config sainfo 'office'
+       option  p2_proposal     'example_prop2'
+       option  local_net       '192.168.8.0/24'
+       option  remote_net      '192.168.1.0/24'
+
+config sainfo 'welcome'
+       option  p2_proposal     'example_in2'
+       option  local_net       '192.168.8.0/24'
+       option  remote_net      '192.168.10.0/24'
+       option  dns4            '192.168.8.1'
+       option  defdomain       'myhome.local'
+
+config sainfo 'client'
+       p2_proposal             'std_p2'
+
+config tunnel 'Office'
+       option  enabled         1
+# initial_contact
+#      option  init            1
+       option  remote          'vpn.example.tld'
+       option  exchange_mode   'main'
+       option  certificate     'example_cert'
+#      option  peer_id_type    'asn1dn'
+#      option  prop_check      'obey'
+#      option  verify_id       1
+#      option  weak_p1check    1
+#      option  dpd_delay       ''
+       list    p1_proposal     'example_prop1'
+       list    sainfo          'office'
+
+# WARNING:     Only ONE tunnel with remote anonymous
+#              can be configured and it can have only
+#              ONE sainfo. Otherwise resulting racoon
+#              configuration will be unusable
+config tunnel 'Incoming'
+       option  enabled         1
+       option  remote          'anonymous'
+       option  pre_shared_key  'testitnow'
+       option  exchange_mode   'aggressive,main'
+       option  my_id_type      'fqdn'
+       option  my_id           'myserver.homeip.net'
+       list    p1_proposal     'example_anon'
+       list    sainfo          'welcome'
+
+config tunnel 'Client'
+       option  enabled         1
+       option  remote          'vpn.example.tld'
+       option  username        'testuser'
+       option  password        'testW0rD'
+#      option  mode_cfg        1
+       list    p1_proposal     'example_xauth'
+       list    sainfo          'client'
+
+# Insert corresponding data in PEM format as one line
+config 'certificate' 'example_cert'
+       option  'key'   '-----BEGIN PRIVATE KEY----- ~ -----END PRIVATE KEY-----'
+       option  'crt'   '-----BEGIN CERTIFICATE----- ~ -----END CERTIFICATE-----'
+
+config 'certificate' 'example_ca_cert'
+       option  'crt'   '-----BEGIN CERTIFICATE----- ~ -----END CERTIFICATE-----'
diff --git a/net/ipsec-tools/files/racoon.conf b/net/ipsec-tools/files/racoon.conf
deleted file mode 100644 (file)
index 5c05bcd..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# Simple racoon.conf
-# 
-# Refer to http://wiki.openwrt.org/doc/howto/vpn.ipsec.basics.racoon for
-# details about configuring racoon in OpenWRT.
-#
-# Also read the Linux IPSEC Howto up at 
-# http://www.ipsec-howto.org/t1.html 
-#
-# Manual pages for ipsec-tools are not included with OpenWRT. Refer to
-# the following locations to view them online:
-# http://linux.die.net/man/8/racoon
-# http://linux.die.net/man/5/racoon.conf
-# http://linux.die.net/man/8/setkey
-#
-
-log notify;
-path pre_shared_key "/etc/racoon/psk.txt";
-path certificate "/etc/racoon/certs";
-
-#remote 172.31.1.1 {
-#        exchange_mode main,aggressive;
-#        proposal {
-#                encryption_algorithm 3des;
-#                hash_algorithm sha1;
-#                authentication_method pre_shared_key;
-#                dh_group modp1024;
-#        }
-#        generate_policy off;
-#}
-# 
-#sainfo address 192.168.203.10[any] any address 192.168.22.0/24[any] any {
-#        pfs_group modp768;
-#        encryption_algorithm 3des;
-#        authentication_algorithm hmac_md5;
-#        compression_algorithm deflate;
-#}
index 68053c91ee39187533a2806b26d09ebcf37bb2c2..6520d5bdeb9e3772d36a567d00849218a2b18044 100644 (file)
 #!/bin/sh /etc/rc.common
-# Copyright (C) 2009-2011 OpenWrt.org
-# Copyright (C) 2011 Artem Makhutov
-# Copyright (C) 2014 Noah Meyerhans <frodo@morgul.net>
+#
+# Copyright (C) 2015 Vitaly Protsko <villy@sft.ru>
+
+#set -vx
 
 USE_PROCD=1
 
-START=49
+START=60
+STOP=40
+
+let connWait=2/2
+confDir=/var/racoon
+confExtZone=
+confIntZone=
+confPort=
+confNATPort=
+confIPMode=
+
+confPh1ID=0
+
+log="logger -t init.d/racoon[$$] "
+
+. /etc/racoon/functions.sh
+
+setup_load() {
+  config_get confExtZone "$1" ext_zone wan
+  config_get confIntZone "$1" int_zone lan
+  config_get confPort    "$1" port 500
+  config_get confNATPort "$1" natt_port 4500
+  config_get confIPMode  "$1" ipversion ""
+
+  case X$confIPMode in
+    X4|X6) ;;
+    *) unset confIPMode ;;
+  esac
+}
+
+write_header() {
+  echo "
+# autogenerated, don't edit, look at /etc/config/racoon
+#
+path certificate \"$confDir/cert\";
+path script \"/etc/racoon\";
+path pre_shared_key \"$confDir/psk.txt\";
+path pidfile \"$confDir/racoon.pid\";
+padding { maximum_length 20; randomize off; strict_check off; exclusive_tail off; }
+timer { counter 5; interval 20 sec; persend 1; phase1 30 sec; phase2 15 sec; }
+"
+}
+
+setup_conf() {
+  local conf=$confDir/racoon.conf
+  local peerconf=$confDir/peers.txt
+  local pskconf=$confDir/psk.txt
+  local item
+  local data
+
+  data="$(get_zoneiplist $confExtZone)"
+  if [ "X$data" = X ]; then
+    $log "No IP addresses found for zone $confExtZone, exitng"
+    errno=2; return 2
+  fi
+
+  write_header > $conf
+  echo -n > $peerconf
+  echo -n > $pskconf
+  chmod 0600 $conf $peerconf $pskconf
+
+  echo "listen {" >> $conf
+  for item in $data ; do
+    echo "  isakmp $item [$confPort]; isakmp_natt $item [$confNATPort];" >> $conf
+  done
+  echo "}" >> $conf
+
+  config_get_bool item "$1" debug 0
+  data=warning
+  test $item -ne 0 && data=debug
+  echo "log $data;" >> $conf
+
+  setup_fw add
+}
+
+setup_p1() {
+  local conf=$confDir/racoon.conf
+  local data
+
+  echo "  proposal {" >> $conf
+  config_get data "$1" lifetime 28800
+  echo "    lifetime time $data sec;" >> $conf
+
+  config_get data "$1" enc_alg
+  test -n "$data" && echo "    encryption_algorithm $data;" >> $conf
+
+  config_get data "$1" hash_alg
+  test -n "$data" && echo "    hash_algorithm $data;" >> $conf
+
+  config_get data "$1" auth_method
+  test -n "$data" && echo "    authentication_method $data;" >> $conf
+
+  config_get data "$1" dh_group 2
+  echo -e "    dh_group $data;\n  }" >> $conf
+}
+
+setup_fw() {
+  local cmd=/usr/sbin/iptables
+  local mode
+
+  case "$1" in
+    add|up|1) mode=A ;;
+    del|down|0) mode=D ;;
+    *) return 3 ;;
+  esac
+
+  $cmd -$mode input_${confExtZone}_rule -p AH -j ACCEPT
+  $cmd -$mode input_${confExtZone}_rule -p ESP -j ACCEPT
+  $cmd -$mode input_${confExtZone}_rule -p UDP --dport $confPort -j ACCEPT
+  $cmd -$mode input_${confExtZone}_rule -p UDP --dport $confNATPort -j ACCEPT
+}
+
+setup_sa() {
+  local conf=$confDir/racoon.conf
+  local remote="${2/ *}"
+  local client="${2#* }"
+  local locnet
+  local remnet
+  local p2
+  local data
+
+  test "$2" = "$client" && unset client
+
+  if [ -z "$client" ]; then
+    config_get locnet "$1" local_net
+    config_get remnet "$1" remote_net
+    if [ -z "$locnet" ] || [ -z "$remnet" ]; then
+      $log "Remote and local networks for $1 must be configured ($2)"
+      errno=4; return 4
+    fi
+
+    if [ "$remote" = "anonymous" ]; then
+      echo "sainfo anonymous {" >> $conf
+     else
+      echo "sainfo address $locnet any address $remnet any {" >> $conf
+    fi
+  else
+    echo "sainfo anonymous {" >> $conf
+  fi
+
+  config_get p2 "$1" p2_proposal
+  if [ -z "$p2" ]; then
+    $log "Phase2 proposal must be configured in $1 sainfo"
+    errno=5; return 5
+  fi
+
+  echo "  remoteid $confPh1ID;" >> $conf
+
+  config_get data "$p2" pfs_group
+  test -n "$data" && echo "  pfs_group $data;" >> $conf
+  config_get data "$p2" lifetime 14400
+  test -n "$data" && echo "  lifetime time $data sec;" >> $conf
+  config_get data "$p2" enc_alg
+  test -n "$data" && echo "  encryption_algorithm $data;" >> $conf
+  config_get data "$p2" auth_alg
+  test -n "$data" && echo "  authentication_algorithm $data;" >> $conf
+
+  echo -e "  compression_algorithm deflate;\n}" >> $conf
+
+  if [ "$remote" = "anonymous" ]; then
+    echo -e "mode_cfg {\n  auth_source system;\n  conf_source local;" >> $conf
+
+    config_get data "$1" dns4
+    test -n "$data" && echo "  dns4 $data;" >> $conf
+    config_get data "$1" defdomain
+    test -n "$data" && echo "  default_domain \"$data\";" >> $conf
+
+    data=${remnet%/*}
+    let "data=${data##*.}+1"
+    echo "  network4 ${remnet%.*}.$data;" >> $conf
+
+    let "data=255<<(24-${remnet#*/}+8)&255"
+    echo "  netmask4 255.255.255.$data;" >> $conf
+
+    echo -e "  split_network include $locnet;\n}" >> $conf
+
+  elif [ -z "$client" ]; then
+    manage_sa add $locnet $remnet $remote
+    test $? -gt 0 -o $errno -gt 0 && return $errno
+
+    manage_fw add $confIntZone $confExtZone $remnet
+  fi
+}
+
+setup_tunnel() {
+  local conf=$confDir/racoon.conf
+  local peerconf=$confDir/peers.txt
+  local data
+  local remote
+  local xauth
+
+  config_get_bool data "$1" enabled 0
+  test "$data" = "0" && return 0
+
+  config_get remote "$1" remote
+  if [ "$remote" = "anonymous" ]; then
+    echo -e "remote anonymous {\n  generate_policy on;" >> $conf
+  else
+    data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
+    test -n "$data" && remote="$data"
+    echo -e "remote \"$1\" {\n  remote_address $remote;" >> $conf
+    echo "$data" >> $peerconf
+  fi
+
+  config_get data "$1" pre_shared_key ""
+  if [ -n "$data" ]; then
+    if [ "$remote" != "anonymous" ]; then
+      echo "$remote $data" >> $confDir/psk.txt
+    else
+      echo "* $data" >> $confDir/psk.txt
+    fi
+  fi
+
+  let confPh1ID=$confPh1ID+1
+  echo "  ph1id $confPh1ID;" >> $conf
+
+  config_get xauth "$1" username ""
+
+  config_get data "$1" certificate ""
+  if [ -n "$data" ]; then
+    echo -en "  verify_cert on;\n  my_identifier asn1dn;\n  certificate_type x509 " >> $conf
+    echo -en "\"$data.crt\" \"$data.key\";\n  send_cr off;\n  peers_identifier " >> $conf
+  else
+    config_get data "$1" my_id_type ""
+    if [ -n "$data" ]; then
+      echo -n "  my_identifier $data" >> $conf
+      config_get data "$1" my_id ""
+      if [ -n "$data" ]; then
+       echo " \"$data\";" >> $conf
+      elif [ -n "$xauth" ]; then
+       echo " \"$xauth\";" >> $conf
+      else
+       echo ";" >> $conf
+      fi
+    elif [ -n "$xauth" ]; then
+      echo "  my_identifier user_fqdn \"$xauth\";" >> $conf
+    fi
+    echo -n "  peers_identifier " >> $conf
+  fi
+
+  if [ "$remote" = "anonymous" ]; then
+    echo "user_fqdn;" >> $conf
+  else
+    config_get data "$1" peer_id_type "asn1dn"
+    echo -n "$data" >> $conf
+
+    config_get data "$1" peer_id ""
+    test -n "$data" && echo -n " \"$data\"" >> $conf
+
+    echo ";" >> $conf
+  fi
+
+  if [ -n "$xauth" ]; then
+    config_get data "$1" password
+    if [ -z "$data" ]; then
+      $log "Password must be given in $1 tunnel"
+      errno=7; return 7
+    fi
+    echo "$xauth $data" >> $confDir/psk.txt
+
+    echo "  xauth_login \"$xauth\";" >> $conf
+    echo -e "  script \"p1client-up\" phase1_up;\n  script \"p1client-down\" phase1_down;" >> $conf
+  fi
+
+  config_get data "$1" exchange_mode
+  if [ -z "$data" ]; then
+    data=main
+    test -n "$xauth" && data="${data},aggressive"
+  fi
+  echo -e "  exchange_mode $data;\n  nat_traversal on;\n  support_proxy on;" >> $conf
+
+  config_get data "$1" prop_check "obey"
+  test -n "$data" && echo "  proposal_check $data;" >> $conf
+
+  config_get_bool data "$1" weak_p1check 1
+  if [ $data -eq 0 ]; then data=off; else data=on; fi
+  echo "  weak_phase1_check $data;" >> $conf
+
+  config_get_bool data "$1" verify_id 1
+  if [ $data -eq 0 ]; then data=off; else data=on; fi
+  echo "  verify_identifier $data;" >> $conf
+
+  config_get data "$1" dpd_delay ""
+  test -n "$data" && echo "  dpd_delay $data;" >> $conf
+
+  unset data
+  test -n "$xauth" && data="on"
+  config_get data "$1" mode_cfg "$data"
+  test -n "$data" && echo "  mode_cfg $data;" >> $conf
+
+  config_get_bool data "$1" init 0
+  if [ $data -eq 0 ]; then data=off; else data=on; fi
+  echo "  initial_contact $data;" >> $conf
+
+
+  config_list_foreach "$1" p1_proposal setup_p1
+  echo "}" >> $conf
+
+  config_list_foreach "$1" sainfo setup_sa "$remote $xauth"
+}
+
+setup_cert() {
+  local item
+  local data
+
+  for item in key crt ; do
+    config_get data "$1" $item ""
+    test -z "$data" && continue
+
+    echo "$data" |\
+    sed 's/-\+[A-Z ]\+-\+/\n&\n/g' | sed 's/.\{50,50\}/&\n/g' | sed '/^$/d'\
+    > $confDir/cert/$1.$item
+
+    chmod 600 $confDir/cert/$1.$item
+  done
+
+  if [ -s $confDir/cert/$1.crt ]; then
+    data=$(openssl x509 -noout -hash -in $confDir/cert/$1.crt)
+    ln -sf $confDir/cert/$1.crt $confDir/cert/$data.0
+  fi
+}
+
+destroy_sa() {
+  local locnet
+  local remnet
+
+  config_get locnet "$1" local_net
+  config_get remnet "$1" remote_net
+  if [ -z "$locnet" ] || [ -z "$remnet" ]; then
+    $log "Remote and local networks for $1 must be configured"
+    errno=4; return 4
+  fi
+
+  manage_sa del $locnet $remnet $2
+  manage_fw del $confIntZone $confExtZone $remnet
+}
+
+destroy_tunnel() {
+  local data
+
+  config_get_bool data "$1" enabled 0
+  test "$data" = "0" && return 0
+
+  config_get remote "$1" remote
+  data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
+  test -n "$data" && remote="$data"
+
+  config_get data "$1" username ""
+  if [ -z "$data" ]; then
+    config_list_foreach "$1" sainfo destroy_sa $remote
+  fi
+}
+
+destroy_conf() {
+  setup_fw del
+}
+
+check_software() {
+  local item
+
+  for item in /usr/sbin/setkey /usr/bin/openssl /usr/sbin/ip ; do
+    if [ ! -x $item ]; then
+      $log "Needed program $item not found, exiting"
+      errno=9; return 9
+    fi
+  done
+}
+
+cleanup_conf() {
+  config_load racoon
+  config_foreach setup_load racoon
+  config_foreach destroy_conf racoon
+  config_foreach destroy_tunnel tunnel
+
+  /usr/sbin/setkey -P -F
+  /usr/sbin/setkey -F
+}
+
+check_dir() {
+  local item
+
+  for item in $confDir $confDir/cert ; do
+    if [ ! -d $item ]; then
+      mkdir -m 0700 -p $item
+    fi
+  done
+}
+
+wait4wanzone() {
+  local item=$connWait
+  local data
+
+  data="$(get_zoneiplist $confExtZone)"
+  while [ $item -gt 0 ]; do
+    test -n "$data" && break
+    sleep 2
+    let "item=$item-1"
+    data="$(get_zoneiplist $confExtZone)"
+  done
+
+  test -z "$data" && return 10
+}
 
 start_service() {
-    mkdir -m 0700 -p /var/racoon
-    [ -f /etc/ipsec.conf ] && /usr/sbin/setkey -f /etc/ipsec.conf
-    procd_open_instance
-    procd_set_param command /usr/sbin/racoon -F -f /etc/racoon.conf
-    procd_set_param respawn
-    procd_close_instance
+  check_software
+  test $? -gt 0 -o $errno -gt 0 && exit $errno
+
+  check_dir
+
+  config_load racoon
+  config_foreach setup_load racoon
+
+  config_foreach wait4wanzone racoon
+  if [ $? -gt 0 ] || [ $errno -gt 0 ]; then
+    $log "No active interfaces in $confExtZone zone found, exiting"
+    exit $errno
+  fi
+
+  config_foreach setup_conf racoon
+  test $? -gt 0 -o $errno -gt 0 && exit $errno
+
+  config_foreach setup_tunnel tunnel
+  test $? -gt 0 -o $errno -gt 0 && exit $errno
+
+  config_foreach setup_cert certificate
+
+  procd_open_instance
+  procd_set_param command /usr/sbin/racoon
+  test -n "$confIPMode" && procd_append_param command -$confIPMode
+  procd_append_param command -F -f $confDir/racoon.conf
+  procd_set_param file $confDir/racoon.conf
+  procd_close_instance
+
+  if [ -x /etc/racoon/vpnctl ]; then
+    let connWait=$connWait*2+2
+    ( sleep $connWait; /etc/racoon/vpnctl up ) &
+  fi
+}
+
+service_triggers() {
+  local item
+  local data
+
+  procd_add_reload_trigger "racoon" "network"
+
+  config_load racoon
+  config_foreach setup_load racoon
+
+  data=$(get_zoneiflist $confExtZone)
+  if [ $? -gt 0 ] || [ $errno -gt 0 ] || [ -z "$data" ]; then
+    $log "Can not find interfaces for $confExtZone zone"
+  else
+    for item in $data ; do
+      procd_add_reload_interface_trigger $item
+    done
+  fi
+}
+
+stop_service() {
+  cleanup_conf
+  procd_kill racoon 
 }
+
+trap "cleanup_conf" 1 2 3 4 5 6 7 8 9 10
+
+
+# EOF /etc/init.d/racoon
diff --git a/net/ipsec-tools/files/vpnctl b/net/ipsec-tools/files/vpnctl
new file mode 100644 (file)
index 0000000..5fb6667
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+
+case X$1 in
+  Xup|X1|Xstart) connMode=vpn-connect ;;
+  Xdown|X0|Xstop) connMode=vpn-disconnect ;;
+  *)
+    echo "Usage: $0: up|1|start || down|0|stop"
+    exit 1 ;;
+esac
+
+if [ -s /var/racoon/peers.txt ]; then
+  (while read ipa ; do
+    racoonctl $connMode $ipa
+  done) < /var/racoon/peers.txt
+fi
+
+
+# EOF /usr/bin/vpnctl