pluto: Include fixed.
[strongswan.git] / src / pluto / kernel.c
index e7fa90b..e4729ef 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <wait.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/queue.h>
+#include <sys/wait.h>
 
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <crypto/rngs/rng.h>
 #include <kernel/kernel_listener.h>
 
-#ifdef KLIPS
 #include <signal.h>
 #include <sys/time.h>   /* for select(2) */
 #include <sys/types.h>  /* for select(2) */
 #include <pfkeyv2.h>
 #include <pfkey.h>
 #include "kameipsec.h"
-#endif /* KLIPS */
 
 #include "constants.h"
 #include "defs.h"
@@ -55,9 +53,7 @@
 #include "state.h"
 #include "timer.h"
 #include "kernel.h"
-#include "kernel_netlink.h"
 #include "kernel_pfkey.h"
-#include "kernel_noklips.h"
 #include "log.h"
 #include "ca.h"
 #include "server.h"
@@ -79,71 +75,6 @@ bool can_do_IPcomp = TRUE;  /* can system actually perform IPCOMP? */
 #define routes_agree(c, d) ((c)->interface == (d)->interface \
                && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop))
 
-#ifndef KLIPS
-
-bool no_klips = TRUE;   /* don't actually use KLIPS */
-
-#else /* !KLIPS */
-
-/* bare (connectionless) shunt (eroute) table
- *
- * Bare shunts are those that don't "belong" to a connection.
- * This happens because some %trapped traffic hasn't yet or cannot be
- * assigned to a connection.  The usual reason is that we cannot discover
- * the peer SG.  Another is that even when the peer has been discovered,
- * it may be that no connection matches all the particulars.
- * We record them so that, with scanning, we can discover
- * which %holds are news and which others should expire.
- */
-
-#define SHUNT_SCAN_INTERVAL     (60 * 2)   /* time between scans of eroutes */
-
-/* SHUNT_PATIENCE only has resolution down to a multiple of the sample rate,
- * SHUNT_SCAN_INTERVAL.
- * By making SHUNT_PATIENCE an odd multiple of half of SHUNT_SCAN_INTERVAL,
- * we minimize the effects of jitter.
- */
-#define SHUNT_PATIENCE  (SHUNT_SCAN_INTERVAL * 15 / 2)  /* inactivity timeout */
-
-struct bare_shunt {
-       policy_prio_t policy_prio;
-       ip_subnet ours;
-       ip_subnet his;
-       ip_said said;
-       int transport_proto;
-       unsigned long count;
-       time_t last_activity;
-       char *why;
-       struct bare_shunt *next;
-};
-
-static struct bare_shunt *bare_shunts = NULL;
-
-#ifdef DEBUG
-static void DBG_bare_shunt(const char *op, const struct bare_shunt *bs)
-{
-       DBG(DBG_KLIPS,
-               {
-                       int ourport = ntohs(portof(&(bs)->ours.addr));
-                       int hisport = ntohs(portof(&(bs)->his.addr));
-                       char ourst[SUBNETTOT_BUF];
-                       char hist[SUBNETTOT_BUF];
-                       char sat[SATOT_BUF];
-                       char prio[POLICY_PRIO_BUF];
-
-                       subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
-                       subnettot(&(bs)->his, 0, hist, sizeof(hist));
-                       satot(&(bs)->said, 0, sat, sizeof(sat));
-                       fmt_policy_prio(bs->policy_prio, prio);
-                       DBG_log("%s bare shunt %p %s:%d -> %s:%d => %s:%d %s    %s"
-                               , op, (const void *)(bs), ourst, ourport, hist, hisport
-                               , sat, (bs)->transport_proto, prio, (bs)->why);
-               });
-}
-#else /* !DEBUG */
-#define DBG_bare_shunt(op, bs) {}
-#endif /* !DEBUG */
-
 /* forward declaration */
 static bool shunt_eroute(connection_t *c, struct spd_route *sr,
                                                 enum routing_t rt_kind, unsigned int op,
@@ -152,8 +83,6 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
 static void set_text_said(char *text_said, const ip_address *dst,
                                                  ipsec_spi_t spi, int proto);
 
-bool no_klips = FALSE;  /* don't actually use KLIPS */
-
 /**
  * Default IPsec SA config (e.g. to install trap policies).
  */
@@ -198,45 +127,15 @@ void record_and_initiate_opportunistic(const ip_subnet *ours,
                                                                           const ip_subnet *his,
                                                                           int transport_proto, const char *why)
 {
+       ip_address src, dst;
        passert(samesubnettype(ours, his));
 
-       /* Add to bare shunt list.
-        * We need to do this because the shunt was installed by KLIPS
-        * which can't do this itself.
-        */
-       {
-               struct bare_shunt *bs = malloc_thing(struct bare_shunt);
-
-               bs->why = clone_str(why);
-               bs->ours = *ours;
-               bs->his = *his;
-               bs->transport_proto = transport_proto;
-               bs->policy_prio = BOTTOM_PRIO;
-
-               bs->said.proto = SA_INT;
-               bs->said.spi = htonl(SPI_HOLD);
-               bs->said.dst = *aftoinfo(subnettypeof(ours))->any;
-
-               bs->count = 0;
-               bs->last_activity = now();
-
-               bs->next = bare_shunts;
-               bare_shunts = bs;
-               DBG_bare_shunt("add", bs);
-       }
-
        /* actually initiate opportunism */
-       {
-               ip_address src, dst;
-
-               networkof(ours, &src);
-               networkof(his, &dst);
-               initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD);
-       }
+       networkof(ours, &src);
+       networkof(his, &dst);
+       initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD);
 }
 
