support of xfrm marks for IKEv2
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 2 Jul 2010 21:45:57 +0000 (23:45 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 2 Jul 2010 21:46:09 +0000 (23:46 +0200)
24 files changed:
src/libcharon/config/child_cfg.c
src/libcharon/config/child_cfg.h
src/libcharon/kernel/kernel_interface.c
src/libcharon/kernel/kernel_interface.h
src/libcharon/kernel/kernel_ipsec.h
src/libcharon/plugins/android/android_service.c
src/libcharon/plugins/ha/ha_tunnel.c
src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libcharon/plugins/load_tester/load_tester_config.c
src/libcharon/plugins/medcli/medcli_config.c
src/libcharon/plugins/nm/nm_service.c
src/libcharon/plugins/sql/sql_config.c
src/libcharon/plugins/stroke/stroke_config.c
src/libcharon/plugins/uci/uci_config.c
src/libcharon/sa/child_sa.c
src/starter/args.c
src/starter/confread.c
src/starter/confread.h
src/starter/keywords.h
src/starter/keywords.txt
src/starter/starterstroke.c
src/stroke/stroke_msg.h

index a33502e..d3f688a 100644 (file)
@@ -114,11 +114,20 @@ struct private_child_cfg_t {
        u_int32_t inactivity;
 
        /**
-        * Reqid to install CHIL_SA with
+        * Reqid to install CHILD_SA with
         */
        u_int32_t reqid;
 
        /**
+        * Optional mark to install inbound CHILD_SA with
+        */
+       mark_t mark_in;
+
+       /**
+        * Optional mark to install outbound CHILD_SA with
+        */
+       mark_t mark_out;
+       /**
         * set up IPsec transport SA in MIPv6 proxy mode
         */
        bool proxy_mode;
@@ -461,6 +470,14 @@ static u_int32_t get_reqid(private_child_cfg_t *this)
 }
 
 /**
+ * Implementation of child_cfg_t.get_mark.
+ */
+static mark_t get_mark(private_child_cfg_t *this, bool inbound)
+{
+       return inbound ? this->mark_in : this->mark_out;
+}
+
+/**
  * Implementation of child_cfg_t.set_mipv6_options.
  */
 static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
@@ -521,7 +538,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
                                                          char *updown, bool hostaccess,
                                                          ipsec_mode_t mode, action_t dpd_action,
                                                          action_t close_action, bool ipcomp,
-                                                         u_int32_t inactivity, u_int32_t reqid)
+                                                         u_int32_t inactivity, u_int32_t reqid,
+                                                         mark_t *mark)
 {
        private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
 
@@ -542,6 +560,7 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
        this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
        this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity;
        this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid;
+       this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark;
        this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
        this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
        this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
@@ -556,6 +575,21 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
        this->use_ipcomp = ipcomp;
        this->inactivity = inactivity;
        this->reqid = reqid;
+
+       /* TODO configure separate inbound and outbound marks */
+       if (mark)
+       {
+               this->mark_in  = *mark;
+               this->mark_out = *mark;
+       }
+       else
+       {
+               this->mark_in.value  = 0;
+               this->mark_in.mask   = 0;
+               this->mark_out.value = 0;
+               this->mark_out.mask  = 0;
+       }
+
        this->proxy_mode = FALSE;
        this->install_policy = TRUE;
        this->refcount = 1;
index db86cd6..a401918 100644 (file)
@@ -26,6 +26,7 @@
 typedef enum action_t action_t;
 typedef enum ipcomp_transform_t ipcomp_transform_t;
 typedef struct lifetime_cfg_t lifetime_cfg_t;
+typedef struct mark_t mark_t;
 typedef struct child_cfg_t child_cfg_t;
 
 #include <library.h>
@@ -83,6 +84,16 @@ struct lifetime_cfg_t {
 };
 
 /**
+ * A mark_t defines an optional mark in a CHILD_SA.
+ */
+struct mark_t {
+       /** Mark value */
+       u_int32_t value;
+       /** Mark mask */
+       u_int32_t mask;
+};
+
+/**
  * A child_cfg_t defines the config template for a CHILD_SA.
  *
  * After creation, proposals and traffic selectors may be added to the config.
@@ -246,6 +257,14 @@ struct child_cfg_t {
        u_int32_t (*get_reqid)(child_cfg_t *this);
 
        /**
+        * Optional mark for CHILD_SA
+        *
+        * @param inbound               TRUE for inbound, FALSE for outbound 
+        * @return                              mark
+        */
+       mark_t (*get_mark)(child_cfg_t *this, bool inbound);
+
+       /**
         * Sets two options needed for Mobile IPv6 interoperability
         *
         * @param proxy_mode    use IPsec transport proxy mode (default FALSE)
@@ -307,12 +326,14 @@ struct child_cfg_t {
  * @param ipcomp                       use IPComp, if peer supports it
  * @param inactivity           inactivity timeout in s before closing a CHILD_SA
  * @param reqid                                specific reqid to use for CHILD_SA, 0 for auto assign
+ * @param mark                         optional mark (can be NULL)
  * @return                                     child_cfg_t object
  */
 child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
                                                          char *updown, bool hostaccess,
                                                          ipsec_mode_t mode, action_t dpd_action,
                                                          action_t close_action, bool ipcomp,
-                                                         u_int32_t inactivity, u_int32_t reqid);
+                                                         u_int32_t inactivity, u_int32_t reqid,
+                                                         mark_t *mark);
 
 #endif /** CHILD_CFG_H_ @}*/
