]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-interface: add an exchange initiator parameter to add_sa()
authorMartin Willi <martin@revosec.ch>
Wed, 8 May 2013 08:31:06 +0000 (10:31 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 11 Jun 2013 13:58:48 +0000 (15:58 +0200)
This new flag gives the kernel-interface a hint how it should priorize the
use of newly installed SAs during rekeying.

Consider the following rekey procedure in IKEv2:

Initiator  ---    Responder

I1 -------CREATE-------> R1
I2 <------CREATE--------
   -------DELETE-------> R2
I3 <------DELETE--------

SAs are always handled as pairs, the following happens at the SA level:

  * Initiator starts the exchange at I1
  * Responder installs new SA pair at R1
  * Initiator installs new SA pair at I2
  * Responder removes old SA pair at R2
  * Initiator removes old SA pair at I3

This makes sure SAs get installed/removed overlapping during rekeying. However,
to avoid any packet loss, it is crucial that the new outbound SA gets
activated at the correct position:

  * as exchange initiator, in I2
  * as exchange responder, in R2

This should guarantee that we don't use the new outbound SA before the peer
could install its corresponding inbound SA.

The new parameter allows the kernel backend to install the new SA with
appropriate priorities, i.e. it should:

  * as exchange inititator, have the new outbound SA installed with higher
    priority than the old SA
  * as exchange responder, have the new outbound SA installed with lower
    priority than the old SA

While we could split up the SA installation at the responder, this approach
has another advantage: it allows the kernel backend to switch SAs based on
other criteria, for example when receiving traffic on the new inbound SA.

14 files changed:
src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c
src/libcharon/plugins/load_tester/load_tester_ipsec.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/libhydra/kernel/kernel_interface.c
src/libhydra/kernel/kernel_interface.h
src/libhydra/kernel/kernel_ipsec.h
src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libipsec/ipsec_sa_mgr.c

index a276166e2f3b8beb06a245b58852e9c9fd3c8bf0..1d070fd5fc08fd9ee7bdc6274e9a8f3027d8043a 100644 (file)
@@ -92,7 +92,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, 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 esn, bool inbound,
+       u_int16_t cpi, bool _initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
        esa_info_t esa;
@@ -120,6 +120,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        }
 
        /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */
+       /* TODO: does the new _initiator parameter have the same meaning? */
        initiator = esa.is_encr_r && inbound;
        if (initiator)
        {
index c37ca26ab00ac60389ffdb1d56cf31fefb7caeb2..d58e8d5370939134762e30f56f247d4f5b97898a 100644 (file)
@@ -65,7 +65,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, 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 esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
index 49e35c4ca263b8675c6c1bd1de1b5b659bf1bbfd..bf08d2c9cd53158e85789c25558e42476bd9c213 100644 (file)
@@ -54,7 +54,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, 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 esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        return SUCCESS;
index a14b039497191e2380acfd93e1b7faf4e589088e..f50e32ff1ad7444a430452a65b6f7df773b7936d 100644 (file)
@@ -607,9 +607,9 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t,
 }
 
 METHOD(child_sa_t, install, status_t,
-          private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
-          u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts,
-          linked_list_t *other_ts)
+       private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
+       u_int16_t cpi, bool initiator, bool inbound, bool tfcv3,
+       linked_list_t *my_ts, linked_list_t *other_ts)
 {
        u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
        u_int16_t esn = NO_EXT_SEQ_NUMBERS;
@@ -703,7 +703,8 @@ METHOD(child_sa_t, install, status_t,
                                src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
                                inbound ? this->mark_in : this->mark_out, tfc,
                                lifetime, enc_alg, encr, int_alg, integ, this->mode,
-                               this->ipcomp, cpi, this->encap, esn, update, src_ts, dst_ts);
+                               this->ipcomp, cpi, initiator, this->encap, esn, update,
+                               src_ts, dst_ts);
 
        free(lifetime);
 