-#endif /* KLIPS */
-
 /* Generate Unique SPI numbers.
  *
  * The returned SPI is in network byte order.
@@ -351,7 +250,7 @@ static void escape_metachar(const char *src, char *dst, size_t dstlen)
 # define DEFAULT_UPDOWN "ipsec _updown"
 #endif
 
-static bool do_command(connection_t *c, struct spd_route *sr,
+static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
                                           const char *verb)
 {
        char cmd[1536];     /* arbitrary limit on shell command length */
@@ -395,6 +294,9 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                        peerclientnet_str[ADDRTOT_BUF],
                        peerclientmask_str[ADDRTOT_BUF],
                        peerca_str[BUF_LEN],
+                       mark_in[BUF_LEN] = "",
+                       mark_out[BUF_LEN] = "",
+                       udp_encap[BUF_LEN] = "",
                        xauth_id_str[BUF_LEN] = "",
                        secure_myid_str[BUF_LEN] = "",
                        secure_peerid_str[BUF_LEN] = "",
@@ -427,6 +329,24 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                        strncat(srcip_str, "' ", sizeof(srcip_str));
                }
 
+               if (sr->mark_in.value)
+               {
+                       snprintf(mark_in, sizeof(mark_in), "PLUTO_MARK_IN='%u/0x%08x' ",
+                                        sr->mark_in.value, sr->mark_in.mask);
+               }
+
+               if (sr->mark_out.value)
+               {
+                       snprintf(mark_out, sizeof(mark_out), "PLUTO_MARK_OUT='%u/0x%08x' ",
+                                        sr->mark_out.value, sr->mark_out.mask);
+               }
+
+               if (st && (st->nat_traversal & NAT_T_DETECTED))
+               {
+                       snprintf(udp_encap, sizeof(udp_encap), "PLUTO_UDP_ENC='%u' ",
+                                        sr->that.host_port);
+               }
+
                addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
                snprintf(myid_str, sizeof(myid_str), "%Y", sr->this.id);
                escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
@@ -504,6 +424,9 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                        "PLUTO_PEER_CA='%s' "
                        "%s"        /* optional PLUTO_MY_SRCIP */
                        "%s"        /* optional PLUTO_XAUTH_ID */
+                       "%s"        /* optional PLUTO_MARK_IN */
+                       "%s"        /* optional PLUTO_MARK_OUT */
+                       "%s"        /* optional PLUTO_UDP_ENC */
                        "%s"        /* actual script */
                        , verb, verb_suffix
                        , c->name
@@ -528,6 +451,9 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                        , secure_peerca_str
                        , srcip_str
                        , xauth_id_str
+                       , mark_in
+                       , mark_out
+                       , udp_encap
                        , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))
                {
                        loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);
@@ -538,88 +464,83 @@ static bool do_command(connection_t *c, struct spd_route *sr,
        DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"
                , verb, verb_suffix, cmd));
 
-#ifdef KLIPS
-       if (!no_klips)
+       /* invoke the script, catching stderr and stdout
+        * It may be of concern that some file descriptors will
+        * be inherited.  For the ones under our control, we
+        * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
+        * Any used by library routines (perhaps the resolver or syslog)
+        * will remain.
+        */
+       FILE *f = popen(cmd, "r");
+
+       if (f == NULL)
        {
-               /* invoke the script, catching stderr and stdout
-                * It may be of concern that some file descriptors will
-                * be inherited.  For the ones under our control, we
-                * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
-                * Any used by library routines (perhaps the resolver or syslog)
-                * will remain.
-                */
-               FILE *f = popen(cmd, "r");
+               loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
+               return FALSE;
+       }
 
-               if (f == NULL)
-               {
-                       loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
-                       return FALSE;
-               }
+       /* log any output */
+       for (;;)
+       {
+               /* if response doesn't fit in this buffer, it will be folded */
+               char resp[256];
 
-               /* log any output */
-               for (;;)
+               if (fgets(resp, sizeof(resp), f) == NULL)
                {
-                       /* if response doesn't fit in this buffer, it will be folded */
-                       char resp[256];
-
-                       if (fgets(resp, sizeof(resp), f) == NULL)
+                       if (ferror(f))
                        {
-                               if (ferror(f))
-                               {
-                                       log_errno((e, "fgets failed on output of %s%s command"
-                                               , verb, verb_suffix));
-                                       return FALSE;
-                               }
-                               else
-                               {
-                                       passert(feof(f));
-                                       break;
-                               }
+                               log_errno((e, "fgets failed on output of %s%s command"
+                                       , verb, verb_suffix));
+                               return FALSE;
                        }
                        else
                        {
-                               char *e = resp + strlen(resp);
-
-                               if (e > resp && e[-1] == '\n')
-                                       e[-1] = '\0';       /* trim trailing '\n' */
-                               plog("%s%s output: %s", verb, verb_suffix, resp);
+                               passert(feof(f));
+                               break;
                        }
                }
-
-               /* report on and react to return code */
+               else
                {
-                       int r = pclose(f);
+                       char *e = resp + strlen(resp);
 
-                       if (r == -1)
-                       {
-                               log_errno((e, "pclose failed for %s%s command"
-                                       , verb, verb_suffix));
-                               return FALSE;
-                       }
-                       else if (WIFEXITED(r))
-                       {
-                               if (WEXITSTATUS(r) != 0)
-                               {
-                                       loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
-                                               , verb, verb_suffix, WEXITSTATUS(r));
-                                       return FALSE;
-                               }
-                       }
-                       else if (WIFSIGNALED(r))
-                       {
-                               loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
-                                       , verb, verb_suffix, WTERMSIG(r));
-                               return FALSE;
-                       }
-                       else
+                       if (e > resp && e[-1] == '\n')
+                               e[-1] = '\0';       /* trim trailing '\n' */
+                       plog("%s%s output: %s", verb, verb_suffix, resp);
+               }
+       }
+
+       /* report on and react to return code */
+       {
+               int r = pclose(f);
+
+               if (r == -1)
+               {
+                       log_errno((e, "pclose failed for %s%s command"
+                               , verb, verb_suffix));
+                       return FALSE;
+               }
+               else if (WIFEXITED(r))
+               {
+                       if (WEXITSTATUS(r) != 0)
                        {
-                               loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
-                                       , verb, verb_suffix, r);
+                               loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
+                                       , verb, verb_suffix, WEXITSTATUS(r));
                                return FALSE;
                        }
                }