index 64a43a7..837e628 100644 (file)
@@ -67,8 +67,8 @@ METHOD(kernel_interface_t, get_cpi, status_t,
 METHOD(kernel_interface_t, add_sa, status_t,
        private_kernel_interface_t *this, host_t *src, host_t *dst,
        u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
-       lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
-       u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+       mark_t mark, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+       u_int16_t int_alg, chunk_t int_key,     ipsec_mode_t mode, u_int16_t ipcomp,
        u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
        traffic_selector_t *dst_ts)
 {
@@ -77,82 +77,84 @@ METHOD(kernel_interface_t, add_sa, status_t,
                return NOT_SUPPORTED;
        }
        return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
-                       lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi,
-                       encap, inbound, src_ts, dst_ts);
+                       mark, lifetime, enc_alg, enc_key, int_alg, int_key,     mode, ipcomp,
+                       cpi, encap, inbound, src_ts, dst_ts);
 }
 
 METHOD(kernel_interface_t, update_sa, status_t,
        private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol,
        u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap)
+       bool encap, bool new_encap, mark_t mark)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
        return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
-                                                                 new_src, new_dst, encap, new_encap);
+                                                                 new_src, new_dst, encap, new_encap, mark);
 }
 
 METHOD(kernel_interface_t, query_sa, status_t,
        private_kernel_interface_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+       u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
+       return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark, bytes);
 }
 
 METHOD(kernel_interface_t, del_sa, status_t,
        private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
-       protocol_id_t protocol, u_int16_t cpi)
+       protocol_id_t protocol, u_int16_t cpi, mark_t mark)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
-       return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi);
+       return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
 }
 
 METHOD(kernel_interface_t, add_policy, status_t,
        private_kernel_interface_t *this, host_t *src, host_t *dst,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
        policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
-       u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-       bool routed)
+       u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+       u_int16_t cpi,  bool routed)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
        return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
-                       direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
+                       direction, spi, protocol, reqid, mark, mode, ipcomp, cpi, routed);
 }
 
 METHOD(kernel_interface_t, query_policy, status_t,
        private_kernel_interface_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       u_int32_t *use_time)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
        return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
-                                                                        direction, use_time);
+                                                                        direction, mark, use_time);
 }
 
 METHOD(kernel_interface_t, del_policy, status_t,
        private_kernel_interface_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       bool unrouted)
 {
        if (!this->ipsec)
        {
                return NOT_SUPPORTED;
        }
        return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
-                                                                  direction, unrouted);
+                                                                  direction, mark, unrouted);
 }
 
 METHOD(kernel_interface_t, get_source_addr, host_t*,
index 4a62e76..92d85f9 100644 (file)
@@ -90,6 +90,7 @@ struct kernel_interface_t {
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
         * @param reqid                 unique ID for this SA
+        * @param mark                  optional mark for this SA
         * @param lifetime              lifetime_cfg_t for this SA
         * @param enc_alg               Algorithm to use for encryption (ESP only)
         * @param enc_key               key to use for encryption
@@ -106,7 +107,7 @@ struct kernel_interface_t {
         */
        status_t (*add_sa) (kernel_interface_t *this,
                                                host_t *src, host_t *dst, u_int32_t spi,
-                                               protocol_id_t protocol, u_int32_t reqid,
+                                               protocol_id_t protocol, u_int32_t reqid, mark_t mark,
                                                lifetime_cfg_t *lifetime,
                                                u_int16_t enc_alg, chunk_t enc_key,
                                                u_int16_t int_alg, chunk_t int_key,
@@ -131,6 +132,7 @@ struct kernel_interface_t {
         * @param new_dst               new destination address
         * @param encap                 current use of UDP encapsulation
         * @param new_encap             new use of UDP encapsulation
+        * @param mark                  optional mark for this SA
         * @return                              SUCCESS if operation completed, NOT_SUPPORTED if
         *                                        the kernel interface can't update the SA
         */
@@ -138,7 +140,7 @@ struct kernel_interface_t {
                                                  u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
                                                  host_t *src, host_t *dst,
                                                  host_t *new_src, host_t *new_dst,
-                                                 bool encap, bool new_encap);
+                                                 bool encap, bool new_encap, mark_t mark);
 
        /**
         * Query the number of bytes processed by an SA from the SAD.
@@ -147,11 +149,13 @@ struct kernel_interface_t {
         * @param dst                   destination address for this SA
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
+        * @param mark                  optional mark for this SA
         * @param[out] bytes    the number of bytes processed by SA
         * @return                              SUCCESS if operation completed
         */
        status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-                                                 u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+                                                 u_int32_t spi, protocol_id_t protocol, mark_t mark,
+                                                 u_int64_t *bytes);
 
        /**
         * Delete a previously installed SA from the SAD.
@@ -161,10 +165,12 @@ struct kernel_interface_t {
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
         * @param cpi                   CPI for IPComp or 0
+        * @param mark                  optional mark for this SA
         * @return                              SUCCESS if operation completed
         */
        status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-                                               u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+                                               u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+                                               mark_t mark);
 
        /**
         * Add a policy to the SPD.
@@ -180,6 +186,7 @@ struct kernel_interface_t {
         * @param spi                   SPI of SA
         * @param protocol              protocol to use to protect traffic (AH/ESP)
         * @param reqid                 unique ID of an SA to use to enforce policy
+        * @param mark                  mark for this policy
         * @param mode                  mode of SA (tunnel, transport)
         * @param ipcomp                the IPComp transform used
         * @param cpi                   CPI for IPComp
@@ -192,8 +199,8 @@ struct kernel_interface_t {
                                                        traffic_selector_t *dst_ts,
                                                        policy_dir_t direction, u_int32_t spi,
                                                        protocol_id_t protocol, u_int32_t reqid,
-                                                       ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-                                                       bool routed);
+                                                       mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+                                                       u_int16_t cpi, bool routed);
 
        /**
         * Query the use time of a policy.
@@ -204,13 +211,15 @@ struct kernel_interface_t {
         * @param src_ts                traffic selector to match traffic source
         * @param dst_ts                traffic selector to match traffic dest
         * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+        * @param mark                  optional mark
         * @param[out] use_time the time of this SA's last use
         * @return                              SUCCESS if operation completed
         */
        status_t (*query_policy) (kernel_interface_t *this,
                                                          traffic_selector_t *src_ts,
                                                          traffic_selector_t *dst_ts,
-                                                         policy_dir_t direction, u_int32_t *use_time);
+                                                         policy_dir_t direction, mark_t mark,
+                                                         u_int32_t *use_time);
 
        /**
         * Remove a policy from the SPD.
@@ -223,13 +232,14 @@ struct kernel_interface_t {
         * @param src_ts                traffic selector to match traffic source
         * @param dst_ts                traffic selector to match traffic dest
         * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+        * @param mark                  optional mark
         * @param unrouted              TRUE, if this policy is unrouted from the kernel
         * @return                              SUCCESS if operation completed
         */
        status_t (*del_policy) (kernel_interface_t *this,
                                                        traffic_selector_t *src_ts,
                                                        traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction,
+                                                       policy_dir_t direction, mark_t mark,
                                                        bool unrouted);
 
        /**
index 300464c..d09265c 100644 (file)
@@ -121,6 +121,7 @@ struct kernel_ipsec_t {
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
         * @param reqid                 unique ID for this SA
+        * @param mark                  mark for this SA
         * @param lifetime              lifetime_cfg_t for this SA
         * @param enc_alg               Algorithm to use for encryption (ESP only)
         * @param enc_key               key to use for encryption
@@ -138,7 +139,7 @@ struct kernel_ipsec_t {
        status_t (*add_sa) (kernel_ipsec_t *this,
                                                host_t *src, host_t *dst, u_int32_t spi,
                                                protocol_id_t protocol, u_int32_t reqid,
-                                               lifetime_cfg_t *lifetime,
+                                               mark_t mark, lifetime_cfg_t *lifetime,
                                                u_int16_t enc_alg, chunk_t enc_key,
                                                u_int16_t int_alg, chunk_t int_key,
                                                ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
@@ -162,6 +163,7 @@ struct kernel_ipsec_t {
         * @param new_dst               new destination address
         * @param encap                 current use of UDP encapsulation
         * @param new_encap             new use of UDP encapsulation
+        * @param mark                  optional mark for this SA
         * @return                              SUCCESS if operation completed, NOT_SUPPORTED if
         *                                        the kernel interface can't update the SA
         */
@@ -169,7 +171,7 @@ struct kernel_ipsec_t {
                                                  u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
                                                  host_t *src, host_t *dst,
                                                  host_t *new_src, host_t *new_dst,
-                                                 bool encap, bool new_encap);
+                                                 bool encap, bool new_encap, mark_t mark);
 
        /**
         * Query the number of bytes processed by an SA from the SAD.
@@ -178,11 +180,13 @@ struct kernel_ipsec_t {
         * @param dst                   destination address for this SA
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
+        * @param mark                  optional mark for this SA
         * @param[out] bytes    the number of bytes processed by SA
         * @return                              SUCCESS if operation completed
         */
        status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-                                                 u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+                                                 u_int32_t spi, protocol_id_t protocol, mark_t mark,
