ikev2: make UDP encap flag configurable 46/25546/3
authorFilip Tehlar <ftehlar@cisco.com>
Tue, 25 Feb 2020 09:27:10 +0000 (09:27 +0000)
committerDamjan Marion <dmarion@me.com>
Mon, 2 Mar 2020 09:10:57 +0000 (09:10 +0000)
Type: improvement

Change-Id: I081dec2dc0c2bd0845dd4638b7b2f12806594112
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/ikev2/ikev2.api
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2.h
src/plugins/ikev2/ikev2_api.c
src/plugins/ikev2/ikev2_cli.c
src/plugins/ikev2/ikev2_priv.h
src/plugins/ikev2/ikev2_test.c

index aa9f1b3..c872c6f 100644 (file)
@@ -317,6 +317,19 @@ autoreply define ikev2_initiate_rekey_child_sa
   option vat_help = "<ispi>";
 };
 
+/** \brief IKEv2: Set UDP encapsulation
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param name - IKEv2 profile name
+*/
+autoreply define ikev2_profile_set_udp_encap
+{
+  u32 client_index;
+  u32 context;
+
+  string name[64];
+};
+
 /*
  * Local Variables:
  * eval: (c-set-style "gnu")
index b0ed4f2..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);
   }));
@@ -1608,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);
@@ -3151,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,
@@ -3235,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);
index d4222d2..c73df15 100644 (file)
@@ -394,6 +394,7 @@ clib_error_t *ikev2_set_profile_sa_lifetime (vlib_main_t * vm, u8 * name,
                                             u32 handover, u64 maxdata);
 clib_error_t *ikev2_set_profile_tunnel_interface (vlib_main_t * vm, u8 * name,
                                                  u32 sw_if_index);
+clib_error_t *ikev2_set_profile_udp_encap (vlib_main_t * vm, u8 * name);
 clib_error_t *ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name);
 clib_error_t *ikev2_initiate_delete_child_sa (vlib_main_t * vm, u32 ispi);
 clib_error_t *ikev2_initiate_delete_ike_sa (vlib_main_t * vm, u64 ispi);
index bfcfa64..f846bfa 100644 (file)
@@ -133,6 +133,28 @@ vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
 }
 
+static void
+  vl_api_ikev2_profile_set_udp_encap_t_handler
+  (vl_api_ikev2_profile_set_udp_encap_t * mp)
+{
+  vl_api_ikev2_profile_set_udp_encap_reply_t *rmp;
+  int rv = 0;
+
+#if WITH_LIBSSL > 0
+  vlib_main_t *vm = vlib_get_main ();
+  clib_error_t *error;
+  u8 *tmp = format (0, "%s", mp->name);
+  error = ikev2_set_profile_udp_encap (vm, tmp);
+  vec_free (tmp);
+  if (error)
+    rv = VNET_API_ERROR_UNSPECIFIED;
+#else
+  rv = VNET_API_ERROR_UNIMPLEMENTED;
+#endif
+
+  REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_UDP_ENCAP);
+}
+
 static void
 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
 {
index a48828d..6b9876b 100644 (file)
@@ -370,6 +370,12 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm,
            ikev2_set_profile_sa_lifetime (vm, name, tmp4, tmp1, tmp2, tmp5);
          goto done;
        }
+      else if (unformat (line_input, "set %U udp-encap",
+                        unformat_token, valid_chars, &name))
+       {
+         r = ikev2_set_profile_udp_encap (vm, name);
+         goto done;
+       }
       else
        break;
     }
@@ -393,6 +399,7 @@ VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = {
     " <data>\n"
     "ikev2 profile set <id> id <local|remote> <type> <data>\n"
     "ikev2 profile set <id> tunnel <interface>\n"
+    "ikev2 profile set <id> udp-encap\n"
     "ikev2 profile set <id> traffic-selector <local|remote> ip-range "
     "<start-addr> - <end-addr> port-range <start-port> - <end-port> "
     "protocol <protocol-number>\n"
@@ -477,6 +484,8 @@ show_ikev2_profile_command_fn (vlib_main_t * vm,
     if (~0 != p->tun_itf)
       vlib_cli_output(vm, "  protected tunnel %U",
                       format_vnet_sw_if_index_name, vnet_get_main(), p->tun_itf);
+    if (p->udp_encap)
+      vlib_cli_output(vm, "  udp-encap");
   }));
   /* *INDENT-ON* */
 
index 8fddb7d..7609166 100644 (file)
@@ -360,6 +360,7 @@ typedef struct
   u32 handover;
 
   u32 tun_itf;
+  u8 udp_encap;
 } ikev2_profile_t;
 
 typedef struct
@@ -422,6 +423,7 @@ typedef struct
   u32 profile_index;
   u8 is_tun_itf_set;
   u32 tun_itf;
+  u8 udp_encap;
 
   f64 old_id_expiration;
   u32 current_remote_id_mask;
index cd9445d..9ff4bbc 100644 (file)
@@ -406,6 +406,49 @@ api_ikev2_set_local_key (vat_main_t * vam)
   return ret;
 }
 
+static int
+api_ikev2_profile_set_udp_encap (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_ikev2_set_responder_t *mp;
+  int ret;
+  u8 *name = 0;
+
+  const char *valid_chars = "a-zA-Z0-9_";
+
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "%U udp-encap", unformat_token, valid_chars, &name))
+       vec_add1 (name, 0);
+      else
+       {
+         errmsg ("parse error '%U'", format_unformat_error, i);
+         return -99;
+       }
+    }
+
+  if (!vec_len (name))
+    {
+      errmsg ("profile name must be specified");
+      return -99;
+    }
+
+  if (vec_len (name) > 64)
+    {
+      errmsg ("profile name too long");
+      return -99;
+    }
+
+  M (IKEV2_PROFILE_SET_UDP_ENCAP, mp);
+
+  clib_memcpy (mp->name, name, vec_len (name));
+  vec_free (name);
+
+  S (mp);
+  W (ret);
+  return ret;
+}
+
 static int
 api_ikev2_set_tunnel_interface (vat_main_t * vam)
 {