+               else if (WIFSIGNALED(r))
+               {
+                       loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
+                               , verb, verb_suffix, WTERMSIG(r));
+                       return FALSE;
+               }
+               else
+               {
+                       loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
+                               , verb, verb_suffix, r);
+                       return FALSE;
+               }
        }
-#endif /* KLIPS */
        return TRUE;
 }
 
@@ -662,10 +583,9 @@ static enum routability could_route(connection_t *c)
        }
 
        /* if routing would affect IKE messages, reject */
-       if (!no_klips
-       && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT
-       && c->spd.this.host_port != IKE_UDP_PORT
-       && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client))
+       if (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT
+        && c->spd.this.host_port != IKE_UDP_PORT
+        && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client))
        {
                loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
                return route_impossible;
@@ -685,7 +605,6 @@ static enum routability could_route(connection_t *c)
                                                                         using the eroute */
        }
 
-#ifdef KLIPS
        /* if there is an eroute for another connection, there is a problem */
        if (ero != NULL && ero != c)
        {
@@ -769,10 +688,9 @@ static enum routability could_route(connection_t *c)
                        loglog(RC_LOG_SERIOUS
                                , "cannot install eroute -- it is in use for \"%s\"%s #%lu"
                                , ero->name, inst, esr->eroute_owner);
-                       return FALSE;       /* another connection already using the eroute */
+                       return route_impossible;
                }
        }
-#endif /* KLIPS */
        return route_easy;
 }
 
@@ -817,9 +735,7 @@ void unroute_connection(connection_t *c)
                {
                        /* cannot handle a live one */
                        passert(sr->routing != RT_ROUTED_TUNNEL);
-#ifdef KLIPS
                        shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete");
-#endif
                }
 
                sr->routing = RT_UNROUTED;  /* do now so route_owner won't find us */
@@ -827,14 +743,12 @@ void unroute_connection(connection_t *c)
                /* only unroute if no other connection shares it */
                if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL)
                {
-                       (void) do_command(c, sr, "unroute");
+                       (void) do_command(c, sr, NULL, "unroute");
                }
        }
 }
 
 
-#ifdef KLIPS
-
 static void set_text_said(char *text_said, const ip_address *dst,
                                                  ipsec_spi_t spi, int proto)
 {
@@ -844,76 +758,6 @@ static void set_text_said(char *text_said, const ip_address *dst,
        satot(&said, 0, text_said, SATOT_BUF);
 }
 
-/* find an entry in the bare_shunt table.
- * Trick: return a pointer to the pointer to the entry;
- * this allows the entry to be deleted.
- */
-static struct bare_shunt** bare_shunt_ptr(const ip_subnet *ours,
-                                                                                 const ip_subnet *his,
-                                                                                 int transport_proto)
-{
-       struct bare_shunt *p, **pp;
-
-       for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next)
-       {
-               if (samesubnet(ours, &p->ours)
-               && samesubnet(his, &p->his)
-               && transport_proto == p->transport_proto
-               && portof(&ours->addr) == portof(&p->ours.addr)
-               && portof(&his->addr) == portof(&p->his.addr))
-                       return pp;
-       }
-       return NULL;
-}
-
-/* free a bare_shunt entry, given a pointer to the pointer */
-static void free_bare_shunt(struct bare_shunt **pp)
-{
-       if (pp == NULL)
-       {
-               DBG(DBG_CONTROL,
-                       DBG_log("delete bare shunt: null pointer")
-               )
-       }
-       else
-       {
-               struct bare_shunt *p = *pp;
-
-               *pp = p->next;
-               DBG_bare_shunt("delete", p);
-               free(p->why);
-               free(p);
-       }
-}
-
-void
-show_shunt_status(void)
-{
-       struct bare_shunt *bs;
-
-       for (bs = bare_shunts; bs != NULL; bs = bs->next)
-       {
-               /* Print interesting fields.  Ignore count and last_active. */
-
-               int ourport = ntohs(portof(&bs->ours.addr));
-               int hisport = ntohs(portof(&bs->his.addr));
-               char ourst[SUBNETTOT_BUF];
-               char hist[SUBNETTOT_BUF];
-               char sat[SATOT_BUF];
-               char prio[POLICY_PRIO_BUF];
-
-               subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
-               subnettot(&(bs)->his, 0, hist, sizeof(hist));
-               satot(&(bs)->said, 0, sat, sizeof(sat));
-               fmt_policy_prio(bs->policy_prio, prio);
-
-               whack_log(RC_COMMENT, "%s:%d -> %s:%d => %s:%d %s    %s"
-                       , ourst, ourport, hist, hisport, sat, bs->transport_proto
-                       , prio, bs->why);
-       }
-       if (bare_shunts != NULL)
-               whack_log(RC_COMMENT, BLANK_FORMAT);    /* spacer */
-}
 
 /**
  * Setup an IPsec route entry.
@@ -923,12 +767,12 @@ static bool raw_eroute(const ip_address *this_host,
                                           const ip_subnet *this_client,
                                           const ip_address *that_host,
                                           const ip_subnet *that_client,
+                                          mark_t mark,
                                           ipsec_spi_t spi,
                                           unsigned int proto,
                                           unsigned int satype,
                                           unsigned int transport_proto,
                                           ipsec_sa_cfg_t *sa,
-                                          time_t use_lifetime,
                                           unsigned int op,
                                           const char *opname USED_BY_DEBUG)
 {
@@ -936,15 +780,15 @@ static bool raw_eroute(const ip_address *this_host,
        host_t *host_src, *host_dst;
        policy_type_t type = POLICY_IPSEC;
        policy_dir_t dir = POLICY_OUT;
-       mark_t mark_none = { 0, 0 };
+       policy_priority_t priority = POLICY_PRIORITY_DEFAULT;
        char text_said[SATOT_BUF];
-       bool ok = TRUE, routed = FALSE,
+       bool ok = TRUE,
                 deleting = (op & ERO_MASK) == ERO_DELETE,
                 replacing = op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT);
 
        set_text_said(text_said, that_host, spi, proto);
 
-       DBG(DBG_CONTROL | DBG_KLIPS,
+       DBG(DBG_CONTROL | DBG_KERNEL,
                {
                        int sport = ntohs(portof(&this_client->addr));
                        int dport = ntohs(portof(&that_client->addr));
@@ -976,7 +820,7 @@ static bool raw_eroute(const ip_address *this_host,
                                {
                                        return TRUE;
                                }
-                               routed = TRUE;
+                               priority = POLICY_PRIORITY_ROUTED;
                                break;
                }
        }
@@ -994,15 +838,14 @@ static bool raw_eroute(const ip_address *this_host,
        if (deleting || replacing)
        {
                hydra->kernel_interface->del_policy(hydra->kernel_interface,
-                                               ts_src, ts_dst, dir, mark_none, routed);
+                                               ts_src, ts_dst, dir, sa->reqid, mark, priority);
        }
 
        if (!deleting)
        {
-               /* FIXME: use_lifetime? */
                ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
                                                host_src, host_dst, ts_src, ts_dst, dir, type, sa,