+                                                 u_int64_t *bytes);
 
        /**
         * Delete a previusly installed SA from the SAD.
@@ -192,10 +196,12 @@ struct kernel_ipsec_t {
         * @param spi                   SPI allocated by us or remote peer
         * @param protocol              protocol for this SA (ESP/AH)
         * @param cpi                   CPI for IPComp or 0
+        * @param mark                  optional mark for this SA
         * @return                              SUCCESS if operation completed
         */
        status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-                                               u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+                                               u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+                                               mark_t mark);
 
        /**
         * Add a policy to the SPD.
@@ -211,6 +217,7 @@ struct kernel_ipsec_t {
         * @param spi                   SPI of SA
         * @param protocol              protocol to use to protect traffic (AH/ESP)
         * @param reqid                 unique ID of an SA to use to enforce policy
+        * @param mark                  mark for this policy
         * @param mode                  mode of SA (tunnel, transport)
         * @param ipcomp                the IPComp transform used
         * @param cpi                   CPI for IPComp
@@ -223,8 +230,8 @@ struct kernel_ipsec_t {
                                                        traffic_selector_t *dst_ts,
                                                        policy_dir_t direction, u_int32_t spi,
                                                        protocol_id_t protocol, u_int32_t reqid,
-                                                       ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-                                                       bool routed);
+                                                       mark_t mark, ipsec_mode_t mode,
+                                                       u_int16_t ipcomp, u_int16_t cpi, bool routed);
 
        /**
         * Query the use time of a policy.
@@ -236,13 +243,15 @@ struct kernel_ipsec_t {
         * @param src_ts                traffic selector to match traffic source
         * @param dst_ts                traffic selector to match traffic dest
         * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+        * @param mark                  optional mark
         * @param[out] use_time the monotonic timestamp of this SA's last use
         * @return                              SUCCESS if operation completed
         */
        status_t (*query_policy) (kernel_ipsec_t *this,
                                                          traffic_selector_t *src_ts,
                                                          traffic_selector_t *dst_ts,
-                                                         policy_dir_t direction, u_int32_t *use_time);
+                                                         policy_dir_t direction, mark_t mark,
+                                                         u_int32_t *use_time);
 
        /**
         * Remove a policy from the SPD.
@@ -255,13 +264,14 @@ struct kernel_ipsec_t {
         * @param src_ts                traffic selector to match traffic source
         * @param dst_ts                traffic selector to match traffic dest
         * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+        * @param mark                  optional mark
         * @param unrouted              TRUE, if this policy is unrouted from the kernel
         * @return                              SUCCESS if operation completed
         */
        status_t (*del_policy) (kernel_ipsec_t *this,
                                                        traffic_selector_t *src_ts,
                                                        traffic_selector_t *dst_ts,
-                                                       policy_dir_t direction,
+                                                       policy_dir_t direction, mark_t mark,
                                                        bool unrouted);
 
        /**
index c60aa86..80d068c 100644 (file)
@@ -291,7 +291,7 @@ static job_requeue_t initiate(private_android_service_t *this)
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
        child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        ts = traffic_selector_create_dynamic(0, 0, 65535);
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
index faa3b2c..e2807c0 100644 (file)
@@ -233,8 +233,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
                                  identification_create_from_string(remote));
        peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
 
-       child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE,
-                                               MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+       child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
+                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
        ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
        ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
index 01df4f7..6b5aeb3 100644 (file)
@@ -1690,10 +1690,11 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
        private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
-       protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
-       u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
-       ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
-       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+       lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+       u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+       u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1849,7 +1850,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 METHOD(kernel_ipsec_t, update_sa, status_t,
        private_kernel_klips_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
        u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap)
+       bool encap, bool new_encap, mark_t mark)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1920,14 +1921,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
        private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+       u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
 {
        return NOT_SUPPORTED;  /* TODO */
 }
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
        private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1992,8 +1993,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
        policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
