child-sa: Configure interface ID on SAs and policies
authorTobias Brunner <tobias@strongswan.org>
Tue, 12 Feb 2019 10:39:11 +0000 (11:39 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 3 Apr 2019 10:00:08 +0000 (12:00 +0200)
src/libcharon/plugins/ha/ha_dispatcher.c
src/libcharon/sa/child_sa.c
src/libcharon/sa/child_sa.h
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/tasks/child_create.c
src/libcharon/sa/trap_manager.c

index ab84531..11f3bd9 100644 (file)
@@ -746,7 +746,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
        child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
                                                           ike_sa->get_other_host(ike_sa), config, 0,
                                                           ike_sa->has_condition(ike_sa, COND_NAT_ANY),
-                                                          0, 0);
+                                                          0, 0, 0, 0);
        child_sa->set_mode(child_sa, mode);
        child_sa->set_protocol(child_sa, PROTO_ESP);
        child_sa->set_ipcomp(child_sa, ipcomp);
index f74d0c2..2ea6780 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2018 Tobias Brunner
+ * Copyright (C) 2006-2019 Tobias Brunner
  * Copyright (C) 2016 Andreas Steffen
  * Copyright (C) 2005-2008 Martin Willi
  * Copyright (C) 2006 Daniel Roethlisberger
@@ -154,6 +154,16 @@ struct private_child_sa_t {
        bool policies_fwd_out;
 
        /**
+        * Inbound interface ID
+        */
+       uint32_t if_id_in;
+
+       /**
+        * Outbound interface ID
+        */
+       uint32_t if_id_out;
+
+       /**
         * inbound mark used for this child_sa
         */
        mark_t mark_in;
@@ -539,6 +549,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
                                .spi = this->my_spi,
                                .proto = proto_ike2ip(this->protocol),
                                .mark = mark_in_sa(this),
+                               .if_id = this->if_id_in,
                        };
                        kernel_ipsec_query_sa_t query = {};
 
@@ -572,6 +583,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
                                .spi = this->other_spi,
                                .proto = proto_ike2ip(this->protocol),
                                .mark = this->mark_out,
+                               .if_id = this->if_id_out,
                        };
                        kernel_ipsec_query_sa_t query = {};
 
@@ -619,6 +631,7 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
                                .src_ts = other_ts,
                                .dst_ts = my_ts,
                                .mark = this->mark_in,
+                               .if_id = this->if_id_in,
                        };
                        kernel_ipsec_query_policy_t query = {};
 
@@ -644,6 +657,7 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
                                .src_ts = my_ts,
                                .dst_ts = other_ts,
                                .mark = this->mark_out,
+                               .if_id = this->if_id_out,
                                .interface = this->config->get_interface(this->config),
                        };
                        kernel_ipsec_query_policy_t query = {};
