pluto: Include fixed.
[strongswan.git] / src / pluto / kernel.c
index 8fac50b..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>
@@ -294,6 +294,8 @@ static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
                        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] = "",
@@ -327,6 +329,18 @@ static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
                        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' ",
@@ -410,6 +424,8 @@ static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
                        "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
@@ -435,6 +451,8 @@ static bool do_command(connection_t *c, struct spd_route *sr, struct state *st,
                        , secure_peerca_str
                        , srcip_str
                        , xauth_id_str
+                       , mark_in
+                       , mark_out
                        , udp_encap
                        , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown))
                {
@@ -749,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)
 {
@@ -762,9 +780,9 @@ 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);
 
@@ -802,7 +820,7 @@ static bool raw_eroute(const ip_address *this_host,
                                {
                                        return TRUE;
                                }
-                               routed = TRUE;
+                               priority = POLICY_PRIORITY_ROUTED;
                                break;
                }
        }
@@ -820,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)
@@ -837,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;
                }
        }
 
@@ -865,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);
@@ -873,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 */
@@ -1034,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)
        {
@@ -1093,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)
@@ -1111,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;
@@ -1119,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);
@@ -1168,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;
@@ -1277,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;
                }
@@ -1310,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;
                }
@@ -1320,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:
@@ -1337,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;
 
@@ -1353,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);
@@ -1384,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)
@@ -1392,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)
@@ -1400,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);
@@ -1419,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;
 
@@ -1434,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;
        }
 
@@ -1448,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;
@@ -1469,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;
                }
@@ -1479,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;
@@ -1603,6 +1606,7 @@ void kernel_finalize()
 {
        hydra->kernel_interface->remove_listener(hydra->kernel_interface,
                                                                                         kernel_handler);
+       free(kernel_handler);
 }
 
 /* Note: install_inbound_ipsec_sa is only used by the Responder.
@@ -2034,11 +2038,11 @@ 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);
@@ -2051,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);