-       u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-       bool routed)
+       u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+       u_int16_t cpi, bool routed)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -2210,7 +2211,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
        private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       u_int32_t *use_time)
 {
        #define IDLE_PREFIX "idle="
        static const char *path_eroute = "/proc/net/ipsec_eroute";
@@ -2365,7 +2367,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
        private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       bool unrouted)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg = (struct sadb_msg*)request, *out;
@@ -2574,7 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void,
        {
                close(this->socket);
        }
-       if (this->socket_evnets > 0)
+       if (this->socket_events > 0)
        {
                close(this->socket_events);
        }
index 1b8c1b8..019ec93 100644 (file)
@@ -280,6 +280,9 @@ struct policy_entry_t {
        /** parameters of installed policy */
        struct xfrm_selector sel;
 
+       /** optional mark */
+       u_int32_t mark;
+
        /** associated route installed for this policy */
        route_entry_t *route;
 
@@ -292,7 +295,8 @@ struct policy_entry_t {
  */
 static u_int policy_hash(policy_entry_t *key)
 {
-       chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+       chunk_t chunk = chunk_create((void*)&key->sel,
+                                                       sizeof(struct xfrm_selector) + sizeof(u_int32_t));
        return chunk_hash(chunk);
 }
 
@@ -301,7 +305,8 @@ static u_int policy_hash(policy_entry_t *key)
  */
 static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
 {
-       return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+       return memeq(&key->sel, &other_key->sel, 
+                                sizeof(struct xfrm_selector) + sizeof(u_int32_t)) &&
                   key->direction == other_key->direction;
 }
 
@@ -917,11 +922,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
        private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
+       u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
        lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
-       u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool inbound, traffic_selector_t* src_ts,
-       traffic_selector_t* dst_ts)
+       u_int16_t int_alg, chunk_t int_key,     ipsec_mode_t mode, u_int16_t ipcomp,
+       u_int16_t cpi, bool encap, bool inbound,
+       traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
        netlink_buf_t request;
        char *alg_name;
@@ -934,8 +939,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        if (ipcomp != IPCOMP_NONE && cpi != 0)
        {
                lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
-               add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, &lft,
-                          ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+               add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
+                          &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
                           mode, ipcomp, 0, FALSE, inbound, NULL, NULL);
                ipcomp = IPCOMP_NONE;
                /* use transport mode ESP SA, IPComp uses tunnel mode */
@@ -944,9 +949,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
-                ntohl(spi), reqid);
-
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}  "
+                                         "(mark %u/0x%8x)", ntohl(spi), reqid, mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
+                                          ntohl(spi), reqid);
+       }
        hdr = (struct nlmsghdr*)request;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -1151,6 +1163,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 
        if (encap)
        {
+               struct xfrm_encap_tmpl *tmpl;
+
                rthdr->rta_type = XFRMA_ENCAP;
                rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
 
@@ -1160,7 +1174,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        return FAILED;
                }
 
-               struct xfrm_encap_tmpl* tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
+               tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
                tmpl->encap_type = UDP_ENCAP_ESPINUDP;
                tmpl->encap_sport = htons(src->get_port(src));
                tmpl->encap_dport = htons(dst->get_port(dst));
@@ -1177,9 +1191,36 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                rthdr = XFRM_RTA_NEXT(rthdr);
        }
 
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+               rthdr = XFRM_RTA_NEXT(rthdr);
+       }
+
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+               if (mark.value)
+               {
+                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x  "
+                                                 "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+               }
+               else
+               {
+                       DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+               }
                return FAILED;
        }
        return SUCCESS;
@@ -1275,7 +1316,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
        private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+       u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
 {
        netlink_buf_t request;
        struct nlmsghdr *out = NULL, *hdr;
@@ -1285,8 +1326,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
-
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "querying SAD entry with SPI %.8x  (mark %u/0x%8x)",
+                                          ntohl(spi), mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+       }
        hdr = (struct nlmsghdr*)request;
        hdr->nlmsg_flags = NLM_F_REQUEST;
        hdr->nlmsg_type = XFRM_MSG_GETSA;