@@ -707,11 +721,13 @@ METHOD(child_sa_t, get_usestats, void,
 METHOD(child_sa_t, get_mark, mark_t,
        private_child_sa_t *this, bool inbound)
 {
-       if (inbound)
-       {
-               return this->mark_in;
-       }
-       return this->mark_out;
+       return inbound ? this->mark_in : this->mark_out;
+}
+
+METHOD(child_sa_t, get_if_id, uint32_t,
+       private_child_sa_t *this, bool inbound)
+{
+       return inbound ? this->if_id_in : this->if_id_out;
 }
 
 METHOD(child_sa_t, get_lifetime, time_t,
@@ -832,8 +848,8 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
        if (!this->reqid_allocated && !this->static_reqid)
        {
                status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
-                                                               this->mark_in, this->mark_out, 0, 0,
-                                                               &this->reqid);
+                                                               this->mark_in, this->mark_out, this->if_id_in,
+                                                               this->if_id_out, &this->reqid);
                if (status != SUCCESS)
                {
                        my_ts->destroy(my_ts);
@@ -873,6 +889,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
                .spi = spi,
                .proto = proto_ike2ip(this->protocol),
                .mark = inbound ? mark_in_sa(this) : this->mark_out,
+               .if_id = inbound ? this->if_id_in : this->if_id_out,
        };
        sa = (kernel_ipsec_add_sa_t){
                .reqid = this->reqid,
@@ -992,6 +1009,7 @@ static status_t install_policies_inbound(private_child_sa_t *this,
                .src_ts = other_ts,
                .dst_ts = my_ts,
                .mark = this->mark_in,
+               .if_id = this->if_id_in,
        };
        kernel_ipsec_manage_policy_t in_policy = {
                .type = type,
@@ -1026,6 +1044,7 @@ static status_t install_policies_outbound(private_child_sa_t *this,
                .src_ts = my_ts,
                .dst_ts = other_ts,
                .mark = this->mark_out,
+               .if_id = this->if_id_out,
                .interface = this->config->get_interface(this->config),
        };
        kernel_ipsec_manage_policy_t out_policy = {
@@ -1099,6 +1118,7 @@ static void del_policies_inbound(private_child_sa_t *this,
                .src_ts = other_ts,
                .dst_ts = my_ts,
                .mark = this->mark_in,
+               .if_id = this->if_id_in,
        };
        kernel_ipsec_manage_policy_t in_policy = {
                .type = type,
@@ -1132,6 +1152,7 @@ static void del_policies_outbound(private_child_sa_t *this,
                .src_ts = my_ts,
                .dst_ts = other_ts,
                .mark = this->mark_out,
+               .if_id = this->if_id_out,
                .interface = this->config->get_interface(this->config),
        };
        kernel_ipsec_manage_policy_t out_policy = {
@@ -1229,7 +1250,8 @@ METHOD(child_sa_t, install_policies, status_t,
                                                                        array_create_enumerator(this->other_ts));
                status = charon->kernel->alloc_reqid(
                                                        charon->kernel, my_ts_list, other_ts_list,
-                                                       this->mark_in, this->mark_out, 0, 0, &this->reqid);
+                                                       this->mark_in, this->mark_out, this->if_id_in,
+                                                       this->if_id_out, &this->reqid);
                my_ts_list->destroy(my_ts_list);
                other_ts_list->destroy(other_ts_list);
                if (status != SUCCESS)
@@ -1404,6 +1426,7 @@ METHOD(child_sa_t, remove_outbound, void,
                .spi = this->other_spi,
                .proto = proto_ike2ip(this->protocol),
                .mark = this->mark_out,
+               .if_id = this->if_id_out,
        };
        kernel_ipsec_del_sa_t sa = {
                .cpi = this->other_cpi,
@@ -1454,6 +1477,7 @@ static status_t update_sas(private_child_sa_t *this, host_t *me, host_t *other,
                        .spi = this->my_spi,
                        .proto = proto_ike2ip(this->protocol),
                        .mark = mark_in_sa(this),
+                       .if_id = this->if_id_in,
                };
                kernel_ipsec_update_sa_t sa = {
                        .cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
@@ -1478,6 +1502,7 @@ static status_t update_sas(private_child_sa_t *this, host_t *me, host_t *other,
                        .spi = this->other_spi,
                        .proto = proto_ike2ip(this->protocol),
                        .mark = this->mark_out,
+                       .if_id = this->if_id_out,
                };
                kernel_ipsec_update_sa_t sa = {
                        .cpi = this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
@@ -1680,6 +1705,7 @@ METHOD(child_sa_t, destroy, void,
                        .spi = this->my_spi,
                        .proto = proto_ike2ip(this->protocol),
                        .mark = mark_in_sa(this),
+                       .if_id = this->if_id_in,
                };
                kernel_ipsec_del_sa_t sa = {
                        .cpi = this->my_cpi,
@@ -1694,6 +1720,7 @@ METHOD(child_sa_t, destroy, void,
                        .spi = this->other_spi,
                        .proto = proto_ike2ip(this->protocol),
                        .mark = this->mark_out,
+                       .if_id = this->if_id_out,
                };
                kernel_ipsec_del_sa_t sa = {
                        .cpi = this->other_cpi,
@@ -1705,7 +1732,7 @@ METHOD(child_sa_t, destroy, void,
        {
                if (charon->kernel->release_reqid(charon->kernel,
                                                this->reqid, this->mark_in, this->mark_out,
-                                               0, 0) != SUCCESS)
+                                               this->if_id_in, this->if_id_out) != SUCCESS)
                {
                        DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
                }
@@ -1762,11 +1789,11 @@ static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local)
  */
 child_sa_t * child_sa_create(host_t *me, host_t* other,
                                                         child_cfg_t *config, uint32_t reqid, bool encap,
-                                                        u_int mark_in, u_int mark_out)
+                                                        uint32_t mark_in, uint32_t mark_out,
+                                                        uint32_t if_id_in, uint32_t if_id_out)
 {
        private_child_sa_t *this;
-       static refcount_t unique_id = 0, unique_mark = 0;
-       refcount_t mark = 0;
+       static refcount_t unique_id = 0, unique_mark = 0, unique_if_id = 0;
 
        INIT(this,
                .public = {
@@ -1789,6 +1816,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                        .get_installtime = _get_installtime,
                        .get_usestats = _get_usestats,
                        .get_mark = _get_mark,
+                       .get_if_id = _get_if_id,
                        .has_encap = _has_encap,
                        .get_ipcomp = _get_ipcomp,
                        .set_ipcomp = _set_ipcomp,
@@ -1824,6 +1852,8 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                .unique_id = ref_get(&unique_id),
                .mark_in = config->get_mark(config, TRUE),
                .mark_out = config->get_mark(config, FALSE),
+               .if_id_in = config->get_if_id(config, TRUE),
+               .if_id_out = config->get_if_id(config, FALSE),
                .install_time = time_monotonic(NULL),
                .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
        );
@@ -1839,14 +1869,21 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        {
                this->mark_out.value = mark_out;
        }
+       if (if_id_in)
+       {
+               this->if_id_in = if_id_in;
+       }
+       if (if_id_out)
+       {
+               this->if_id_out = if_id_out;
+       }
 
        if (MARK_IS_UNIQUE(this->mark_in.value) ||
                MARK_IS_UNIQUE(this->mark_out.value))
        {
-               bool unique_dir;
-
-               unique_dir = this->mark_in.value == MARK_UNIQUE_DIR ||
-                                        this->mark_out.value == MARK_UNIQUE_DIR;
+               refcount_t mark = 0;
+               bool unique_dir = this->mark_in.value == MARK_UNIQUE_DIR ||
+                                                 this->mark_out.value == MARK_UNIQUE_DIR;
 
                if (!unique_dir)
                {
@@ -1854,19 +1891,32 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                }
                if (MARK_IS_UNIQUE(this->mark_in.value))
                {
-                       if (unique_dir)
-                       {
-                               mark = ref_get(&unique_mark);
-                       }
-                       this->mark_in.value = mark;
+                       this->mark_in.value = unique_dir ? ref_get(&unique_mark) : mark;
                }
                if (MARK_IS_UNIQUE(this->mark_out.value))
                {
-                       if (unique_dir)
-                       {
-                               mark = ref_get(&unique_mark);
-                       }
-                       this->mark_out.value = mark;
+                       this->mark_out.value = unique_dir ? ref_get(&unique_mark) : mark;
+               }
+       }
+
+       if (IF_ID_IS_UNIQUE(this->if_id_in) ||
+               IF_ID_IS_UNIQUE(this->if_id_out))
+       {
+               refcount_t if_id = 0;
+               bool unique_dir = this->if_id_in == IF_ID_UNIQUE_DIR ||
+                                                 this->if_id_out == IF_ID_UNIQUE_DIR;
+
+               if (!unique_dir)
+               {
+                       if_id = ref_get(&unique_if_id);
+               }
+               if (IF_ID_IS_UNIQUE(this->if_id_in))
+               {
+                       this->if_id_in = unique_dir ? ref_get(&unique_if_id) : if_id;
+               }
+               if (IF_ID_IS_UNIQUE(this->if_id_out))
+               {
+                       this->if_id_out = unique_dir ? ref_get(&unique_if_id) : if_id;
                }
        }
 
index 183033f..483dd15 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2017 Tobias Brunner
+ * Copyright (C) 2006-2019 Tobias Brunner
  * Copyright (C) 2006-2008 Martin Willi
  * Copyright (C) 2006 Daniel Roethlisberger
  * HSR Hochschule fuer Technik Rapperswil
@@ -361,6 +361,14 @@ struct child_sa_t {
        mark_t (*get_mark)(child_sa_t *this, bool inbound);
 
        /**
+        * Get the interface ID used with this CHILD_SA.
+        *
+        * @param inbound               TRUE to get inbound ID, FALSE for outbound
+        * @return                              interface ID used with this CHILD_SA
+        */
+       uint32_t (*get_if_id)(child_sa_t *this, bool inbound);
+
+       /**
         * Create an enumerator over traffic selectors of one side.
         *
         * @param local         TRUE for own traffic selectors, FALSE for remote.
@@ -514,10 +522,13 @@ struct child_sa_t {
  * @param encap                                TRUE to enable UDP encapsulation (NAT traversal)
  * @param mark_in                      explicit inbound mark value to use, 0 for config
  * @param mark_out                     explicit outbound mark value to use, 0 for config
+ * @param if_id_in                     explicit inbound interface ID to use, 0 for config
+ * @param if_id_out                    explicit outbound interface ID to use, 0 for config
  * @return                                     child_sa_t object
  */
 child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
                                                         uint32_t reqid, bool encap,
-                                                        u_int mark_in, u_int mark_out);
+                                                        uint32_t mark_in, uint32_t mark_out,
+                                                        uint32_t if_id_in, uint32_t if_id_out);
 
 #endif /** CHILD_SA_H_ @}*/
index b0a42b8..876b99e 100644 (file)
@@ -845,7 +845,8 @@ METHOD(task_t, build_i, status_t,
                                                                        this->ike_sa->get_my_host(this->ike_sa),
                                                                        this->ike_sa->get_other_host(this->ike_sa),
                                                                        this->config, this->reqid, this->udp,
-                                                                       this->mark_in, this->mark_out);
+                                                                       this->mark_in, this->mark_out,
+                                                                       0, 0);
 
                        if (this->udp && this->mode == MODE_TRANSPORT)
                        {
@@ -1185,7 +1186,8 @@ METHOD(task_t, process_r, status_t,
                                                                        this->ike_sa->get_my_host(this->ike_sa),
                                                                        this->ike_sa->get_other_host(this->ike_sa),
                                                                        this->config, this->reqid, this->udp,
-                                                                       this->mark_in, this->mark_out);
+                                                                       this->mark_in, this->mark_out,
+                                                                       0, 0);
 
                        tsi = linked_list_create_with_items(this->tsi, NULL);
                        tsr = linked_list_create_with_items(this->tsr, NULL);
index ce61ef9..1f93be4 100644 (file)
@@ -1110,7 +1110,7 @@ METHOD(task_t, build_i, status_t,
        this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
                        this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
-                       this->mark_in, this->mark_out);
+                       this->mark_in, this->mark_out, 0, 0);
 
        if (this->reqid)
        {
@@ -1395,7 +1395,7 @@ METHOD(task_t, build_r, status_t,
        this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
                        this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
-                       this->mark_in, this->mark_out);
+                       this->mark_in, this->mark_out, 0, 0);
 
        if (this->ipcomp_received != IPCOMP_NONE)
        {
index c35b8c0..7acbb28 100644 (file)
@@ -293,7 +293,7 @@ METHOD(trap_manager_t, install, bool,
        this->lock->unlock(this->lock);
 
        /* create and route CHILD_SA */
-       child_sa = child_sa_create(me, other, child, 0, FALSE, 0, 0);
+       child_sa = child_sa_create(me, other, child, 0, FALSE, 0, 0, 0, 0);
 
        list = linked_list_create_with_items(me, NULL);
        my_ts = child->get_traffic_selectors(child, TRUE, NULL, list, FALSE);