ikev2: make UDP encap flag configurable
[vpp.git] / src / plugins / ikev2 / ikev2.c
index dfa697f..db68135 100644 (file)
@@ -398,6 +398,7 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai)
   sa->i_auth.key = _(sai->i_auth.key);
   sa->last_sa_init_req_packet_data = _(sai->last_sa_init_req_packet_data);
   sa->childs = _(sai->childs);
+  sa->udp_encap = sai->udp_encap;
 #undef _
 
 
@@ -1372,6 +1373,9 @@ ikev2_sa_auth (ikev2_sa_t * sa)
           }
       }
 
+    if (sel_p)
+      sa->udp_encap = sel_p->udp_encap;
+
     vec_free(auth);
     vec_free(psk);
   }));
@@ -1541,6 +1545,8 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
   vec_add1 (sas_in, a->remote_sa_id);
   if (a->is_rekey)
     {
+      ipsec_tun_protect_del (sw_if_index, NULL);
+
       /* replace local SA immediately */
       ipsec_sa_unlock_id (a->local_sa_id);
 
@@ -1606,6 +1612,9 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm,
     }
 
   a.flags = IPSEC_SA_FLAG_USE_ANTI_REPLAY;
+  a.flags |= IPSEC_SA_FLAG_IS_TUNNEL;
+  if (sa->udp_encap)
+    a.flags |= IPSEC_SA_FLAG_UDP_ENCAP;
   a.is_rekey = is_rekey;
 
   tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_ESN);
@@ -3149,6 +3158,22 @@ ikev2_set_profile_tunnel_interface (vlib_main_t * vm,
   return 0;
 }
 
+clib_error_t *
+ikev2_set_profile_udp_encap (vlib_main_t * vm, u8 * name)
+{
+  ikev2_profile_t *p = ikev2_profile_index_by_name (name);
+  clib_error_t *r;
+
+  if (!p)
+    {
+      r = clib_error_return (0, "unknown profile %v", name);
+      return r;
+    }
+
+  p->udp_encap = 1;
+  return 0;
+}
+
 clib_error_t *
 ikev2_set_profile_sa_lifetime (vlib_main_t * vm, u8 * name,
                               u64 lifetime, u32 jitter, u32 handover,
@@ -3233,6 +3258,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
     sa.is_profile_index_set = 1;
     sa.state = IKEV2_STATE_SA_INIT;
     sa.tun_itf = p->tun_itf;
+    sa.udp_encap = p->udp_encap;
     sa.is_tun_itf_set = 1;
     sa.initial_contact = 1;
     ikev2_generate_sa_init_data (&sa);
@@ -3742,6 +3768,31 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
     }
 }
 
+static void
+ikev2_process_pending_sa_init (ikev2_main_t * km)
+{
+  u32 sai;
+  u64 ispi;
+  ikev2_sa_t *sa;
+
+  /* *INDENT-OFF* */
+  hash_foreach (ispi, sai, km->sa_by_ispi,
+  ({
+    sa = pool_elt_at_index (km->sais, sai);
+    u32 bi0;
+    if (vlib_buffer_alloc (km->vlib_main, &bi0, 1) != 1)
+      return;
+
+    vlib_buffer_t * b = vlib_get_buffer (km->vlib_main, bi0);
+    clib_memcpy_fast (vlib_buffer_get_current (b),
+        sa->last_sa_init_req_packet_data,
+        vec_len (sa->last_sa_init_req_packet_data));
+    ikev2_send_ike (km->vlib_main, &sa->iaddr, &sa->raddr, bi0,
+        vec_len (sa->last_sa_init_req_packet_data));
+  }));
+  /* *INDENT-ON* */
+}
+
 static vlib_node_registration_t ikev2_mngr_process_node;
 
 static uword
@@ -3790,6 +3841,8 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
       }));
       /* *INDENT-ON* */
 
+      ikev2_process_pending_sa_init (km);
+
       if (req_sent)
        {
          vlib_process_wait_for_event_or_clock (vm, 5);