Merge remote-tracking branch 'origin/unstable' into testing
authorMathieu <mbaudier@argeo.org>
Thu, 9 Mar 2023 08:37:10 +0000 (09:37 +0100)
committerMathieu <mbaudier@argeo.org>
Thu, 9 Mar 2023 08:37:10 +0000 (09:37 +0100)
17 files changed:
README [new file with mode: 0644]
argeo-freed.spec [new file with mode: 0644]
debian/argeo-freed-libreswan.install [new file with mode: 0644]
debian/argeo-freed-roaming-client.install [new file with mode: 0644]
debian/argeo-freed-roaming-host.install [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
etc/ipsec.d/roaming-host-domain.conf.template [new file with mode: 0644]
etc/ipsec.d/roaming-host.conf [new file with mode: 0644]
etc/ipsec.d/roaming.conf [new file with mode: 0644]
usr/lib/systemd/system/freed-ipsec-roaming@.service [new file with mode: 0644]
usr/lib/systemd/system/freed-onresume.service [new file with mode: 0644]
usr/lib/systemd/system/freed-onsuspend.service [new file with mode: 0644]
usr/libexec/ipsec/_updown.host4client6 [new file with mode: 0755]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0e26456
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+Argeo FREEd is a set of operating system-level configurations and utilities whose main purpose is to simplify and clarify the enrolment of a system or a user into a compatible infrastructure.
\ No newline at end of file
diff --git a/argeo-freed.spec b/argeo-freed.spec
new file mode 100644 (file)
index 0000000..87b68e5
--- /dev/null
@@ -0,0 +1,78 @@
+Name:           argeo-freed
+Version:        2.1.0
+Release:        1%{?dist}
+Summary:        Enrollment into a FREEd compatible domain
+
+License:        GPL
+URL:            http://www.argeo.org
+Source0:        %{name}-%{version}.tar.gz
+
+BuildArch:      noarch
+
+# Required for the %{_unitdir} and %{_sysusersdir} macros
+BuildRequires: systemd
+BuildRequires: systemd-rpm-macros
+
+%description
+
+%package libreswan
+Summary:        FREEd extensions to libreswan
+Requires:       libreswan
+
+%description libreswan
+
+%package roaming-client
+Summary:        FREEd roaming client
+Requires:       argeo-freed-libreswan unbound
+
+%description roaming-client
+
+%package roaming-host
+Summary:        FREEd roaming host
+Requires:       argeo-freed-libreswan
+
+%description roaming-host
+
+%prep
+%setup -q
+
+%build
+
+%install
+mkdir -p %{buildroot}%{_sysconfdir}
+cp -a ./etc/ipsec.d %{buildroot}%{_sysconfdir}
+
+mkdir -p %{buildroot}%{_unitdir}
+cp -a ./usr/lib/systemd/system/* %{buildroot}%{_unitdir}
+
+mkdir -p %{buildroot}%{_libexecdir}
+cp -a ./usr/libexec/ipsec %{buildroot}%{_libexecdir}
+
+%files libreswan
+%attr(755, root, root) %{_libexecdir}/ipsec
+
+%files roaming-client
+%{_sysconfdir}/ipsec.d/roaming.conf
+
+%{_unitdir}/freed-ipsec-roaming@.service
+%{_unitdir}/freed-onresume.service
+%{_unitdir}/freed-onsuspend.service
+
+%post roaming-client
+%systemd_post freed-ipsec-roaming@.service
+%systemd_post freed-onresume.service
+%systemd_post freed-onsuspend.service
+
+%preun roaming-client
+%systemd_preun freed-ipsec-roaming@.service
+%systemd_preun freed-onresume.service
+%systemd_preun freed-onsuspend.service
+
+%postun roaming-client
+%systemd_postun freed-ipsec-roaming@.service
+%systemd_postun freed-onresume.service
+%systemd_postun freed-onsuspend.service
+
+%files roaming-host
+%{_sysconfdir}/ipsec.d/roaming-host.conf
+%{_sysconfdir}/ipsec.d/roaming-host-domain.conf.template
diff --git a/debian/argeo-freed-libreswan.install b/debian/argeo-freed-libreswan.install
new file mode 100644 (file)
index 0000000..57586ba
--- /dev/null
@@ -0,0 +1 @@
+./usr/libexec/ipsec/* ./usr/libexec/ipsec
diff --git a/debian/argeo-freed-roaming-client.install b/debian/argeo-freed-roaming-client.install
new file mode 100644 (file)
index 0000000..6f0a7ae
--- /dev/null
@@ -0,0 +1,4 @@
+./etc/ipsec.d/roaming.conf ./etc/ipsec.d
+./usr/lib/systemd/system/freed-ipsec-roaming@.service ./usr/lib/systemd/system
+./usr/lib/systemd/system/freed-onresume.service ./usr/lib/systemd/system
+./usr/lib/systemd/system/freed-onsuspend.service ./usr/lib/systemd/system
diff --git a/debian/argeo-freed-roaming-host.install b/debian/argeo-freed-roaming-host.install
new file mode 100644 (file)
index 0000000..acfec8d
--- /dev/null
@@ -0,0 +1,2 @@
+./etc/ipsec.d/roaming-host.conf ./etc/ipsec.d
+./etc/ipsec.d/roaming-host-domain.conf.template ./etc/ipsec.d
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..c06a49e
--- /dev/null
@@ -0,0 +1,5 @@
+argeo-freed (2.1.0) unstable; urgency=medium
+
+  * Initial release
+
+ -- Mathieu Baudier <mbaudier@argeo.org>  Thu, 09 Mar 2023 09:33:35 +0100
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..1b8eb51
--- /dev/null
@@ -0,0 +1,25 @@
+Source: argeo-freed
+Section: unknown
+Priority: optional
+Maintainer: Mathieu Baudier <mbaudier@argeo.org>
+Build-Depends: debhelper-compat (= 13)
+Standards-Version: 4.5.1
+Rules-Requires-Root: no
+
+Package: argeo-freed-libreswan
+Architecture: all
+Depends: ${misc:Depends}, libreswan
+Description: FREEd extensions to libreswan
+ Argeo FREEd extensions to libreswan
+
+Package: argeo-freed-roaming-client
+Architecture: all
+Depends: ${misc:Depends}, argeo-freed-libreswan, unbound
+Description: FREEd roaming client
+ Argeo FREEd roaming client
+
+Package: argeo-freed-roaming-host
+Architecture: all
+Depends: ${misc:Depends}, argeo-freed-libreswan
+Description: FREEd roaming host
+ Argeo FREEd roaming host
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..2936dda
--- /dev/null
@@ -0,0 +1,23 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: argeo-freed
+Upstream-Contact: Mathieu Baudier
+Source: http://git.argeo.org
+
+Files: *
+Copyright: 2023 Argeo GmbH
+License: GPL-3+
+ This package 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 3 of the License, or
+ (at your option) any later version.
+ .
+ This package 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.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
\ No newline at end of file
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..2d33f6a
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/make -f
+
+%:
+       dh $@
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..89ae9db
--- /dev/null
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/etc/ipsec.d/roaming-host-domain.conf.template b/etc/ipsec.d/roaming-host-domain.conf.template
new file mode 100644 (file)
index 0000000..1880dff
--- /dev/null
@@ -0,0 +1,4 @@
+conn roaming-host-domain
+       leftsubnet=fdfd:dead:beef::/48
+       modecfgdomains="in.example.org f.e.e.b.d.a.e.d.d.f.d.f.ip6.arpa"
+       #modecfgdomains="."
diff --git a/etc/ipsec.d/roaming-host.conf b/etc/ipsec.d/roaming-host.conf
new file mode 100644 (file)
index 0000000..57631be
--- /dev/null
@@ -0,0 +1,21 @@
+conn roaming-host-ipv6
+       also=roaming-host-common
+       hostaddrfamily=ipv6
+
+conn roaming-host-ipv4
+       also=roaming-host-common
+       hostaddrfamily=ipv4
+       # Required so that client is considered IPv6:
+       rightsubnet=::/0
+       ipsec-interface=yes
+       leftupdown="/usr/libexec/ipsec/_updown.host4client6"
+
+conn roaming-host-common 
+       also=roaming-host-domain
+       # Authorisation
+       authby=rsa-sha2
+       leftid=%fromcert
+       rightid=%fromcert
+       # Networking
+       clientaddrfamily=ipv6
+       right=%any
diff --git a/etc/ipsec.d/roaming.conf b/etc/ipsec.d/roaming.conf
new file mode 100644 (file)
index 0000000..6bf61fd
--- /dev/null
@@ -0,0 +1,24 @@
+# Generic roaming configurations
+conn roaming-ipv6
+       also=roaming-common
+       hostaddrfamily=ipv6
+       ipsec-interface=yes
+
+conn roaming-ipv4
+       also=roaming-common
+       hostaddrfamily=ipv4
+       # Required so that client is considered IPv6:
+       leftsubnet=::0/0
+       ipsec-interface=yes
+       leftupdown="/usr/libexec/ipsec/_updown.host4client6"
+
+conn roaming-common
+       # Authorisation
+       authby=rsa-sha2
+       leftid=%fromcert
+       rightid=%fromcert
+       leftcert=ipa-client
+       # Networking
+       left=%defaultroute
+       clientaddrfamily=ipv6
+       leftmodecfgclient=yes
diff --git a/usr/lib/systemd/system/freed-ipsec-roaming@.service b/usr/lib/systemd/system/freed-ipsec-roaming@.service
new file mode 100644 (file)
index 0000000..374004b
--- /dev/null
@@ -0,0 +1,27 @@
+[Unit]
+Description=Roaming IPSec to '%i'
+After=network-online.target
+Wants=network-online.target
+
+After=unbound.service
+Requires=unbound.service
+
+After=ipsec.service
+PartOf=ipsec.service
+Requires=ipsec.service
+
+StartLimitIntervalSec=60
+StartLimitBurst=20
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=ipsec auto --start %i
+ExecStop=ipsec auto --delete %i
+
+Restart=on-failure
+RestartSec=3
+
+[Install]
+WantedBy=multi-user.target
+RequiredBy=ipsec.service
diff --git a/usr/lib/systemd/system/freed-onresume.service b/usr/lib/systemd/system/freed-onresume.service
new file mode 100644 (file)
index 0000000..7b7dc54
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=On resume actions
+After=sleep.target
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=oneshot
+ExecStartPre=sleep 3
+ExecStart=/usr/bin/systemctl restart ipsec
+
+[Install]
+WantedBy=sleep.target
+
diff --git a/usr/lib/systemd/system/freed-onsuspend.service b/usr/lib/systemd/system/freed-onsuspend.service
new file mode 100644 (file)
index 0000000..47afcc2
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=On suspend actions
+Before=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/systemctl stop ipsec
+ExecStartPost=/usr/bin/sleep 5
+
+[Install]
+WantedBy=sleep.target
diff --git a/usr/libexec/ipsec/_updown.host4client6 b/usr/libexec/ipsec/_updown.host4client6
new file mode 100755 (executable)
index 0000000..2f748a6
--- /dev/null
@@ -0,0 +1,977 @@
+#!/bin/sh
+#
+# default updown script for use with NETKEY(XFRM)
+#
+# Copyright (C) 2003-2004 Nigel Metheringham
+# Copyright (C) 2002-2007 Michael Richardson <mcr@xelerance.com>
+# Copyright (C) 2007-2008 Paul Wouters <paul@xelerance.com>
+# Copyright (C) 2003-2020 Tuomo Soini <tis@foobar.fi>
+# Copyright (C) 2011-2016 Paul Wouters <pwouters@redhat.com>
+# Copyright (C) 2016 Antony Antony <antony@phenome.org>
+#
+# 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 <https://www.gnu.org/licenses/gpl2.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.
+
+# CAUTION:  Installing a new version of Libreswan will install a new
+# copy of this script, wiping out any custom changes you make.  If
+# you need changes, make a copy of this under another name, and customize
+# that, and use the (left/right)updown= parameters in ipsec.conf to make
+# Libreswan use your modified updown script instead of this default one.
+
+test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x
+
+LC_ALL=C
+export LC_ALL
+
+# Things that this script gets (from ipsec_pluto(8) man page)
+#
+#
+#      PLUTO_VERSION
+#              indicates  what  version of this interface is being
+#              used.  This document describes version  1.1.   This
+#              is upwardly compatible with version 1.0.
+#
+#      PLUTO_VERB
+#              specifies the name of the operation to be performed
+#              (prepare-host, prepare-client, up-host, up-client,
+#              down-host, or down-client).  If the address family
+#              for security gateway to security gateway
+#              communications is IPv6, then a suffix of -v6 is added
+#              to the verb.
+#
+#      PLUTO_CONNECTION
+#              is the name of the  connection  for  which  we  are
+#              routing.
+#
+#      PLUTO_CONN_POLICY
+#              the policy of the connection, as in:
+#              RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC
+#              +failureDROP+lKOD+rKOD
+#
+#      PLUTO_NEXT_HOP
+#              is the next hop to which packets bound for the peer
+#              must be sent.
+#
+#      PLUTO_INTERFACE
+#              is the name of the real interface used by encrypted traffic and IKE traffic
+#
+#      PLUTO_ME
+#              is the IP address of our host.
+#
+#      PLUTO_METRIC
+#              is the metric to set for the route
+#
+#      PLUTO_MTU
+#              is the mtu to set for the route
+#
+#      PLUTO_MY_CLIENT
+#              is the IP address / count of our client subnet.  If
+#              the  client  is  just  the  host,  this will be the
+#              host's own IP address / mask (where max is  32  for
+#              IPv4 and 128 for IPv6).
+#
+#      PLUTO_MY_CLIENT_NET
+#              is the IP address of our client net.  If the client
+#              is just the host, this will be the  host's  own  IP
+#              address.
+#
+#      PLUTO_MY_CLIENT_MASK
+#              is  the  mask for our client net.  If the client is
+#              just the host, this will be 255.255.255.255.
+#
+#      PLUTO_MY_SOURCEIP
+#              if non-empty, then the source address for the route will be
+#              set to this IP address.
+#
+#      PLUTO_MY_PROTOCOL
+#              is the protocol  for this  connection.  Useful  for
+#              firewalling.
+#
+#      PLUTO_MY_PORT
+#              is the port. Useful for firewalling.
+#
+#      PLUTO_PEER
+#              is the IP address of our peer.
+#
+#      PLUTO_PEER_CLIENT
+#              is the IP address / count of the peer's client subnet.
+#              If the client is just the peer, this will be
+#              the peer's own IP address / mask (where max  is  32
+#              for IPv4 and 128 for IPv6).
+#
+#      PLUTO_PEER_CLIENT_NET
+#              is the IP address of the peer's client net.  If the
+#              client is just the peer, this will  be  the  peer's
+#              own IP address.
+#
+#      PLUTO_PEER_CLIENT_MASK
+#              is  the  mask  for  the  peer's client net.  If the
+#              client   is   just   the   peer,   this   will   be
+#              255.255.255.255.
+#
+#      PLUTO_PEER_PROTOCOL
+#              is  the  protocol  set  for  remote  end  with port
+#              selector.
+#
+#      PLUTO_PEER_PORT
+#              is the peer's port. Useful for firewalling.
+#
+#      PLUTO_CFG_CLIENT=0|1
+#              is MODECFG or IKEv2 Config client.
+#
+#      PLUTO_CFG_SERVER=0|1
+#              is MODECFG or IKEv2 Config server.
+#
+#      PLUTO_CONNECTION_TYPE
+#
+#      PLUTO_CONN_ADDRFAMILY
+#              is the family type, "ipv4" or "ipv6"
+#
+#      PLUTO_PROTO_STACK
+#              is the local IPsec kernel stack used, eg NETKEY, NOSTACK
+#
+#      PLUTO_IS_PEER_CISCO=0|1
+#              remote server type is cisco. Add support for cisco extensions
+#              when used with xauth.
+#
+#      PLUTO_NM_CONFIGURED=0|1
+#              is NetworkManager used for resolv.conf update
+#
+#      PLUTO_SA_REQID
+#              When using KAME or XFRM/NETKEY, the IPsec SA reqid base value.
+#              ESP/AH out is base, ESP/AH in = base + 1
+#              IPCOMP is base + 2 plus for inbound + 1
+#
+#      PLUTO_SA_TYPE
+#              The type of IPsec SA (ESP or AH)
+#
+#      PLUTO_USERNAME
+#              The username (XAUTH or GSSAPI) that was authenticated (if any)
+#              for this SA
+#
+#      PLUTO_VIRT_INTERFACE
+#              is the name of ipsec interface used by clear traffic in/out
+#
+#
+#      XAUTH_FAILED
+#              If xauthfail=soft this will be set to 1 if XAUTH authentication
+#              failed. If xauthfail=hard, the updown scripts never run.
+#
+#      CONNMARK
+#              If mark= is set on the connection, this variable will be
+#              set with the value. It can be used for iptables or VTI.
+#
+#      VTI_IFAC=iface
+#              Name of VTI interface to create
+#
+#      VTI_ROUTING=yes|no
+#              Whether or not to perform ip rule and ip route commands
+#              covering the IPsec SA address ranges to route those packets
+#              into the VTI_IFACE interface. This should be enabled unless
+#              the IPsec SA covers 0.0.0.0/0 <-> 0.0.0.0/0
+#
+#      VTI_SHARED=yes|no
+#              Whether or not more conns (or instances) share a VTI device.
+#               If not shared, the VTI device is deleted when tunnel goes down.
+#
+#      SPI_IN / SPI_OUT
+#              The inbound and outbound SPI's of the connection.
+
+# rpm based systems
+if [ -f /etc/sysconfig/pluto_updown ]; then
+    . /etc/sysconfig/pluto_updown
+# deb based systems
+elif [ -f /etc/default/pluto_updown ]; then
+    . /etc/default/pluto_updown
+fi
+
+BACKUP_RESOLV_CONF=/run/pluto/libreswan-resolv-conf-backup
+ETC_RESOLV_CONF=/etc/resolv.conf
+
+case "${PLUTO_CONN_ADDRFAMILY}" in
+    ipv4)
+       FAMILY=4
+       MAX_CIDR=32
+       SCOPE=50        # Use scope 50 to verify ip was added by addsource()
+       ;;
+    ipv6)
+       FAMILY=6
+       MAX_CIDR=128
+       SCOPE=global
+       ;;
+    *)
+       echo "unknown address family \"${PLUTO_CONN_ADDRFAMILY}\"" >&2
+       exit 1
+       ;;
+esac
+export FAMILY MAX_CIDR SCOPE
+
+# 2022-09-03 - mbaudier : Hack when having an IPv6 subnet
+export CLIENT_FAMILY=6
+export CLIENT_MAX_CIDR=128
+
+# Ignore parameter custom
+if [ "${1}" = "custom" ]; then
+    shift
+fi
+
+while [ $# -gt 0 ]; do
+    case ${1} in
+       --route)
+           case ${2} in
+               [Yy]*)
+                   ROUTE=yes
+                   PROXY_ARP_ROUTE=no
+                   ;;
+               *)
+                   ROUTE=
+                   PROXY_ARP_ROUTE=
+                   ;;
+           esac
+           shift; shift
+           ;;
+       --iproute)
+           IPRARGS="${2}"
+           shift; shift
+           ;;
+       *)
+           echo "$0: Unknown argument \"${1}\"" >&2
+           exit 1
+           ;;
+    esac
+done
+
+# utility functions for route manipulation
+# Meddling with this stuff should not be necessary and requires great care.
+uproute() {
+    doproxyarp add
+    doroute replace
+}
+
+downroute() {
+    doroute del
+    doproxyarp delete
+}
+
+downrule() {
+    if [ -n "${PLUTO_MY_SOURCEIP}" -a 0${PLUTO_IS_PEER_CISCO} -eq 1 ]; then
+       doroute del
+    fi
+}
+
+updateresolvconf() {
+    local domain
+    local nameserver
+    local new_nameserver
+    local new_resolv_conf
+    local new_search
+    local orig_domain
+    local orig_nameserver
+    local rc
+    rc=0
+    if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then
+       return ${rc}
+    fi
+    if [ -n "$(pidof unbound)" -a \
+       -n "${PLUTO_PEER_DNS_INFO}" -a \
+       -n "${PLUTO_PEER_DOMAIN_INFO}" ]
+    then
+       for domain in ${PLUTO_PEER_DOMAIN_INFO}; do
+           echo "updating local nameserver for ${domain} with ${PLUTO_PEER_DNS_INFO}"
+           unbound-control forward_add ${domain} \
+               ${PLUTO_PEER_DNS_INFO}
+           unbound-control flush_zone ${domain}
+           unbound-control flush_requestlist
+       done
+       rc=$?
+    elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 -a \
+       -n "${PLUTO_PEER_DNS_INFO}" ]
+    then
+       echo "updating resolvconf"
+
+       if [ ! -e "${ETC_RESOLV_CONF}" ]; then
+           echo "resolv.conf does not exist, so doing nothing"
+           return 0
+       fi
+
+       if [ -e "${BACKUP_RESOLV_CONF}" ]; then
+           if grep -q Libreswan "${ETC_RESOLV_CONF}"; then
+               echo "Current resolv.conf is generated by Libreswan, and backup resolv.conf already exists, so doing nothing"
+               return 0
+           else
+               echo "backup resolv.conf exists, but current resolv.conf is not generated by Libreswan"
+           fi
+       fi
+
+       rm -f -- "${BACKUP_RESOLV_CONF}"
+       cp -- "${ETC_RESOLV_CONF}" "${BACKUP_RESOLV_CONF}"
+
+       new_resolv_conf="# Generated by Libreswan (IPsec)"
+
+       orig_domain="$(grep ^domain "${ETC_RESOLV_CONF}" 2>/dev/null | \
+           awk '{ print $2 }')"
+
+       orig_search=$(grep ^search "${ETC_RESOLV_CONF}" 2>/dev/null | \
+           sed 's/^search[[:space:]]\+//;s/[[:space:]]*\#.*//')
+
+       if [ -n "${orig_domain}" ]; then
+           new_resolv_conf="${new_resolv_conf}
+domain ${orig_domain}"
+       fi
+
+       if [ -n "${orig_search}" ]; then
+           new_search="${orig_search}"
+       elif [ -n "${orig_domain}" ]; then
+           new_search="${orig_domain}"
+       fi
+
+       if [ -n "${PLUTO_PEER_DOMAIN_INFO}" ]; then
+           if [ -n "${new_search}" ]; then
+               new_search=$(echo $(echo "${new_search} ${PLUTO_PEER_DOMAIN_INFO}" | tr [:space:] '\n' | awk '!a[$0]++'))
+           else
+               new_search="${PLUTO_PEER_DOMAIN_INFO}"
+           fi
+       fi
+
+       if [ -n "${new_search}" ]; then
+           new_resolv_conf="${new_resolv_conf}
+search ${new_search}"
+       fi
+
+       orig_nameserver=$(grep -m 1 ^nameserver "${ETC_RESOLV_CONF}" | \
+           sed 's/^nameserver[[:space:]]\+//;s/[[:space:]]*\#.*//')
+       if [ -n "${orig_nameserver}" ]; then
+           new_nameserver=$(echo $(echo "${PLUTO_PEER_DNS_INFO} ${orig_nameserver}" | tr [:space:] '\n' | awk '!a[$0]++'))
+       else
+           new_nameserver="${PLUTO_PEER_DNS_INFO}"
+       fi
+
+       for nameserver in ${new_nameserver}; do
+           new_resolv_conf="${new_resolv_conf}
+nameserver ${nameserver}"
+       done
+
+       echo "${new_resolv_conf}" > "${ETC_RESOLV_CONF}"
+       rc=$?
+    fi
+    return ${rc}
+}
+
+restoreresolvconf() {
+    local domain
+    local rc
+    rc=0
+    if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then
+       return ${rc}
+    fi
+    if [ -n "$(pidof unbound)" -a \
+       -n "${PLUTO_PEER_DNS_INFO}" -a \
+       -n "${PLUTO_PEER_DOMAIN_INFO}" ]
+    then
+       for domain in ${PLUTO_PEER_DOMAIN_INFO}; do
+           echo "flushing local nameserver of ${domain}"
+           unbound-control forward_remove ${domain}
+           unbound-control flush_zone ${domain}
+           unbound-control flush_requestlist
+       done
+       rc=$?
+    elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 ]; then
+       # We only restore if current resolv.conf is made by us.
+       if grep -q Libreswan "${ETC_RESOLV_CONF}" 2>/dev/null; then
+           # And if there is a backup...
+           if [ -e "${BACKUP_RESOLV_CONF}" ]; then
+               echo "restoring resolvconf"
+           else
+               return 0
+           fi
+           cp -- "${BACKUP_RESOLV_CONF}" "${ETC_RESOLV_CONF}"
+       fi
+       rm -f -- "${BACKUP_RESOLV_CONF}"
+       rc=0
+    fi
+    return ${rc}
+}
+
+notifyNM() {
+    # This will be called whenever a connection is established or
+    # fails to establish (either phase 1, xauth phase, or phase 2)
+    # or whenever an already established connection is being terminated.
+    # This will send a signal to NetworkManager over dbus so that NM
+    # can keep track of the coonnections.
+
+    if [ 0${PLUTO_NM_CONFIGURED} -eq 1 ]; then
+       echo "sending $1 signal to NetworkManager"
+       libreswan_reason=$1
+       export libreswan_reason
+       export PLUTO_PEER_DOMAIN_INFO
+       export PLUTO_PEER_DNS_INFO
+       export PLUTO_PEER_BANNER
+       export PLUTO_MY_SOURCEIP
+       export PLUTO_PEER
+       [ -x /usr/libexec/nm-libreswan-service-helper ] && \
+           /usr/libexec/nm-libreswan-service-helper
+    fi
+    return 0
+}
+
+addsource() {
+    local interface
+    local st
+    interface=lo
+    st=0
+
+    if [ -z "${PLUTO_MY_SOURCEIP}" ]; then
+        return ${st}
+    fi
+    # check if given sourceip is local and add as alias if not
+    if ! ip -${CLIENT_FAMILY} -o route get ${PLUTO_MY_SOURCEIP} | grep -q ^local; then
+       if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then
+           interface="${VTI_IFACE}"
+       elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then
+           interface=${PLUTO_VIRT_INTERFACE}
+       fi
+       it="ip addr add ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR} dev ${interface} scope ${SCOPE}"
+       oops="$(eval ${it} 2>&1)"
+       st=$?
+       if [ -z "${oops}" -a ${st} -ne 0 ]; then
+           oops="silent error, exit status ${st}"
+       fi
+       case "${oops}" in
+           'RTNETLINK answers: File exists'*)
+               # should not happen, but ... ignore if the
+               # address was already assigned on interface
+               oops=""
+               st=0
+               ;;
+       esac
+       if [ -n "${oops}" -o ${st} -ne 0 ]; then
+           echo "$0: addsource \"${it}\" failed (${oops})" >&2
+       fi
+    fi
+    return ${st}
+}
+
+delsource() {
+    local interface
+    local oops
+    local st
+    interface=lo
+    st=0
+    if [ -z "${PLUTO_MY_SOURCEIP}" ]; then
+        return ${st}
+    fi
+    # Remove source ip if it's not used any more.
+    if [ -z "$(ip -${CLIENT_FAMILY} -o route list src ${PLUTO_MY_SOURCEIP})" ]; then
+       if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then
+           interface="${VTI_IFACE}"
+       elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then
+           interface=${PLUTO_VIRT_INTERFACE}
+       fi
+       # If there is no ip we just return
+       if ! ip -${FAMILY} -o addr list dev ${interface} scope ${SCOPE} | \
+           grep -q ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR}
+       then
+           return ${st}
+       fi
+
+       if [ -n "${PLUTO_MOBIKE_EVENT}" ] ; then
+               return ${st}
+       fi
+
+       it="ip -${CLIENT_FAMILY} addr del ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR} dev ${interface}"
+       oops="$(eval ${it} 2>&1)"
+       st=$?
+       if [ -z "${oops}" -a ${st} -ne 0 ]; then
+           oops="silent error, exit status ${st}"
+       fi
+       case "${oops}" in
+           'RTNETLINK answers: File exists'*)
+               # should not happen, but ... ignore if the
+               # address was already assigned on interface
+               oops=""
+               st=0
+               ;;
+           'RTNETLINK answers: Cannot assign'*)
+               # Address is not there to remove or is there with different
+               # netmask and in that case we must not remove it so we ignore
+               # the error.
+               oops=""
+               st=0
+               ;;
+       esac
+       if [ -n "${oops}" -o ${st} -ne 0 ]; then
+           echo "$0: delsource \"${it}\" failed (${oops})" >&2
+       fi
+    fi
+    return ${st}
+}
+
+doproxyarp() {
+    local cmd
+    local iface
+    cmd=${1}
+    # Check if client has a single ip only client net
+    if [ ${PLUTO_PEER_CLIENT#*/} = ${MAX_CIDR} ]; then
+       # Skip OE special connections and direct host-host connections
+       if [ "${PLUTO_PEER_CLIENT_NET}" = "0.0.0.0" -o \
+           "${PLUTO_PEER_CLIENT_NET}" = "::" -o \
+           "${PLUTO_PEER_CLIENT_NET}" = "${PLUTO_PEER}" -o \
+           "${PLUTO_MY_CLIENT_NET}" = "${PLUTO_ME}" ]
+       then
+           return 0
+       fi
+       # check if client is routeable
+       if ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \
+           grep -E -q -s -v " via |^local"
+       then
+           iface=$(ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \
+               awk '{print $3}')
+           if [ -r /sys/class/net/${iface}/address ]; then
+               macaddr=$(cat /sys/class/net/${iface}/address)
+           fi
+           # add/remove arp entry for the client on ethernet devices only
+           if [ -n "${macaddr}" ]; then
+               if [ "${cmd}" = "add" ]; then
+                   ip -${FAMILY} neigh add proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} \
+                       lladdr ${macaddr} nud permanent
+                   # Force routing, required for proxyarp to work
+                   PROXY_ARP_ROUTE=yes
+                   export PROXY_ARP_ROUTE
+               else
+                   ip -${FAMILY} neigh del proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface}
+               fi
+           fi
+       fi
+    fi
+}
+
+do_ip()
+{
+    local cmd="$1"
+    oops="$(eval ${cmd} 2>&1)"
+    st=$?
+
+    if [ -z "${oops}" -a ${st} -ne 0 ]; then
+       oops="silent error, exit status ${st}"
+    fi
+
+    case "${oops}" in
+       'RTNETLINK answers: No such process'*)
+           # should not happen, but ... ignore if the
+           # route was already removed
+           oops=""
+           st=0
+           ;;
+    esac
+
+    if [ -n "${oops}" -a ${st} -ne 0 ]; then
+       echo "$0: doroute \"${cmd}\" failed (${oops})" >&2
+    fi
+
+    return ${st}
+}
+
+doroute() {
+    local cmd
+    local esp_nexthop
+    local esp_peer_interface
+    local espipro
+    local ipru
+    local route_table
+    local oops
+    local parms
+    local parms2
+    local st
+    local xfrmi_route
+    local xfrmi_rule
+    cmd=${1}
+    route_table=50
+    st=0
+    xfrmi_route="${PLUTO_XFRMI_ROUTE}"
+
+    if [ ${cmd} != del ]; then
+       oops="$(ip -${FAMILY} route get ${PLUTO_PEER_CLIENT_NET} 2>&1)"
+       case "${oops}" in
+           'RTNETLINK answers: No route to host'*)
+               if [ -z "${PLUTO_XFRMI_ROUTE}" ]; then
+                   ROUTE=yes   # Routing is mandatory for IPsec
+               fi
+               ;;
+       esac
+    fi
+
+    if [ -n "${PLUTO_XFRMI_FWMARK}" ]; then
+       xfrmi_rule=yes  # we have to add "ip rules" and "ip route table"
+       ROUTE=no        # xfrmi_route will add the route
+    fi
+
+    # skip routing if it's not enabled or necessary
+    if [ -z "${PLUTO_MY_SOURCEIP}" -a \
+       -z "${PLUTO_MTU}" -a \
+       "${PROXY_ARP_ROUTE}" != yes -a \
+       "${cmd}" != "del" ]
+    then
+       PROXY_ARP_ROUTE=no
+    fi
+
+    if [ -n "${PLUTO_MY_SOURCEIP}" -o -n "${PLUTO_MTU}" ]; then
+       ROUTE=yes
+    fi
+
+    if [ "${PLUTO_PEER_CLIENT}" =  "${PLUTO_MY_CLIENT}" -a \
+       "${PLUTO_XFRMI_ROUTE}" = yes ]
+    then
+       xfrmi_route="samesubnets";
+       echo "leftsubet == rightsubnet = ${PLUTO_PEER_CLIENT} cannot add route"
+    fi
+
+    parms="${PLUTO_PEER_CLIENT}"
+    parms2=${IPRARGS}
+    # nexthop is not needed on ppp interfaces. unset it to make cases
+    # work, where left is set but no leftnexthop (e.g. left=%defaultroute)
+    if ip link show "${PLUTO_INTERFACE%:*}" | grep -q POINTOPOINT; then
+       POINTPOINT=yes
+    fi
+    # use nexthop if nexthop is not %direct and POINTPOINT is not set
+    if [ "${PLUTO_NEXT_HOP}" != "${PLUTO_PEER}" -a -z "${POINTPOINT}" ]; then
+       # XFRM interface needs no nexthop
+       if [ -z "${PLUTO_XFRMI_ROUTE}"  ]; then
+          parms2="via ${PLUTO_NEXT_HOP}"
+       fi
+       esp_nexthop="via ${PLUTO_NEXT_HOP} "
+    fi
+    # route via proper interface according to routing table
+    if [ "${cmd}" = "del" ]; then
+       case "${PLUTO_PEER_CLIENT}" in
+           "0.0.0.0/0")
+               # in case of default route we use half routes
+               peer_interface=$(ip -${FAMILY} -o route list exact 0.0.0.0/1 | \
+                   sed "s/^.*dev \([^ ]*\) .*/\1/")
+               ;;
+           "::/0")
+               # in case of default route we use half routes
+               peer_interface=$(ip -${FAMILY} -o route list exact 2000::/3 | \
+                   sed "s/^.*dev \([^ ]*\) .*/\1/")
+               ;;
+           *)
+               peer_interface=$(ip -${CLIENT_FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} | \
+                   sed "s/^.*dev \([^ ]*\) .*/\1/")
+               ;;
+       esac
+    else
+       peer_interface=$(ip -o route get ${PLUTO_NEXT_HOP} | \
+           sed "s/^.*dev \([^ ]*\) .*/\1/")
+    fi
+
+    esp_peer_interface=$(ip -${FAMILY} -o route get ${PLUTO_NEXT_HOP} \
+       from ${PLUTO_ME} | sed "s/^.*\(dev [^ ]*\) .*/\1/")
+    if [ -z "${esp_peer_interface}" ]; then
+       esp_peer_interface="dev ${PLUTO_INTERFACE}"
+    fi
+
+    if [ -z "${peer_interface}" ]; then
+       peer_interface=${PLUTO_INTERFACE}
+    fi
+
+    if [ "${PLUTO_XFRMI_ROUTE}" = "yes" ]; then
+       peer_interface=${PLUTO_VIRT_INTERFACE}
+    fi
+
+    if [ -n "${VTI_IFACE}" ]; then
+       addsource
+       peer_interface="${VTI_IFACE}"
+    fi
+
+    parms2="${parms2}${PLUTO_MTU:+ mtu ${PLUTO_MTU}}"
+    parms2="${parms2}${PLUTO_METRIC:+ metric ${PLUTO_METRIC}} ${IPROUTEARGS}"
+
+    parms2="${parms2} dev ${peer_interface%:*}"
+
+    # make sure we have sourceip locally in this machine
+    if [ "${cmd}" = "replace" -a -n "${PLUTO_MY_SOURCEIP}" ]; then
+       addsource
+       # use sourceip as route default source
+       parms2="${parms2} src ${PLUTO_MY_SOURCEIP}"
+    fi
+
+    case "${PLUTO_PEER_CLIENT}" in
+       "0.0.0.0/0")
+           # need to provide route that eclipses default, without
+           # replacing it.
+           it="ip -${FAMILY} route ${cmd} 0.0.0.0/1 ${parms2} && \
+               ip -${FAMILY} route ${cmd} 128.0.0.0/1 ${parms2}"
+           ;;
+       "::/0")
+           # need to provide route that eclipses default, without
+           # replacing it.
+           it="ip -${FAMILY} route ${cmd} 2000::/3 ${parms2}"
+           ;;
+       *)
+           it="ip -${CLIENT_FAMILY} route ${cmd} ${parms} ${parms2}"
+           ;;
+    esac
+
+    if [ "${ROUTE}" = yes -o \
+       "${xfrmi_route}" = yes -o \
+       "${PROXY_ARP_ROUTE}" = yes ]
+    then
+       do_ip "${it}"
+       st=$?
+       if [ ${st} -ne 0 ]; then
+           return ${st}
+       fi
+    fi
+
+    if [ "${xfrmi_rule}" = "yes" ]; then
+       espipro="ip -${FAMILY} route ${cmd} ${PLUTO_PEER}/${MAX_CIDR} ${esp_nexthop} ${esp_peer_interface%:*} table ${route_table}"
+       do_ip "${espipro}"
+
+       st=$?
+        if [ ${st} -ne 0 ]; then
+            return ${st}
+        fi
+
+       iprulecmd="${cmd}"
+       if [ "${cmd}" = "replace" ]; then
+           iprulecmd="add"
+       fi
+
+       ipru="ip -${FAMILY} rule ${iprulecmd} prio 100 to ${parms}"
+       ipru="${ipru} fwmark ${PLUTO_XFRMI_FWMARK} lookup ${route_table}"
+
+       do_ip "${ipru}"
+       st=$?
+       if [ ${st} -ne 0 ]; then
+           return ${st}
+       fi
+
+    fi
+    return 0
+}
+
+# TODO: We need to specify CIDR mask but our _MASK variables are in old school format
+# TODO: Exclude udp 4500 traffic
+addnflog() {
+    if [ -n "${NFLOG}" ]; then
+       iptables -I OUTPUT -m policy --dir out --pol ipsec \
+           -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \
+           -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION}
+       iptables -I INPUT  -m policy --dir in --pol ipsec \
+           -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \
+           -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION}
+    fi
+}
+
+delnflog() {
+    if [ -n "${NFLOG}" ]; then
+       iptables -D OUTPUT -m policy --dir out --pol ipsec \
+           -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \
+           -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION}
+       iptables -D INPUT  -m policy --dir in --pol ipsec \
+           -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \
+           -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION}
+    fi
+}
+
+addvtiiface() {
+    if [ -n "${VTI_IFACE}" ]; then
+       if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then
+           echo "vti-interface option ignored because no mark was configured"
+       else
+           if [ ! -d "/proc/sys/net/ipv4/conf/${VTI_IFACE}" ]; then
+               # echo "creating vti interface"
+               vtipeer="${PLUTO_PEER}"
+               if [ "${PLUTO_CONN_KIND}" = CK_INSTANCE -o "${VTI_SHARED}" = "yes" ]; then
+                   vtipeer="0.0.0.0"
+               fi
+               ip tunnel add ${VTI_IFACE} mode vti local ${PLUTO_ME} \
+                   remote ${vtipeer} okey ${CONNMARK_OUT%/*} \
+                   ikey ${CONNMARK_IN%/*}
+               sysctl -w net.ipv4.conf.${VTI_IFACE}.disable_policy=1
+               sysctl -w net.ipv4.conf.${VTI_IFACE}.rp_filter=0
+               sysctl -w net.ipv4.conf.${VTI_IFACE}.forwarding=1
+               if [ -n "${VTI_IP}" ]; then
+                  ip addr add ${VTI_IP} dev ${VTI_IFACE}
+               fi
+               ip link set ${VTI_IFACE} up
+           else
+               # check there was no conflict if we are sharing - might be sensitive to /sbin/ip differences
+               if [ "${VTI_SHARED}" = yes ]; then
+                   #test: ip/ip remote 3.4.5.6 local 1.2.3.4 ttl inherit key 5
+                   cur="$(ip tun show ${VTI_IFACE})"
+                   new="${VTI_IFACE}: ip/ip  remote any  local ${PLUTO_ME}  ttl inherit  key ${CONNMARK_OUT%/*}"
+                   if [ "${cur}" != "${new}" ]; then
+                       echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting"
+                       echo "existing: ${cur}"
+                       echo "wanted  : ${new}"
+                   else
+                       # temp debug
+                       echo "vti interface already exists with identical parameters, OK"
+                   fi
+               else
+                   echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting (perhaps need vti-sharing=yes ?"
+               fi
+           fi
+       fi
+    fi
+}
+
+addvti() {
+    if [ -n "${VTI_IFACE}" ]; then
+       if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then
+           echo "vti-interface option ignored because no mark was configured"
+       else
+           if [ "${VTI_ROUTING}" = yes ]; then
+               # Tuomo should improve this with using ${PLUTO_MY_CLIENT_NET}
+               # echo "setting up vti routing"
+               r=add
+               ip route list | grep -q "${PLUTO_PEER_CLIENT%/*}" && r=change
+               if [ "${r}" = change ]; then
+                   # resolve LAN conflict by forcing host route for default gw
+                   gw="$(ip ro li | grep ^default | awk '{ print $3;}')"
+                   gwdev="$(ip ro li | grep ^default | awk '{ print $5;}')"
+                   # echo "ip route add ${gw} dev ${gwdev}"
+                   ip route add ${gw} dev ${gwdev} >/dev/null ||:
+               fi
+               srcip=""
+               if [ -n "${PLUTO_MY_SOURCEIP}" ]; then
+                   srcip=" src ${PLUTO_MY_SOURCEIP}"
+               fi
+               # echo "ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip}"
+               ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip}
+               echo "done ip route"
+           fi
+       fi
+    fi
+}
+
+delvti() {
+    if [ -n "${VTI_IFACE}" -a -d /proc/sys/net/ipv4/conf/${VTI_IFACE} ]; then
+       if [ "${VTI_ROUTING}" = yes ]; then
+           ip route del ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} \
+               src ${PLUTO_MY_SOURCEIP} ||:
+       fi
+       # TODO: we can't delete vti interface because we don't have proper reference
+       # counting.
+       #if [ "${VTI_SHARED}" = no -a "${PLUTO_CONN_KIND}" != CK_INSTANCE ]; then
+       #       ip tun del ${VTI_IFACE} ||:
+       #fi
+   fi
+}
+
+# Client Address Translation CAT
+addcat() {
+    if [ -n "${CAT}" ] && [ "${PLUTO_MY_CLIENT_NET}" != "0.0.0.0" ] ; then
+       iptables -t nat -I POSTROUTING -m policy --dir out --pol ipsec \
+           -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET}
+       iptables -t nat -I PREROUTING -m policy --dir in --pol ipsec \
+           -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \
+           -j DNAT --to-destination ${PLUTO_ME}
+    fi
+}
+
+delcat() {
+    if [ -n "${CAT}" ]; then
+       iptables -t nat -D PREROUTING -m policy --dir in --pol ipsec  \
+           -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \
+           -j DNAT --to-destination ${PLUTO_ME}
+       iptables -t nat -D POSTROUTING -m policy --dir out --pol ipsec \
+           -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET}
+    fi
+}
+
+# the big choice
+case "${PLUTO_VERB}" in
+    prepare-host|prepare-client)
+       addvtiiface
+       ;;
+    route-host|route-client)
+       # connection to me or my client subnet being routed
+       addvti
+       uproute
+       addnflog
+       ;;
+    unroute-host|unroute-client)
+       # connection to me or my client subnet being unrouted
+       downroute
+       delsource
+       ;;
+    up-host)
+       # connection to me coming up
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    down-host)
+       # connection to me going down
+       downrule
+       delnflog
+       delcat
+       delvti
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    up-client)
+       # connection to my client subnet coming up
+       addvtiiface
+       updateresolvconf
+       addcat
+       addsource
+       notifyNM connect
+       addvti
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    down-client)
+       # connection to my client subnet going down
+       downrule
+       delnflog
+       delcat
+       delvti
+       restoreresolvconf
+       notifyNM disconnect
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    #
+    # IPv6
+    #
+    prepare-host-v6|prepare-client-v6)
+       # prepare client for connection
+       ;;
+    route-host-v6|route-client-v6)
+       # connection to me or my client subnet being routed
+       uproute
+       ;;
+    unroute-host-v6|unroute-client-v6)
+       # connection to me or my client subnet being unrouted
+       downroute
+       delsource
+       ;;
+    up-host-v6)
+       # connection to me coming up
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    down-host-v6)
+       # connection to me going down
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    up-client-v6)
+       # connection to my client subnet coming up
+       addsource
+       updateresolvconf
+       notifyNM connect
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    down-client-v6)
+       # connection to my client subnet going down
+       restoreresolvconf
+       notifyNM disconnect
+       # If you are doing a custom version, firewall commands go here.
+       ;;
+    *) echo "$0: unknown verb \"${PLUTO_VERB}\" or parameter \"${1}\"" >&2
+       exit 1
+       ;;
+esac