From: Mathieu Baudier Date: Tue, 7 Mar 2023 05:08:57 +0000 (+0100) Subject: Original host4client6 ipsec updown script, working at least from v4.3 X-Git-Tag: v2.3.0~13 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-freed.git;a=commitdiff_plain;h=0ca3923734ff3afe01da825dccb504bd61fbf48d Original host4client6 ipsec updown script, working at least from v4.3 --- diff --git a/usr/libexec/ipsec/_updown.host4client6 b/usr/libexec/ipsec/_updown.host4client6 new file mode 100755 index 0000000..2f748a6 --- /dev/null +++ b/usr/libexec/ipsec/_updown.host4client6 @@ -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 +# Copyright (C) 2007-2008 Paul Wouters +# Copyright (C) 2003-2020 Tuomo Soini +# Copyright (C) 2011-2016 Paul Wouters +# Copyright (C) 2016 Antony Antony +# +# 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. + +# 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