-                                               mark_none, routed) == SUCCESS;
+                                               mark, priority) == SUCCESS;
        }
 
        if (dir == POLICY_IN)
@@ -1011,16 +854,15 @@ static bool raw_eroute(const ip_address *this_host,
                if (deleting || replacing)
                {
                        hydra->kernel_interface->del_policy(hydra->kernel_interface,
-                                               ts_src, ts_dst, dir, mark_none, routed);
+                                               ts_src, ts_dst, dir, sa->reqid, mark, priority);
                }
 
                if (!deleting && ok &&
                        (sa->mode == MODE_TUNNEL || satype == SADB_X_SATYPE_INT))
                {
-                       /* FIXME: use_lifetime? */
                        ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
                                                host_src, host_dst, ts_src, ts_dst, dir, type, sa,
-                                               mark_none, routed) == SUCCESS;
+                                               mark, priority) == SUCCESS;
                }
        }
 
@@ -1032,91 +874,6 @@ static bool raw_eroute(const ip_address *this_host,
        return ok;
 }
 
-/* test to see if %hold remains */
-bool has_bare_hold(const ip_address *src, const ip_address *dst,
-                                  int transport_proto)
-{
-       ip_subnet this_client, that_client;
-       struct bare_shunt **bspp;
-
-       passert(addrtypeof(src) == addrtypeof(dst));
-       happy(addrtosubnet(src, &this_client));
-       happy(addrtosubnet(dst, &that_client));
-       bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto);
-       return bspp != NULL
-               && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD);
-}
-
-
-/* Replace (or delete) a shunt that is in the bare_shunts table.
- * Issues the PF_KEY commands and updates the bare_shunts table.
- */
-bool replace_bare_shunt(const ip_address *src, const ip_address *dst,
-                                               policy_prio_t policy_prio, ipsec_spi_t shunt_spi,
-                                               bool repl, unsigned int transport_proto, const char *why)
-{
-       ip_subnet this_client, that_client;
-       ip_subnet this_broad_client, that_broad_client;
-       const ip_address *null_host = aftoinfo(addrtypeof(src))->any;
-
-       passert(addrtypeof(src) == addrtypeof(dst));
-       happy(addrtosubnet(src, &this_client));
-       happy(addrtosubnet(dst, &that_client));
-       this_broad_client = this_client;
-       that_broad_client = that_client;
-       setportof(0, &this_broad_client.addr);
-       setportof(0, &that_broad_client.addr);
-
-       if (repl)
-       {
-               struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client
-                                                                                                , &that_broad_client, 0);
-
-               /* is there already a broad host-to-host bare shunt? */
-               if (bs_pp == NULL)
-               {
-                       if (raw_eroute(null_host, &this_broad_client, null_host,
-                                                  &that_broad_client, htonl(shunt_spi), SA_INT,
-                                                  SADB_X_SATYPE_INT, 0, &null_ipsec_sa,
-                                                  SHUNT_PATIENCE, ERO_ADD, why))
-                       {
-                               struct bare_shunt *bs = malloc_thing(struct bare_shunt);
-
-                               bs->ours = this_broad_client;
-                               bs->his =  that_broad_client;
-                               bs->transport_proto = 0;
-                               bs->said.proto = SA_INT;
-                               bs->why = clone_str(why);
-                               bs->policy_prio = policy_prio;
-                               bs->said.spi = htonl(shunt_spi);
-                               bs->said.dst = *null_host;
-                               bs->count = 0;
-                               bs->last_activity = now();
-                               bs->next = bare_shunts;
-                               bare_shunts = bs;
-                               DBG_bare_shunt("add", bs);
-                       }
-               }
-               shunt_spi = SPI_HOLD;
-       }
-
-       if (raw_eroute(null_host, &this_client, null_host, &that_client,
-                                  htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT, transport_proto,
-                                  &null_ipsec_sa, SHUNT_PATIENCE, ERO_DELETE, why))
-       {
-               struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client
-                                                                               , transport_proto);
-
-               /* delete bare eroute */
-               free_bare_shunt(bs_pp);
-               return TRUE;
-       }
-       else
-       {
-               return FALSE;
-       }
-}
-
 static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
                                                          unsigned int proto, unsigned int satype,
                                                          ipsec_sa_cfg_t *sa, unsigned int op,
