ikev2: fix crash during SA rekey 16/23816/4
authorFilip Tehlar <ftehlar@cisco.com>
Sat, 30 Nov 2019 20:49:40 +0000 (20:49 +0000)
committerDamjan Marion <dmarion@me.com>
Thu, 12 Dec 2019 23:01:10 +0000 (23:01 +0000)
Type: fix

Change-Id: Ib00ab9b2f28c0f4d85e96bf95697f61b8e415f37
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2_priv.h
src/vnet/ipip/ipip.c

index a260bb1..b94311b 100644 (file)
@@ -1538,13 +1538,31 @@ typedef struct
 static void
 ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
 {
+  ikev2_main_t *km = &ikev2_main;
   u32 sw_if_index;
   int rv;
+  uword *p = 0;
 
   rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
                        &a->local_ip, &a->remote_ip, 0,
                        IPIP_TUNNEL_FLAG_NONE, IP_DSCP_CS0, &sw_if_index);
 
+  if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS)
+    {
+      p = hash_get (km->sw_if_indices, sw_if_index);
+      if (p)
+       /* interface is managed by IKE; proceed with updating SAs */
+       rv = 0;
+    }
+
+  if (rv)
+    {
+      clib_warning ("installing ipip tunnel failed! loc:%U rem:%U",
+                   format_ip4_address, &a->local_ip,
+                   format_ip4_address, &a->remote_ip);
+      return;
+    }
+
   rv |= ipsec_sa_add_and_lock (a->local_sa_id,
                               a->local_spi,
                               IPSEC_PROTOCOL_ESP, a->encr_type,
@@ -1561,6 +1579,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
   u32 *sas_in = NULL;
   vec_add1 (sas_in, a->remote_sa_id);
   rv |= ipsec_tun_protect_update (sw_if_index, a->local_sa_id, sas_in);
+  hash_set1 (km->sw_if_indices, sw_if_index);
 }
 
 static int
@@ -1779,6 +1798,7 @@ typedef struct
 static void
 ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a)
 {
+  ikev2_main_t *km = &ikev2_main;
   /* *INDENT-OFF* */
   ipip_tunnel_key_t key = {
     .src = a->local_ip,
@@ -1793,6 +1813,7 @@ ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a)
 
   if (ipip)
     {
+      hash_unset (km->sw_if_indices, ipip->sw_if_index);
       ipsec_tun_protect_del (ipip->sw_if_index);
       ipsec_sa_unlock_id (a->remote_sa_id);
       ipsec_sa_unlock_id (a->local_sa_id);
@@ -2535,6 +2556,8 @@ ikev2_node_fn (vlib_main_t * vm,
                    {
                      if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
                        {
+                         if (sa0->childs)
+                           vec_free (sa0->childs);
                          ikev2_child_sa_t *child;
                          vec_add2 (sa0->childs, child, 1);
                          child->r_proposals = sa0->rekey[0].r_proposal;
@@ -3480,6 +3503,7 @@ ikev2_init (vlib_main_t * vm)
     }
 
   km->sa_by_ispi = hash_create (0, sizeof (uword));
+  km->sw_if_indices = hash_create (0, 0);
 
   udp_register_dst_port (vm, 500, ikev2_node.index, 1);
 
index c1bc41c..630ba1b 100644 (file)
@@ -297,6 +297,9 @@ typedef struct
 
   ikev2_main_per_thread_data_t *per_thread_data;
 
+  /* interface indices managed by IKE */
+  uword *sw_if_indices;
+
   /* API message ID base */
   u16 msg_id_base;
 } ikev2_main_t;
index fc71b5b..d68e815 100644 (file)
@@ -430,7 +430,11 @@ ipip_add_tunnel (ipip_transport_t transport,
   };
   t = ipip_tunnel_db_find (&key);
   if (t)
-    return VNET_API_ERROR_IF_ALREADY_EXISTS;
+    {
+      if (sw_if_indexp)
+       sw_if_indexp[0] = t->sw_if_index;
+      return VNET_API_ERROR_IF_ALREADY_EXISTS;
+    }
 
   pool_get_aligned (gm->tunnels, t, CLIB_CACHE_LINE_BYTES);
   clib_memset (t, 0, sizeof (*t));