Files
strongswan-ext/testing/tests/route-based/net2net-xfrmi-ike/hosts/sun/etc/updown.py
T
Tobias Brunner 210c1e2628 testing: Fix route-based/net2net-xfrmi-ike scenario
On newer systems, the upper hard limit for open file descriptors (see
`ulimit -H -n`) was increased from 4096 to 524288.  Due to how python-daemon
closes potentially open file descriptors (basically stores them in a set,
removes those excluded by config, and loops through all of them), the updown
script was either killed immediately (by the OOM killer) or not ready yet
when updown events occurred.
2020-09-03 15:46:46 +02:00

96 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python
import sys
import vici
import daemon
import logging
from logging.handlers import SysLogHandler
import subprocess
import resource
logger = logging.getLogger('updownLogger')
handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_DAEMON)
handler.setFormatter(logging.Formatter('charon-updown: %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
def handle_interfaces(ike_sa, up):
if_id_in = int(ike_sa['if-id-in'], 16)
if_id_out = int(ike_sa['if-id-out'], 16)
ifname_in = "xfrm-{}-in".format(if_id_in)
ifname_out = "xfrm-{}-out".format(if_id_out)
if up:
logger.info("add XFRM interfaces %s and %s", ifname_in, ifname_out)
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_out,
"-i", str(if_id_out), "-d", "eth0"])
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_in,
"-i", str(if_id_in), "-d", "eth0"])
subprocess.call(["ip", "link", "set", ifname_out, "up"])
subprocess.call(["ip", "link", "set", ifname_in, "up"])
subprocess.call(["iptables", "-A", "FORWARD", "-o", ifname_out,
"-j", "ACCEPT"])
subprocess.call(["iptables", "-A", "FORWARD", "-i", ifname_in,
"-j", "ACCEPT"])
else:
logger.info("delete XFRM interfaces %s and %s", ifname_in, ifname_out)
subprocess.call(["iptables", "-D", "FORWARD", "-o", ifname_out,
"-j", "ACCEPT"])
subprocess.call(["iptables", "-D", "FORWARD", "-i", ifname_in,
"-j", "ACCEPT"])
subprocess.call(["ip", "link", "del", ifname_out])
subprocess.call(["ip", "link", "del", ifname_in])
def install_routes(ike_sa):
if_id_out = int(ike_sa['if-id-out'], 16)
ifname_out = "xfrm-{}-out".format(if_id_out)
child_sa = next(ike_sa["child-sas"].itervalues())
for ts in child_sa['remote-ts']:
logger.info("add route to %s via %s", ts, ifname_out)
subprocess.call(["ip", "route", "add", ts, "dev", ifname_out])
# the hard limit (second number) is the value used by python-daemon when closing
# potentially open file descriptors while daemonizing. since the default is
# 524288 on newer systems, this can take quite a while, and due to how this
# range of FDs is handled internally (as set) it can even trigger the OOM killer
resource.setrlimit(resource.RLIMIT_NOFILE, (256, 256))
# daemonize and run parallel to the IKE daemon
with daemon.DaemonContext():
logger.debug("starting Python updown listener")
try:
session = vici.Session()
ver = session.version()
logger.info("connected to {daemon} {version} ({sysname}, {release}, "
"{machine})".format(**ver))
except:
logger.error("failed to get status via vici")
sys.exit(1)
try:
for label, event in session.listen(["ike-updown", "child-updown"]):
logger.debug("received event: %s %s", label, repr(event))
name = next((x for x in iter(event) if x != "up"))
up = event.get("up", "") == "yes"
ike_sa = event[name]
if label == "ike-updown":
handle_interfaces(ike_sa, up)
elif label == "child-updown" and up:
install_routes(ike_sa)
except IOError:
logger.error("daemon disconnected")
except:
logger.error("exception while listening for events " +
repr(sys.exc_info()[1]))