@@ -1124,6 +881,7 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
 {
        const ip_address *peer = &sr->that.host_addr;
        char buf2[256];
+       bool ok;
 
        snprintf(buf2, sizeof(buf2)
                         , "eroute_connection %s", opname);
@@ -1132,9 +890,13 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
        {
                peer = aftoinfo(addrtypeof(peer))->any;
        }
+       ok = raw_eroute(peer, &sr->that.client,
+                                       &sr->this.host_addr, &sr->this.client, sr->mark_in,
+                                       spi, proto, satype, sr->this.protocol,
+                                       sa, op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), buf2);
        return raw_eroute(&sr->this.host_addr, &sr->this.client, peer,
-                                         &sr->that.client, spi, proto, satype, sr->this.protocol,
-                                         sa, 0, op, buf2);
+                                         &sr->that.client, sr->mark_out, spi, proto, satype,
+                                         sr->this.protocol, sa, op, buf2) && ok;
 }
 
 /* assign a bare hold to a connection */
@@ -1167,12 +929,11 @@ bool assign_hold(connection_t *c USED_BY_DEBUG, struct spd_route *sr,
                break;
        }
 
-       /* we need a broad %hold, not the narrow one.
+       /* We need a broad %hold
         * First we ensure that there is a broad %hold.
         * There may already be one (race condition): no need to create one.
         * There may already be a %trap: replace it.
         * There may not be any broad eroute: add %hold.
-        * Once the broad %hold is in place, delete the narrow one.
         */
        if (rn != ro)
        {
@@ -1186,11 +947,6 @@ bool assign_hold(connection_t *c USED_BY_DEBUG, struct spd_route *sr,
                        return FALSE;
                }
        }
-       if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE,
-                                                       transport_proto, "delete narrow %hold"))
-       {
-               return FALSE;
-       }
        sr->routing = rn;
        return TRUE;
 }
@@ -1299,7 +1055,6 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
         * The SPI signifies the kind of shunt.
         */
        ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);
-       bool ok;
 
        if (spi == 0)
        {
@@ -1358,14 +1113,8 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
                }
        }
 
-       ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client,
-                                       &c->spd.this.host_addr, &c->spd.this.client, htonl(spi),
-                                       SA_INT, SADB_X_SATYPE_INT, sr->this.protocol,
-                                       &null_ipsec_sa, 0,
-                                       op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
-
        return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT,
-                                                        &null_ipsec_sa, op, opname) && ok;
+                                                        &null_ipsec_sa, op, opname);
 }
 
 static bool setup_half_ipsec_sa(struct state *st, bool inbound)
@@ -1376,7 +1125,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
        ipsec_mode_t mode = MODE_TRANSPORT;
        ipsec_sa_cfg_t sa = { .mode = 0 };
        lifetime_cfg_t lt_none = { .time = { .rekey = 0 } };
-       mark_t mark_none = { 0, 0 };
+       mark_t mark;
        bool ok = TRUE;
        /* SPIs, saved for undoing, if necessary */
        struct kernel_sa said[EM_MAXRELSPIS], *said_next = said;
@@ -1384,11 +1133,13 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
        {
                src = &c->spd.that;
                dst = &c->spd.this;
+               mark = c->spd.mark_in;
        }
        else
        {
                src = &c->spd.this;
                dst = &c->spd.that;
+               mark = c->spd.mark_out;
        }
 
        host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
@@ -1433,9 +1184,9 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
 
                if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
                                                host_dst, ipcomp_spi, said_next->proto, c->spd.reqid,
-                                               mark_none, &lt_none, ENCR_UNDEFINED, chunk_empty,
+                                               mark, 0, &lt_none, ENCR_UNDEFINED, chunk_empty,
                                                AUTH_UNDEFINED, chunk_empty, mode,
-                                               st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE,
+                                               st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE, FALSE,
                                                inbound, NULL, NULL) != SUCCESS)
                {
                        goto fail;
@@ -1542,9 +1293,9 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
 
                if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
                                                host_dst, esp_spi, said_next->proto, c->spd.reqid,
-                                               mark_none, &lt_none, enc_alg, enc_key,
+                                               mark, 0, &lt_none, enc_alg, enc_key,
                                                auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
-                                               encap, inbound, NULL, NULL) != SUCCESS)
+                                               encap, FALSE, inbound, NULL, NULL) != SUCCESS)
                {
                        goto fail;
                }
@@ -1575,9 +1326,9 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
 
                if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
                                                host_dst, ah_spi, said_next->proto, c->spd.reqid,
-                                               mark_none, &lt_none, ENCR_UNDEFINED, chunk_empty,
+                                               mark, 0, &lt_none, ENCR_UNDEFINED, chunk_empty,
                                                auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