@@ -1298,6 +1346,24 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
        sa_id->proto = proto_ike2kernel(protocol);
        sa_id->family = dst->get_family(dst);
 
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+               struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+       }
+
        if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
        {
                hdr = out;
@@ -1313,8 +1379,20 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
                                case NLMSG_ERROR:
                                {
                                        struct nlmsgerr *err = NLMSG_DATA(hdr);
-                                       DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)",
-                                                ntohl(spi), strerror(-err->error), -err->error);
+                                       
+                                       if (mark.value)
+                                       {
+                                               DBG1(DBG_KNL, "querying SAD entry with SPI %.8x  "
+                                                                         "(mark %u/0x%8x) failed: %s (%d)",
+                                                                          ntohl(spi), mark.value, mark.mask,
+                                                                          strerror(-err->error), -err->error);
+                                       }
+                                       else
+                                       {
+                                               DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+                                                                         "failed: %s (%d)", ntohl(spi),
+                                                                          strerror(-err->error), -err->error);
+                                       }
                                        break;
                                }
                                default:
@@ -1341,7 +1419,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
        private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
 {
        netlink_buf_t request;
        struct nlmsghdr *hdr;
@@ -1350,13 +1428,20 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
        /* if IPComp was used, we first delete the additional IPComp SA */
        if (cpi)
        {
-               del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0);
+               del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
        }
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
-
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x  (mark %u/0x%8x)",
+                                          ntohl(spi), mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+       }
        hdr = (struct nlmsghdr*)request;
        hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        hdr->nlmsg_type = XFRM_MSG_DELSA;
@@ -1368,19 +1453,53 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
        sa_id->proto = proto_ike2kernel(protocol);
        sa_id->family = dst->get_family(dst);
 
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+               struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+       }
+
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+               if (mark.value)
+               {
+                       DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x  "
+                                                 "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+               }
+               else
+               {
+                       DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+               }
                return FAILED;
        }
-       DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x  (mark %u/0x%8x)",
+                                          ntohl(spi), mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+       }
        return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, update_sa, status_t,
        private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
        u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool old_encap, bool new_encap)
+       bool old_encap, bool new_encap, mark_t mark)
 {
        netlink_buf_t request;
        u_char *pos;
@@ -1398,7 +1517,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        if (cpi)
        {
                update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
-                                 src, dst, new_src, new_dst, FALSE, FALSE);
+                                 src, dst, new_src, new_dst, FALSE, FALSE, mark);
        }
 
        memset(&request, 0, sizeof(request));
@@ -1459,7 +1578,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
        }
 
        /* delete the old SA (without affecting the IPComp SA) */
-       if (del_sa(this, src, dst, spi, protocol, 0) != SUCCESS)
+       if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
        {
                DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
                free(out);
@@ -1558,8 +1677,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
        policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
-       u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-       bool routed)
+       u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+       u_int16_t cpi,  bool routed)
 {
        policy_entry_t *current, *policy;
        bool found = FALSE;
@@ -1571,6 +1690,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        policy = malloc_thing(policy_entry_t);
        memset(policy, 0, sizeof(policy_entry_t));
        policy->sel = ts2selector(src_ts, dst_ts);
+       policy->mark = mark.value & mark.mask;
        policy->direction = direction;
 
        /* find the policy, which matches EXACTLY */
@@ -1580,9 +1700,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        {
                /* use existing policy */
                current->refcount++;
-               DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
-                                         "refcount", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               if (mark.value)
+               {
+                       DBG2(DBG_KNL, "policy %R === %R %N  (mark %u/0x%8x) "
+                                                 "already exists, increasing refcount",
+                                                  src_ts, dst_ts, policy_dir_names, direction,
+                                                  mark.value, mark.mask);
+               }
+               else
+               {
+                       DBG2(DBG_KNL, "policy %R === %R %N "
+                                                 "already exists, increasing refcount",
+                                                  src_ts, dst_ts, policy_dir_names, direction);
+               }
                free(policy);
                policy = current;
                found = TRUE;
@@ -1593,8 +1723,17 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
                policy->refcount = 1;
        }
 
-       DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
-                                  policy_dir_names, direction);
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "adding policy %R === %R %N  (mark %u/0x%8x)",
+                                          src_ts, dst_ts, policy_dir_names, direction,
+                                          mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "adding policy %R === %R %N",
+                                          src_ts, dst_ts, policy_dir_names, direction);
+       }
 
        memset(&request, 0, sizeof(request));
        hdr = (struct nlmsghdr*)request;
@@ -1673,6 +1812,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
        tmpl->mode = mode2kernel(mode);
        tmpl->family = src->get_family(src);
+       rthdr = XFRM_RTA_NEXT(rthdr);
+
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+       }
 
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
@@ -1741,7 +1899,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
        private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       u_int32_t *use_time)
 {
        netlink_buf_t request;
        struct nlmsghdr *out = NULL, *hdr;
@@ -1751,9 +1910,17 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
        memset(&request, 0, sizeof(request));
 
-       DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
-                                  policy_dir_names, direction);
-
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "querying policy %R === %R %N  (mark %u/0x%8x)",
+                                          src_ts, dst_ts, policy_dir_names, direction,
+                                          mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+                                          policy_dir_names, direction);
+       }
        hdr = (struct nlmsghdr*)request;
        hdr->nlmsg_flags = NLM_F_REQUEST;
        hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
@@ -1763,6 +1930,25 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
        policy_id->sel = ts2selector(src_ts, dst_ts);
        policy_id->dir = direction;
 
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+               struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+       }
+
        if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
        {
                hdr = out;
@@ -1816,7 +2002,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
        private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+       traffic_selector_t *dst_ts, policy_dir_t direction,     mark_t mark,
+       bool unrouted)
 {
        policy_entry_t *current, policy, *to_delete = NULL;
        route_entry_t *route;
@@ -1824,12 +2011,22 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        struct nlmsghdr *hdr;
        struct xfrm_userpolicy_id *policy_id;
 
-       DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
-                                  policy_dir_names, direction);
+       if (mark.value)
+       {
+               DBG2(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%8x)",
+                                          src_ts, dst_ts, policy_dir_names, direction,
+                                          mark.value, mark.mask);
+       }
+       else
+       {
+               DBG2(DBG_KNL, "deleting policy %R === %R %N",
+                                          src_ts, dst_ts, policy_dir_names, direction);
+       }
 
        /* create a policy */
        memset(&policy, 0, sizeof(policy_entry_t));
        policy.sel = ts2selector(src_ts, dst_ts);