index 44511edf838c12e69c44e1a787b05a844d557b20..aa44dbfadc690f84fb8c7ea7208ce619e5e36b6d 100644 (file)
@@ -321,6 +321,7 @@ struct child_sa_t {
         * @param integ         integrity key
         * @param spi           SPI to use, allocated for inbound
         * @param cpi           CPI to use, allocated for outbound
+        * @param initiator     TRUE if initiator of exchange resulting in this SA
         * @param inbound       TRUE to install an inbound SA, FALSE for outbound
         * @param tfcv3         TRUE if peer supports ESPv3 TFC
         * @param my_ts         negotiated local traffic selector list
@@ -328,7 +329,8 @@ struct child_sa_t {
         * @return                      SUCCESS or FAILED
         */
        status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
-                                               u_int32_t spi, u_int16_t cpi, bool inbound, bool tfcv3,
+                                               u_int32_t spi, u_int16_t cpi,
+                                               bool initiator, bool inbound, bool tfcv3,
                                                linked_list_t *my_ts, linked_list_t *other_ts);
        /**
         * Install the policies using some traffic selectors.
index 47c844e5f65f9b9087ced631f2b9dd8ba998680e..52ea34b1a25fe14f34e75ae2ec823681327edbce 100644 (file)
@@ -306,17 +306,21 @@ static bool install(private_quick_mode_t *this)
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
-                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, TRUE, FALSE, tsi, tsr);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, FALSE, FALSE, tsi, tsr);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
-                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, TRUE, FALSE, tsr, tsi);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, FALSE, FALSE, tsr, tsi);
                }
        }
        chunk_clear(&integ_i);
index d1116d8a1bebf21b22f72f4adf8d16caaeb13e10..e4d762ad703c72cdd13c843a736a58b31c4f4936 100644 (file)
@@ -526,20 +526,20 @@ static status_t select_and_install(private_child_create_t *this,
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa,
-                                                       encr_r, integ_r, this->my_spi, this->my_cpi,
+                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                       this->my_spi, this->my_cpi, this->initiator,
                                                        TRUE, this->tfcv3, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa,
-                                                       encr_i, integ_i, this->other_spi, this->other_cpi,
+                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                       this->other_spi, this->other_cpi, this->initiator,
                                                        FALSE, this->tfcv3, my_ts, other_ts);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa,
-                                                       encr_i, integ_i, this->my_spi, this->my_cpi,
+                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                       this->my_spi, this->my_cpi, this->initiator,
                                                        TRUE, this->tfcv3, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa,
-                                                       encr_r, integ_r, this->other_spi, this->other_cpi,
+                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                       this->other_spi, this->other_cpi, this->initiator,
                                                        FALSE, this->tfcv3, my_ts, other_ts);
                }
        }
index d81fa33c75e6e1936590624b87121b45ba802b12..be247df30de7b68e6ed7ce4536edabd266c7aa39 100644 (file)
@@ -180,7 +180,7 @@ METHOD(kernel_interface_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, 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 esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        if (!this->ipsec)
@@ -189,7 +189,7 @@ METHOD(kernel_interface_t, add_sa, status_t,
        }
        return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
                        mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
-                       ipcomp, cpi, encap, esn, inbound, src_ts, dst_ts);
+                       ipcomp, cpi, initiator, encap, esn, inbound, src_ts, dst_ts);
 }
 
 METHOD(kernel_interface_t, update_sa, status_t,
index b333cae99614a9e8d8587b9c3ab45846f4d24131..ab2b3825689077e5275ba7f66ce78bcceb641d07 100644 (file)
@@ -143,6 +143,7 @@ struct kernel_interface_t {
         * @param mode                  mode of the SA (tunnel, transport)
         * @param ipcomp                IPComp transform to use
         * @param cpi                   CPI for IPComp
+        * @param initiator             TRUE if initiator of the exchange creating this SA
         * @param encap                 enable UDP encapsulation for NAT traversal
         * @param esn                   TRUE to use Extended Sequence Numbers
         * @param inbound               TRUE if this is an inbound SA
@@ -157,7 +158,7 @@ struct kernel_interface_t {
                                                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 esn, bool inbound,
+                                               bool initiator, bool encap, bool esn, bool inbound,
                                                traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
        /**
index f61f3c3aa77bfa49b4ad4257b0f8701691e71415..413e5920f26a92217f68827624aeaf86f9a4dd2f 100644 (file)
@@ -101,6 +101,7 @@ struct kernel_ipsec_t {
         * @param mode                  mode of the SA (tunnel, transport)
         * @param ipcomp                IPComp transform to use
         * @param cpi                   CPI for IPComp
+        * @param initiator             TRUE if initiator of the exchange creating this SA
         * @param encap                 enable UDP encapsulation for NAT traversal
         * @param esn                   TRUE to use Extended Sequence Numbers
         * @param inbound               TRUE if this is an inbound SA
@@ -115,7 +116,7 @@ struct kernel_ipsec_t {
                                                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 esn, bool inbound,
+                                               bool initiator, bool encap, bool esn, bool inbound,
                                                traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
        /**
index 32bea738383a9202133d19a80dc510960b39e852..5ca5879ff83448550fb978a1cab5cc448d4cdeda 100644 (file)
@@ -1682,8 +1682,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
        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 esn, bool inbound,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       u_int16_t ipcomp, u_int16_t cpi, bool initiator, bool encap, bool esn,
+       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
index bfb8fa8891c224e7e27002066c472bfd7c5b4f7b..a208045078b9244b68c250b4529e05eb129b5c3b 100644 (file)
@@ -1170,7 +1170,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, 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 esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
        netlink_buf_t request;
@@ -1187,7 +1187,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
                add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
                           tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-                          chunk_empty, mode, ipcomp, 0, FALSE, FALSE, inbound, NULL, NULL);
+                          chunk_empty, mode, ipcomp, 0, initiator, FALSE, FALSE, inbound,
+                          NULL, NULL);
                ipcomp = IPCOMP_NONE;
                /* use transport mode ESP SA, IPComp uses tunnel mode */
                mode = MODE_TRANSPORT;
index ecab2827a8056e8bbc64fe5d2c7c89c17bb3c8ca..f00210b85120f3d8f29552eb9c8194ef4df68e3f 100644 (file)
@@ -1523,8 +1523,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
        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 esn, bool inbound,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       u_int16_t ipcomp, u_int16_t cpi, bool initiator, bool encap, bool esn,
+       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
index 28748971dbb23171b87701a6542d364f2c2a6f4c..1f5d5a3b3db760122c6959a835539e7ae43f5541 100644 (file)
@@ -438,7 +438,7 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid,     mark_t mark, u_int32_t tfc,
        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 esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        ipsec_sa_entry_t *entry;