-                                               FALSE, inbound, NULL, NULL) != SUCCESS)
+                                               FALSE, FALSE, inbound, NULL, NULL) != SUCCESS)
                {
                        goto fail;
                }
@@ -1585,14 +1336,6 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
                mode = MODE_TRANSPORT;
        }
 
-       if (inbound && c->spd.eroute_owner == SOS_NOBODY)
-       {
-               (void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr,
-                                                 &dst->client, 256, SA_IPIP, SADB_SATYPE_UNSPEC,
-                                                 c->spd.this.protocol, &sa, 0, ERO_ADD_INBOUND,
-                                                 "add inbound");
-       }
-
        goto cleanup;
 
 fail:
@@ -1602,7 +1345,7 @@ fail:
                hydra->kernel_interface->del_sa(hydra->kernel_interface, host_src,
                                                                                host_dst, said_next->spi,
                                                                                said_next->proto, 0 /* cpi */,
-                                                                               mark_none);
+                                                                               mark);
        }
        ok = FALSE;
 
@@ -1618,27 +1361,20 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
        const struct end *src, *dst;
        host_t *host_src, *host_dst;
        ipsec_spi_t spi;
-       mark_t mark_none = { 0, 0 };
+       mark_t mark;
        bool result = TRUE;
 
        if (inbound)
        {
                src = &c->spd.that;
                dst = &c->spd.this;
-
-               if (c->spd.eroute_owner == SOS_NOBODY)
-               {
-                       (void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr,
-                                                         &dst->client, 256, IPSEC_PROTO_ANY,
-                                                         SADB_SATYPE_UNSPEC, c->spd.this.protocol,
-                                                         &null_ipsec_sa, 0, ERO_DEL_INBOUND,
-                                                         "delete inbound");
-               }
+               mark = c->spd.mark_in;
        }
        else
        {
                src = &c->spd.this;
                dst = &c->spd.that;
+               mark = c->spd.mark_out;
        }
 
        host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
@@ -1649,7 +1385,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
                spi = inbound ? st->st_ah.our_spi : st->st_ah.attrs.spi;
                result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
                                                                host_src, host_dst, spi, IPPROTO_AH,
-                                                               0 /* cpi */, mark_none) == SUCCESS;
+                                                               0 /* cpi */, mark) == SUCCESS;
        }
 
        if (st->st_esp.present)
@@ -1657,7 +1393,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
                spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
                result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
                                                                host_src, host_dst, spi, IPPROTO_ESP,
-                                                               0 /* cpi */, mark_none) == SUCCESS;
+                                                               0 /* cpi */, mark) == SUCCESS;
        }
 
        if (st->st_ipcomp.present)
@@ -1665,7 +1401,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
                spi = inbound ? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi;
                result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
                                                                host_src, host_dst, spi, IPPROTO_COMP,
-                                                               0 /* cpi */, mark_none) == SUCCESS;
+                                                               0 /* cpi */, mark) == SUCCESS;
        }
 
        host_src->destroy(host_src);
@@ -1684,7 +1420,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
        host_t *host_src = NULL, *host_dst = NULL;
        const struct end *src, *dst;
        ipsec_spi_t spi;
-       mark_t mark_none = { 0, 0 };
+       mark_t mark;
        u_int64_t bytes_kernel = 0;
        bool result = FALSE;
 
@@ -1699,12 +1435,14 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
        {
                src = &c->spd.that;
                dst = &c->spd.this;
+               mark = c->spd.mark_in;
                spi = st->st_esp.our_spi;
        }
        else
        {
                src = &c->spd.this;
                dst = &c->spd.that;
+               mark = c->spd.mark_out;
                spi = st->st_esp.attrs.spi;
        }
 
@@ -1713,7 +1451,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
 
        switch(hydra->kernel_interface->query_sa(hydra->kernel_interface, host_src,
                                                                                         host_dst, spi, IPPROTO_ESP,
-                                                                                        mark_none, &bytes_kernel))
+                                                                                        mark, &bytes_kernel))
        {
                case FAILED:
                        goto failed;
@@ -1734,7 +1472,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
 
                if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
                                                        ts_src, ts_dst, inbound ? POLICY_IN : POLICY_OUT,
-                                                       mark_none, &time_kernel) != SUCCESS)
+                                                       mark, &time_kernel) != SUCCESS)
                {
                        goto failed;
                }
@@ -1744,7 +1482,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
                        st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
                {
                        if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
-                                                       ts_src, ts_dst, POLICY_FWD, mark_none,
+                                                       ts_src, ts_dst, POLICY_FWD, mark,
                                                        &time_kernel) != SUCCESS)
                        {
                                goto failed;
@@ -1763,7 +1501,10 @@ failed:
        return result;
 }
 