+       policy.mark = mark.value & mark.mask;
        policy.direction = direction;
 
        /* find the policy */
@@ -1851,8 +2048,17 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        this->mutex->unlock(this->mutex);
        if (!to_delete)
        {
-               DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
-                                          dst_ts, policy_dir_names, direction);
+               if (mark.value)
+               {
+                       DBG1(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%8x) "
+                                                 "failed, not found", src_ts, dst_ts, policy_dir_names,
+                                                  direction, mark.value, mark.mask);
+               }
+               else
+               {
+                       DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+                                                  src_ts, dst_ts, policy_dir_names, direction);
+               }
                return NOT_FOUND;
        }
 
@@ -1867,13 +2073,40 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
        policy_id->sel = to_delete->sel;
        policy_id->dir = direction;
 
+       if (mark.value)
+       {
+               struct xfrm_mark *mrk;
+               struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+
+               rthdr->rta_type = XFRMA_MARK;
+               rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+               hdr->nlmsg_len += rthdr->rta_len;
+               if (hdr->nlmsg_len > sizeof(request))
+               {
+                       return FAILED;
+               }
+
+               mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+               mrk->v = mark.value;
+               mrk->m = mark.mask;
+       }
+
        route = to_delete->route;
        free(to_delete);
 
        if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
        {
-               DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
-                                          policy_dir_names, direction);
+               if (mark.value)
+               {
+                       DBG1(DBG_KNL, "unable to delete policy %R === %R %N  "
+                          "(mark %u/0x%8x)", src_ts, dst_ts, policy_dir_names,
+                                                  direction, mark.value, mark.mask);
+               }
+               else
+               {
+                       DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
+                                                  src_ts, dst_ts, policy_dir_names, direction);
+               }
                return FAILED;
        }
 
index 04abf9f..a64c27f 100644 (file)
@@ -1245,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
        private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
-       protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
-       u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
-       ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
-       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+       lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+       u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+       u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1392,7 +1393,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 METHOD(kernel_ipsec_t, update_sa, status_t,
        private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
        u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-       bool encap, bool new_encap)
+       bool encap, bool new_encap, mark_t mark)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1525,7 +1526,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 
 METHOD(kernel_ipsec_t, query_sa, status_t,
        private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+       u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1581,7 +1582,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
 
 METHOD(kernel_ipsec_t, del_sa, status_t,
        private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+       u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1632,8 +1633,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
        private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
        policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
-       u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-       bool routed)
+       u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+       u_int16_t cpi, bool routed)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1834,7 +1835,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
 
 METHOD(kernel_ipsec_t, query_policy, status_t,
        private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       u_int32_t *use_time)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
@@ -1937,7 +1939,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
 
 METHOD(kernel_ipsec_t, del_policy, status_t,
        private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
-       traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+       traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+       bool unrouted)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
index b9a6f05..528c9a3 100644 (file)
@@ -224,7 +224,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
        }
 
        child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE,
-                                                       MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+                                       MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
        proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
        child_cfg->add_proposal(child_cfg, proposal);
        ts = traffic_selector_create_dynamic(0, 0, 65535);
index 7b9b5aa..e574910 100644 (file)
@@ -181,8 +181,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
                          identification_create_from_encoding(ID_KEY_ID, other));
        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
 
-       child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE,
-                                                       MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+       child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
+                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
        child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
@@ -260,7 +260,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
        this->current->add_auth_cfg(this->current, auth, FALSE);
 
        child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+                                                                ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
        child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
index d9badec..20e6c15 100644 (file)
@@ -444,7 +444,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
 
        child_cfg = child_cfg_create(priv->name, &lifetime,
                                                                 NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
-                                                                ACTION_NONE, ACTION_NONE, ipcomp, 0, 0);
+                                                                ACTION_NONE, ACTION_NONE, ipcomp, 0, 0, NULL);
        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        ts = traffic_selector_create_dynamic(0, 0, 65535);
        child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
index 8893bea..d9964ce 100644 (file)
@@ -134,7 +134,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
                        .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
                };
                child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
-                                                                        dpd, close, ipcomp, 0, 0);
+                                                                        dpd, close, ipcomp, 0, 0, NULL);
                /* TODO: read proposal from db */
                child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
                add_traffic_selectors(this, child_cfg, id);
index c86d145..41bf5d1 100644 (file)
@@ -769,6 +769,10 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
                        .jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
                }
        };
+       mark_t mark = {
+               .value = msg->add_conn.mark.value,
+               .mask = msg->add_conn.mark.mask
+       };
 
        switch (msg->add_conn.dpd.action)
        {       /* map startes magic values to our action type */
@@ -787,7 +791,7 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
                                msg->add_conn.name, &lifetime,
                                msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
                                msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp,
-                               msg->add_conn.inactivity, msg->add_conn.reqid);
+                               msg->add_conn.inactivity, msg->add_conn.reqid, &mark);
        child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
                                                                                        msg->add_conn.install_policy);
        add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
index 00d05c4..ba93d87 100644 (file)
@@ -196,7 +196,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
                this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
 
                child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                        ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+                                                                        ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
                child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
                child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
                child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
