File: //usr/libexec/ipsec/_stackmanager
#!/usr/bin/sh
# -*- mode: sh; sh-shell: sh -*-
# STACK startup script
# Copyright (C) 2007 Ken Bantoft <ken@xelerance.com>
# Copyright (C) 2007-2008 Paul Wouters <paul@xelerance.com>
# Copyright (C) 2008-2019 Tuomo Soini <tis@foobar.fi>
# Copyright (C) 2012-2014 Paul Wouters <paul@libreswan.org>
# Copyright (C) 2019 Paul Wouters <pwouters@redhat.com>
#
# 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.
#
# nothing to do if the kernel has no module loading/unloading support
[ ! -f /proc/modules ] && exit 0
# These prevent coverity warnings; variables come in via ipsec addconn call
xfrmlifetime=""
IPSEC_CONF="${IPSEC_CONF:-/etc/ipsec.conf}"
PATH=/usr/sbin:${PATH}
export PATH
# export config setup items needs rename of - to _
eval $(ASAN_OPTIONS=detect_leaks=0 ipsec addconn --configsetup | grep -v "#" | sed "s/-/_/g")
test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x
MODPROBE="modprobe --quiet --use-blacklist"
# not all kernels have either :/
xfrm_stat=/proc/sys/net/core/xfrm_acq_expires
xfrm_old=/proc/net/xfrm_stat
action="${1}"
if [ -z "${action}" ]; then
echo "no action specified - aborted" >&2
exit 1
fi
stop_xfrm() {
local wait larval_drop
wait=""
larval_drop=""
# Validate wait option
[ "${1}" = "--wait" -o "${1}" = "-w" ] && wait="${1}"
if [ -f ${xfrm_stat} -o -f ${xfrm_old}]; then
ip xfrm state flush
ip xfrm policy flush
if [ -n "$(ip xfrm state)" -o -n "$(ip xfrm policy)" ]; then
echo "XFRM IPsec stack could not be cleared" >&2
fi
if [ -f /proc/modules ]; then
# check if we can write our own settings
if [ -n "${wait}" -a -w /proc/sys/net/core/xfrm_larval_drop ]; then
# read previous state so we can restore it
larval_drop=$(cat /proc/sys/net/core/xfrm_larval_drop)
if [ -n "${larval_drop}" ]; then
# set to 0 so we can unload modules
echo 0 >/proc/sys/net/core/xfrm_larval_drop
fi
fi
# XFRM stack found, let's unload.
for mod in xfrm_ipcomp ipcomp ipcomp6 ip_vti xfrm6_tunnel \
xfrm6_mode_tunnel xfrm6_mode_beet xfrm6_mode_ro \
xfrm6_mode_transport xfrm4_mode_transport xfrm4_mode_tunnel \
xfrm4_tunnel xfrm4_mode_beet esp4 esp6 ah4 ah6 \
xfrm_user xfrm_interface
do
# first try and unload the modules without the 10s wait pause
if [ -n "$(grep ^${mod} /proc/modules)" ]; then
# echo "unloading module ${mod}" >&2
rmmod ${mod} 2>/dev/null
fi
# We only run rmmod again with --wait if requested
if [ -n "${wait}" -a \
-n "$(grep ^${mod} /proc/modules)" ]; then
# echo "unloading module ${mod} using --wait" >&2
# we start rmmod to background so unloading one module
# won't block
rmmod ${wait} ${mod} 2>/dev/null &
fi
done
# Finally we wait for background executed rmmods to complete
if [ -n "${wait}" ]; then
wait
if [ -n "${larval_drop}" -a \
-w /proc/sys/net/core/xfrm_larval_drop ]; then
# restore original value of xfrm_larval_drop
echo "${larval_drop}" >/proc/sys/net/core/xfrm_larval_drop
larval_drop=""
fi
fi
fi
fi
# if we were executed with --wait or -w option we inform about unload
# failure
if [ -n "${wait}" -a -n "$(lsmod | grep ^esp)" ]; then
echo "FAIL" >&2
exit 1
fi
}
# We can get called even if we abort with "pluto already running"
start_xfrm() {
# in case pluto crashed
if pidof pluto > /dev/null; then
: pluto is running, skip cleanup
else
ip xfrm policy flush
ip xfrm state flush
fi
cryptomodules
if [ -f /proc/modules ]; then
# load all XFRM modules
for mod in ipcomp6 xfrm_ipcomp ipcomp xfrm6_tunnel xfrm6_mode_tunnel \
xfrm6_mode_beet xfrm6_mode_ro xfrm6_mode_transport \
xfrm4_mode_transport xfrm4_mode_tunnel xfrm4_tunnel \
xfrm4_mode_beet esp4 esp6 ah4 ah6 ip_vti xfrm_interface
do
# echo -n "${mod} " >&2
${MODPROBE} ${mod} 2>/dev/null
done
# xfrm_user is the old name for xfrm4_tunnel - backwards compatibility
${MODPROBE} xfrm_user 2>/dev/null
fi
# Time before kernel ACQUIRE for ondemand/ Opportunistic expires
# Also Time before reserved kernel SPI times out
xcur=$(cat /proc/sys/net/core/xfrm_acq_expires 2>/dev/null)
if [ -w /proc/sys/net/core/xfrm_acq_expires ]; then
if [ ${xfrmlifetime} -ne 0${xcur} ]; then
echo "changing /proc/sys/net/core/xfrm_acq_expires from ${xcur} to ${xfrmlifetime}"
echo ${xfrmlifetime} >/proc/sys/net/core/xfrm_acq_expires
fi
else
echo "WARNING: cannot change /proc/sys/net/core/xfrm_acq_expires from ${xcur} to ${xfrmlifetime}" >&2
fi
# Fail on error in loading XFRM IPsec stack
if [ ! -f ${xfrm_stat} ]; then
echo "FAILURE in loading XFRM IPsec stack" >&2
exit 1
fi
}
stop() {
stop_xfrm
}
cryptomodules() {
# load the most common ciphers/algo's
# padlock must load before aes module - though does not exist on newer
# kernels
# padlock-aes must load before padlock-sha for some reason
${MODPROBE} padlock 2>/dev/null
${MODPROBE} padlock-aes 2>/dev/null
${MODPROBE} padlock-sha 2>/dev/null
# load the most common ciphers/algo's
# aes-x86_64 has higher priority in via crypto api
# kernel directory does not match uname -m on x86_64 :(
modules=$(ls /lib/modules/$(uname -r)/kernel/arch/*/crypto/* 2>/dev/null)
modules="aesni-intel aes-x86_64 geode-aes aes aes_generic des sha512 \
sha256 md5 cbc xcbc ecb ccm gcm ctr cts \
deflate lzo sha256_generic sha512_generic camellia \
cmac chacha20poly1305 ${modules}"
for module in ${modules}
do
module=$(basename ${module} | sed "s/\.ko$//")
# echo -n "${module} " >&2
${MODPROBE} ${module} 2>/dev/null
done
}
# Start the actual work
if [ $(id -u) -ne 0 ]; then
echo "permission denied (must be superuser)" >&2
exit 4
fi
if [ "$2" = "--netkey" -o "$2" = "--xfrm" ]; then
# manual override for use in docker
stack=xfrm
else
stack="$(ASAN_OPTIONS=detect_leaks=0 ipsec addconn --config ${IPSEC_CONF} --liststack | grep -v "#")"
fi
case ${stack} in
xfrm|none)
;;
auto|mast|klips|netkey)
echo "protostack= values auto, klips, mast and netkey are not longer supported, defaulting to xfrm" >&2
stack=xfrm
;;
*)
echo "unknown stack ${stack}" >&2
exit 1
;;
esac
case ${action} in
stop)
# We don't unload XFRM IPsec on stop
if [ -f ${xfrm_stat} ]; then
ip xfrm state flush
ip xfrm policy flush
# module unloading skipped on purpose - can hang for a long
# time or fail
fi
;;
start)
case ${stack} in
xfrm)
start_xfrm
;;
esac
;;
restart)
stop
start
;;
*)
echo "unknown action ${action}" >&2
exit 1
;;
esac
exit 0