-const struct kernel_ops *kernel_ops;
+/**
+ * Handler for kernel events (called by thread-pool thread)
+ */
+kernel_listener_t *kernel_handler;
 
 /**
  * Data for acquire events
@@ -1784,11 +1525,6 @@ void handle_acquire(acquire_data_t *this)
                                                                          "%acquire");
 }
 
-/**
- * Handler for kernel events (called by thread-pool thread)
- */
-kernel_listener_t *kernel_handler;
-
 METHOD(kernel_listener_t, acquire, bool,
           kernel_listener_t *this, u_int32_t reqid,
           traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
@@ -1817,52 +1553,60 @@ METHOD(kernel_listener_t, acquire, bool,
        return TRUE;
 }
 
-#endif /* KLIPS */
+/**
+ * Data for mapping events
+ */
+typedef struct {
+       /** reqid, spi of affected SA */
+       u_int32_t reqid, spi;
+       /** new endpont */
+       ip_address new_end;
+} mapping_data_t;
 
-void init_kernel(void)
+/**
+ * Callback for mapping events (called by main thread)
+ */
+void handle_mapping(mapping_data_t *this)
 {
-#ifdef KLIPS
-
-       init_pfkey();
-
-       kernel_ops = &klips_kernel_ops;
+       process_nat_t_new_mapping(this->reqid, this->spi, &this->new_end);
+}
 
-#if defined(linux) && defined(KERNEL26_SUPPORT)
-       {
-               bool linux_ipsec = 0;
-               struct stat buf;
 
-               linux_ipsec = (stat("/proc/net/pfkey", &buf) == 0);
-               if (linux_ipsec)
-                       {
-                               plog("Using Linux 2.6 IPsec interface code");
-                               kernel_ops = &linux_kernel_ops;
-                       }
-               else
-                       {
-                               plog("Using KLIPS IPsec interface code");
-                       }
-       }
-#endif
+METHOD(kernel_listener_t, mapping, bool,
+          kernel_listener_t *this, u_int32_t reqid, u_int32_t spi, host_t *remote)
+{
+       mapping_data_t *data;
+       DBG(DBG_CONTROL,
+               DBG_log("creating mapping event for SA with SPI %.8x and reqid {%u}",
+                               spi, reqid));
+       INIT(data,
+               .reqid = reqid,
+               .spi = spi,
+               .new_end = *(ip_address*)remote->get_sockaddr(remote),
+       );
+       pluto->events->queue(pluto->events, (void*)handle_mapping, data, free);
+       return TRUE;
+}
 
+void init_kernel(void)
+{
        /* register SA types that we can negotiate */
-       can_do_IPcomp = FALSE;  /* until we get a response from KLIPS */
-       kernel_ops->pfkey_register();
+       can_do_IPcomp = FALSE;  /* until we get a response from the kernel */
+       pfkey_register();
 
        INIT(kernel_handler,
                .acquire = _acquire,
+               .mapping = _mapping,
        );
        hydra->kernel_interface->add_listener(hydra->kernel_interface,
                                                                                  kernel_handler);
-#endif
 }
 
 void kernel_finalize()
 {
-#ifdef KLIPS
        hydra->kernel_interface->remove_listener(hydra->kernel_interface,
                                                                                         kernel_handler);
-#endif
+       free(kernel_handler);
 }
 
 /* Note: install_inbound_ipsec_sa is only used by the Responder.
@@ -1921,13 +1665,8 @@ bool install_inbound_ipsec_sa(struct state *st)
                        return FALSE;
        }
 
-#ifdef KLIPS
        /* (attempt to) actually set up the SAs */
        return setup_half_ipsec_sa(st, TRUE);
-#else /* !KLIPS */
-       DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()"));
-       return TRUE;
-#endif /* !KLIPS */
 }
 
 /* Install a route and then a prospective shunt eroute or an SA group eroute.
@@ -1935,11 +1674,8 @@ bool install_inbound_ipsec_sa(struct state *st)
  * Any SA Group must have already been created.
  * On failure, steps will be unwound.
  */
-bool route_and_eroute(connection_t *c USED_BY_KLIPS,
-                                         struct spd_route *sr USED_BY_KLIPS,
-                                         struct state *st USED_BY_KLIPS)
+bool route_and_eroute(connection_t *c, struct spd_route *sr, struct state *st)
 {
-#ifdef KLIPS
        struct spd_route *esr;
        struct spd_route *rosr;
        connection_t *ero      /* who, if anyone, owns our eroute? */
@@ -1949,7 +1685,6 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                , route_installed = FALSE;
 
        connection_t *ero_top;
-       struct bare_shunt **bspp;
 
        DBG(DBG_CONTROLMORE,
                DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu"
@@ -1976,15 +1711,9 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                        break;
 #endif
 
-       bspp = (ero == NULL)
-               ? bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol)
-               : NULL;
-
        /* install the eroute */
 
-       passert(bspp == NULL || ero == NULL);       /* only one non-NULL */
-
-       if (bspp != NULL || ero != NULL)
+       if (ero != NULL)
        {
                /* We're replacing an eroute */
 
@@ -2010,7 +1739,6 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                                && samesubnet(&esr->that.client, &sr->that.client));
                }
 #endif
-               /* remember to free bspp iff we make it out of here alive */
        }
        else
        {
@@ -2040,7 +1768,7 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                 */
                firewall_notified = st == NULL  /* not a tunnel eroute */
                        || sr->eroute_owner != SOS_NOBODY   /* already notified */
-                       || do_command(c, sr, "up"); /* go ahead and notify */
+                       || do_command(c, sr, st, "up"); /* go ahead and notify */
        }
 
        /* install the route */
@@ -2055,8 +1783,8 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
        else if (ro == NULL)
        {
                /* a new route: no deletion required, but preparation is */
-               (void) do_command(c, sr, "prepare");    /* just in case; ignore failure */
-               route_installed = do_command(c, sr, "route");
+               (void) do_command(c, sr, st, "prepare");    /* just in case; ignore failure */
+               route_installed = do_command(c, sr, st, "route");
        }
        else if (routed(sr->routing) || routes_agree(ro, c))
        {
@@ -2075,13 +1803,13 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                 */
                if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop))
                {
-                       (void) do_command(ro, sr, "unroute");
-                       route_installed = do_command(c, sr, "route");
+                       (void) do_command(ro, sr, st, "unroute");
+                       route_installed = do_command(c, sr, st, "route");
                }
                else
                {
-                       route_installed = do_command(c, sr, "route");
-                       (void) do_command(ro, sr, "unroute");
+                       route_installed = do_command(c, sr, st, "route");
+                       (void) do_command(ro, sr, st, "unroute");
                }
 
                /* record unrouting */