index fb1ed34..bd41cba 100644 (file)
@@ -98,6 +98,16 @@ struct private_child_sa_t {
        u_int32_t reqid;
 
        /**
+        * inbound mark used for this child_sa
+        */
+       mark_t mark_in;
+
+       /**
+        * outbound mark used for this child_sa
+        */
+       mark_t mark_out;
+
+       /**
         * absolute time when rekeying is scheduled
         */
        time_t rekey_time;
@@ -431,10 +441,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
        {
                if (this->my_spi)
                {
-                       status = charon->kernel_interface->query_sa(
-                                                                       charon->kernel_interface,
+                       status = charon->kernel_interface->query_sa(charon->kernel_interface,
                                                                        this->other_addr, this->my_addr,
-                                                                       this->my_spi, this->protocol, &bytes);
+                                                                       this->my_spi, this->protocol,
+                                                                       this->mark_in, &bytes);
                        if (status == SUCCESS)
                        {
                                if (bytes > this->my_usebytes)
@@ -450,10 +460,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
        {
                if (this->other_spi)
                {
-                       status = charon->kernel_interface->query_sa(
-                                                                       charon->kernel_interface,
+                       status = charon->kernel_interface->query_sa(charon->kernel_interface,
                                                                        this->my_addr, this->other_addr,
-                                                                       this->other_spi, this->protocol, &bytes);
+                                                                       this->other_spi, this->protocol,
+                                                                       this->mark_out, &bytes);
                        if (status == SUCCESS)
                        {
                                if (bytes > this->other_usebytes)
@@ -485,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
                if (inbound)
                {
                        if (charon->kernel_interface->query_policy(charon->kernel_interface,
-                                                               other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
+                                               other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
                        {
                                last_use = max(last_use, in);
                        }
                        if (this->mode != MODE_TRANSPORT)
                        {
                                if (charon->kernel_interface->query_policy(charon->kernel_interface,
-                                                               other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
+                                               other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
                                {
                                        last_use = max(last_use, fwd);
                                }
@@ -501,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
                else
                {
                        if (charon->kernel_interface->query_policy(charon->kernel_interface,
-                                                               my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
+                                               my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
                        {
                                last_use = max(last_use, out);
                        }
@@ -665,9 +675,10 @@ static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
        }
 
        status = charon->kernel_interface->add_sa(charon->kernel_interface,
-                               src, dst, spi, this->protocol, this->reqid, lifetime,
-                               enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
-                               this->encap, update, src_ts, dst_ts);
+                               src, dst, spi, this->protocol, this->reqid,
+                               inbound ? this->mark_in : this->mark_out,
+                               lifetime, enc_alg, encr, int_alg, integ, this->mode,
+                               this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
 
        free(lifetime);
 
@@ -708,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this,
                        /* install 3 policies: out, in and forward */
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
-                                       this->other_spi, this->protocol, this->reqid, this->mode,
-                                       this->ipcomp, this->other_cpi, routed);
+                                       this->other_spi, this->protocol, this->reqid, this->mark_out,
+                                       this->mode, this->ipcomp, this->other_cpi, routed);
 
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
-                                       this->my_spi, this->protocol, this->reqid, this->mode,
-                                       this->ipcomp, this->my_cpi, routed);
+                                       this->my_spi, this->protocol, this->reqid, this->mark_in,
+                                       this->mode,     this->ipcomp, this->my_cpi, routed);
                        if (this->mode != MODE_TRANSPORT)
                        {
                                status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
-                                       this->my_spi, this->protocol, this->reqid, this->mode,
-                                       this->ipcomp, this->my_cpi, routed);
+                                       this->my_spi, this->protocol, this->reqid, this->mark_in,
+                                       this->mode,     this->ipcomp, this->my_cpi, routed);
                        }
 
                        if (status != SUCCESS)
@@ -768,7 +779,7 @@ static status_t update(private_child_sa_t *this,  host_t *me, host_t *other,
                                                        this->my_spi, this->protocol,
                                                        this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
                                                        this->other_addr, this->my_addr, other, me,
-                                                       this->encap, encap) == NOT_SUPPORTED)
+                                                       this->encap, encap, this->mark_in) == NOT_SUPPORTED)
                        {
                                return NOT_SUPPORTED;
                        }
@@ -781,7 +792,7 @@ static status_t update(private_child_sa_t *this,  host_t *me, host_t *other,
                                                        this->other_spi, this->protocol,
                                                        this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
                                                        this->my_addr, this->other_addr, me, other,
-                                                       this->encap, encap) == NOT_SUPPORTED)
+                                                       this->encap, encap, this->mark_out) == NOT_SUPPORTED)
                        {
                                return NOT_SUPPORTED;
                        }
@@ -803,13 +814,13 @@ static status_t update(private_child_sa_t *this,  host_t *me, host_t *other,
                        {
                                /* remove old policies first */
                                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       my_ts, other_ts, POLICY_OUT, FALSE);
+                                                       my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE);
                                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       other_ts, my_ts,  POLICY_IN, FALSE);
+                                                       other_ts, my_ts,  POLICY_IN, this->mark_in, FALSE);
                                if (this->mode != MODE_TRANSPORT)
                                {
                                        charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       other_ts, my_ts, POLICY_FWD, FALSE);
+                                                       other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE);
                                }
 
                                /* check whether we have to update a "dynamic" traffic selector */
@@ -835,18 +846,18 @@ static status_t update(private_child_sa_t *this,  host_t *me, host_t *other,
                                /* reinstall updated policies */
                                charon->kernel_interface->add_policy(charon->kernel_interface,
                                                me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
-                                               this->protocol, this->reqid, this->mode, this->ipcomp,
-                                               this->other_cpi, FALSE);
+                                               this->protocol, this->reqid, this->mark_out, this->mode,
+                                               this->ipcomp, this->other_cpi, FALSE);
                                charon->kernel_interface->add_policy(charon->kernel_interface,
                                                other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
-                                               this->protocol, this->reqid, this->mode, this->ipcomp,
-                                               this->my_cpi, FALSE);
+                                               this->protocol, this->reqid, this->mark_in, this->mode,
+                                               this->ipcomp, this->my_cpi, FALSE);
                                if (this->mode != MODE_TRANSPORT)
                                {
                                        charon->kernel_interface->add_policy(charon->kernel_interface,
                                                other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
-                                               this->protocol, this->reqid, this->mode, this->ipcomp,
-                                               this->my_cpi, FALSE);
+                                               this->protocol, this->reqid, this->mark_in, this->mode,
+                                               this->ipcomp, this->my_cpi, FALSE);
                                }
                        }
                        enumerator->destroy(enumerator);