@@ -2102,11 +1830,7 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
        {
                /* Success! */
 
-               if (bspp != NULL)
-               {
-                       free_bare_shunt(bspp);
-               }
-               else if (ero != NULL && ero != c)
+               if (ero != NULL && ero != c)
                {
                        /* check if ero is an ancestor of c. */
                        connection_t *ero2;
@@ -2152,7 +1876,7 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
        {
                /* Failure!  Unwind our work. */
                if (firewall_notified && sr->eroute_owner == SOS_NOBODY)
-                       (void) do_command(c, sr, "down");
+                       (void) do_command(c, sr, st, "down");
 
                if (eroute_installed)
                {
@@ -2160,25 +1884,7 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
                         * Since there is nothing much to be done if the restoration
                         * fails, ignore success or failure.
                         */
-                       if (bspp != NULL)
-                       {
-                               /* Restore old bare_shunt.
-                                * I don't think that this case is very likely.
-                                * Normally a bare shunt would have been assigned
-                                * to a connection before we've gotten this far.
-                                */
-                               struct bare_shunt *bs = *bspp;
-
-                               (void) raw_eroute(&bs->said.dst, /* should be useless */
-                                                                 &bs->ours,
-                                                                 &bs->said.dst, /* should be useless */
-                                                                 &bs->his,
-                                                                 bs->said.spi,  /* network order */
-                                                                 SA_INT, SADB_X_SATYPE_INT, 0,
-                                                                 &null_ipsec_sa, SHUNT_PATIENCE,
-                                                                 ERO_REPLACE, "restore");
-                       }
-                       else if (ero != NULL)
+                       if (ero != NULL)
                        {
                                /* restore ero's former glory */
                                if (esr->eroute_owner == SOS_NOBODY)
@@ -2217,14 +1923,10 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
 
                return FALSE;
        }
-#else /* !KLIPS */
-       return TRUE;
-#endif /* !KLIPS */
 }
 
-bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS)
+bool install_ipsec_sa(struct state *st, bool inbound_also)
 {
-#ifdef KLIPS
        struct spd_route *sr;
 
        DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s"
@@ -2274,21 +1976,6 @@ bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS)
                        }
                }
        }
-#else /* !KLIPS */
-       DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s"
-               , inbound_also? "inbound and oubound" : "outbound only"));
-
-       switch (could_route(st->st_connection))
-       {
-               case route_easy:
-               case route_nearconflict:
-                       break;
-               default:
-                       return FALSE;
-       }
-
-
-#endif /* !KLIPS */
 
        return TRUE;
 }
@@ -2297,10 +1984,8 @@ bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS)
  * we may not succeed, but we bull ahead anyway because
  * we cannot do anything better by recognizing failure
  */
-void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
-                                        bool inbound_only USED_BY_KLIPS)
+void delete_ipsec_sa(struct state *st, bool inbound_only)
 {
-#ifdef KLIPS
        if (!inbound_only)
        {
                /* If the state is the eroute owner, we must adjust
@@ -2326,7 +2011,7 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
                                sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE
                                        ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE;
 
-                               (void) do_command(c, sr, "down");
+                               (void) do_command(c, sr, st, "down");
                                if ((c->policy & POLICY_DONT_REKEY)     && c->kind == CK_INSTANCE)
                                {
                                        /* in this special case, even if the connection
@@ -2347,21 +2032,17 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS,
                (void) teardown_half_ipsec_sa(st, FALSE);
        }
        (void) teardown_half_ipsec_sa(st, TRUE);
-#else /* !KLIPS */
-       DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()"));
-#endif /* !KLIPS */
 }
 
-#ifdef KLIPS
 static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
 {
        connection_t *c = st->st_connection;
        host_t *host_src, *host_dst, *new_src, *new_dst;
-       mark_t mark_none = { 0, 0 };
-       bool result;
        ipsec_spi_t spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
        struct end *src = inbound ? &c->spd.that : &c->spd.this,
                           *dst = inbound ? &c->spd.this : &c->spd.that;
+       mark_t mark = inbound ? c->spd.mark_in : c->spd.mark_out;
+       bool result;
 
        host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
        host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
@@ -2374,7 +2055,7 @@ static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
        result = hydra->kernel_interface->update_sa(hydra->kernel_interface,
                                        spi, IPPROTO_ESP, 0 /* cpi */, host_src, host_dst,
                                        new_src, new_dst, TRUE /* encap */, TRUE /* new_encap */,
-                                       mark_none) == SUCCESS;
+                                       mark) == SUCCESS;
 
        host_src->destroy(host_src);
        host_dst->destroy(host_dst);
@@ -2383,11 +2064,9 @@ static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
 
        return result;
 }
-#endif
 
-bool update_ipsec_sa (struct state *st USED_BY_KLIPS)
+bool update_ipsec_sa (struct state *st)
 {
-#ifdef KLIPS
        if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
        {
                if (st->st_esp.present && (
@@ -2410,10 +2089,6 @@ bool update_ipsec_sa (struct state *st USED_BY_KLIPS)
                return FALSE;
        }
        return TRUE;
-#else /* !KLIPS */
-       DBG(DBG_CONTROL, DBG_log("if I knew how, I'd update_ipsec_sa()"));
-       return TRUE;
-#endif /* !KLIPS */
 }
 
 /* Check if there was traffic on given SA during the last idle_max