@@ -896,13 +907,13 @@ static void destroy(private_child_sa_t *this)
                }
                charon->kernel_interface->del_sa(charon->kernel_interface,
                                        this->other_addr, this->my_addr, this->my_spi,
-                                       this->protocol, this->my_cpi);
+                                       this->protocol, this->my_cpi, this->mark_in);
        }
        if (this->other_spi)
        {
                charon->kernel_interface->del_sa(charon->kernel_interface,
                                        this->my_addr, this->other_addr, this->other_spi,
-                                       this->protocol, this->other_cpi);
+                                       this->protocol, this->other_cpi, this->mark_out);
        }
 
        if (this->config->install_policy(this->config))
@@ -912,13 +923,13 @@ static void destroy(private_child_sa_t *this)
                while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
                {
                        charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               my_ts, other_ts, POLICY_OUT, unrouted);
+                                                       my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted);
                        charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               other_ts, my_ts, POLICY_IN, unrouted);
+                                                       other_ts, my_ts, POLICY_IN, this->mark_in, unrouted);
                        if (this->mode != MODE_TRANSPORT)
                        {
                                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               other_ts, my_ts, POLICY_FWD, unrouted);
+                                                       other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted);
                        }
                }
                enumerator->destroy(enumerator);
@@ -1000,6 +1011,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->config = config;
        config->get_ref(config);
        this->reqid = config->get_reqid(config);
+       this->mark_in = config->get_mark(config, TRUE);
+       this->mark_out = config->get_mark(config, FALSE);
+
        if (!this->reqid)
        {
                /* reuse old reqid if we are rekeying an existing CHILD_SA */
index 26f3aae..4fe9c9d 100644 (file)
@@ -235,6 +235,7 @@ static const token_info_t token_info[] =
        { ARG_STR,  offsetof(starter_conn_t, me_mediated_by), NULL                     },
        { ARG_STR,  offsetof(starter_conn_t, me_peerid), NULL                          },
        { ARG_UINT, offsetof(starter_conn_t, reqid), NULL                              },
+       { ARG_MISC, 0, NULL  /* KW_MARK */                                             },
 
        /* ca section keywords */
        { ARG_STR,  offsetof(starter_ca_t, name), NULL                                 },
index e9b9028..6ebdaf5 100644 (file)
@@ -671,6 +671,41 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
                        }
                        break;
                }
+               case KW_MARK:
+               {
+                       char *pos, *endptr;
+
+                       pos = strchr(kw->value, '/');
+                       if (pos)
+                       {
+                               *pos = '\0';
+                               conn->mark_mask = strtoul(pos+1, &endptr, 0);
+                               if (*endptr != '\0')
+                               {
+                                       plog("# invalid mark mask: %s", pos+1);
+                                       cfg->err++;
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               conn->mark_mask = 0xffffffff;
+                       }
+                       if (*kw->value == '\0')
+                       {
+                               conn->mark_value = 0;
+                       }
+                       else
+                       {
+                               conn->mark_value = strtoul(kw->value, &endptr, 0);
+                               if (*endptr != '\0')
+                               {
+                                       plog("# invalid mark value: %s", kw->value);
+                                       cfg->err++;
+                               }
+                       }
+                       break;
+               }
                case KW_KEYINGTRIES:
                        if (streq(kw->value, "%forever"))
                        {
index 5d845c2..ada155d 100644 (file)
@@ -122,6 +122,8 @@ struct starter_conn {
                unsigned long   sa_keying_tries;
                unsigned long   sa_rekey_fuzz;
                u_int32_t       reqid;
+               u_int32_t               mark_value;
+               u_int32_t               mark_mask;
                sa_family_t     addr_family;
                sa_family_t     tunnel_addr_family;
                bool            install_policy;
index 85b8472..ea702fd 100644 (file)
@@ -98,9 +98,10 @@ typedef enum {
        KW_MEDIATED_BY,
        KW_ME_PEERID,
        KW_REQID,
+       KW_MARK,
 
 #define KW_CONN_FIRST   KW_CONN_SETUP
-#define KW_CONN_LAST    KW_REQID
+#define KW_CONN_LAST    KW_MARK
 
    /* ca section keywords */
        KW_CA_NAME,
index 894e1e9..a9d2af4 100644 (file)
@@ -89,6 +89,7 @@ mediation,         KW_MEDIATION
 mediated_by,       KW_MEDIATED_BY
 me_peerid,         KW_ME_PEERID
 reqid,             KW_REQID
+mark,              KW_MARK
 cacert,            KW_CACERT
 ldaphost,          KW_LDAPHOST
 ldapbase,          KW_LDAPBASE
index 6a50007..475f07c 100644 (file)
@@ -270,6 +270,8 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
        msg.add_conn.ikeme.mediated_by = push_string(&msg, conn->me_mediated_by);
        msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid);
        msg.add_conn.reqid = conn->reqid;
+       msg.add_conn.mark.value = conn->mark_value;
+       msg.add_conn.mark.mask = conn->mark_mask;
 
        starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left);
        starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
index b20dd22..e33737b 100644 (file)
@@ -256,6 +256,10 @@ struct stroke_msg_t {
                                char *mediated_by;
                                char *peerid;
                        } ikeme;
+                       struct {
+                               u_int32_t value;
+                               u_int32_t mask;
+                       } mark;
                        stroke_end_t me, other;
                } add_conn;