From 44476c6b271bdebb7458590398b5f140c9a7d353 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 11 Feb 2020 13:53:32 +0000 Subject: [PATCH] ikev2: Configure a profile with an existing interface Type: feature ... rather than always creating a new interface. Change-Id: If8a22ad5a8a3a4e511bea7cab7d8bbf7e6af9433 Signed-off-by: Neale Ranns --- src/plugins/ikev2/ikev2.api | 16 ++++++ src/plugins/ikev2/ikev2.c | 107 +++++++++++++++++++++++++++++------------ src/plugins/ikev2/ikev2.h | 2 + src/plugins/ikev2/ikev2_api.c | 27 +++++++++++ src/plugins/ikev2/ikev2_cli.c | 9 ++++ src/plugins/ikev2/ikev2_priv.h | 4 ++ src/plugins/ikev2/ikev2_test.c | 6 +++ 7 files changed, 141 insertions(+), 30 deletions(-) diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api index 29d0c7bfc0b..aa9f1b3e554 100644 --- a/src/plugins/ikev2/ikev2.api +++ b/src/plugins/ikev2/ikev2.api @@ -146,6 +146,22 @@ autoreply define ikev2_set_local_key option vat_help = "file "; }; +/** \brief IKEv2: Set the tunnel interface which will be protected by IKE + If this API is not called, a new tunnel will be created + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param name - IKEv2 profile name + @param sw_if_index - Of an existing tunnel +*/ +autoreply define ikev2_set_tunnel_interface +{ + u32 client_index; + u32 context; + string name[64]; + + vl_api_interface_index_t sw_if_index; +}; + /** \brief IKEv2: Set IKEv2 responder interface and IP address @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index ee0b11ea4b0..4bbe5549c75 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -389,6 +389,8 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai) sa->i_id.type = sai->i_id.type; sa->profile_index = sai->profile_index; sa->is_profile_index_set = sai->is_profile_index_set; + sa->tun_itf = sai->tun_itf; + sa->is_tun_itf_set = sai->is_tun_itf_set; sa->i_id.data = _(sai->i_id.data); sa->i_auth.method = sai->i_auth.method; sa->i_auth.hex = sai->i_auth.hex; @@ -1478,6 +1480,7 @@ ikev2_mk_remote_sa_id (u32 sai, u32 ci, u32 ti) typedef struct { + u32 sw_if_index; u32 salt_local; u32 salt_remote; u32 local_sa_id; @@ -1497,21 +1500,26 @@ 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, - TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0, - TUNNEL_MODE_P2P, &sw_if_index); + int rv = 0; - if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS) + if (~0 == a->sw_if_index) { - p = hash_get (km->sw_if_indices, sw_if_index); - if (p) - /* interface is managed by IKE; proceed with updating SAs */ - rv = 0; + /* no tunnel associated with the SA/profile - create a new one */ + rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0, + &a->local_ip, &a->remote_ip, 0, + TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0, + TUNNEL_MODE_P2P, &sw_if_index); + + if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS) + { + if (hash_get (km->sw_if_indices, sw_if_index)) + /* interface is managed by IKE; proceed with updating SAs */ + rv = 0; + } + hash_set1 (km->sw_if_indices, sw_if_index); } + else + sw_if_index = a->sw_if_index; if (rv) { @@ -1537,7 +1545,6 @@ 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 @@ -1739,6 +1746,7 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, child->remote_sa_id = a.remote_sa_id = ikev2_mk_remote_sa_id (sa_index, child_index, thread_index); + a.sw_if_index = (sa->is_tun_itf_set ? sa->tun_itf : ~0); vl_api_rpc_call_main_thread (ikev2_add_tunnel_from_main, (u8 *) & a, sizeof (a)); @@ -1751,32 +1759,48 @@ typedef struct ip46_address_t remote_ip; u32 remote_sa_id; u32 local_sa_id; + u32 sw_if_index; } ikev2_del_ipsec_tunnel_args_t; 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, - .dst = a->remote_ip, - .transport = IPIP_TRANSPORT_IP4, - .fib_index = 0, - }; - ipip_tunnel_t *ipip; - /* *INDENT-ON* */ - - ipip = ipip_tunnel_db_find (&key); + ipip_tunnel_t *ipip = NULL; + u32 sw_if_index; - if (ipip) + if (~0 == a->sw_if_index) { - 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); - ipip_del_tunnel (ipip->sw_if_index); + /* *INDENT-OFF* */ + ipip_tunnel_key_t key = { + .src = a->local_ip, + .dst = a->remote_ip, + .transport = IPIP_TRANSPORT_IP4, + .fib_index = 0, + }; + /* *INDENT-ON* */ + + ipip = ipip_tunnel_db_find (&key); + + if (ipip) + { + sw_if_index = ipip->sw_if_index; + hash_unset (km->sw_if_indices, ipip->sw_if_index); + } + else + sw_if_index = ~0; } + else + sw_if_index = a->sw_if_index; + + if (~0 != sw_if_index) + ipsec_tun_protect_del (sw_if_index); + + ipsec_sa_unlock_id (a->remote_sa_id); + ipsec_sa_unlock_id (a->local_sa_id); + + if (ipip) + ipip_del_tunnel (ipip->sw_if_index); } static int @@ -1800,6 +1824,7 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, a.remote_sa_id = child->remote_sa_id; a.local_sa_id = child->local_sa_id; + a.sw_if_index = (sa->is_tun_itf_set ? sa->tun_itf : ~0); vl_api_rpc_call_main_thread (ikev2_del_tunnel_from_main, (u8 *) & a, sizeof (a)); @@ -3044,6 +3069,26 @@ ikev2_set_profile_esp_transforms (vlib_main_t * vm, u8 * name, return 0; } +clib_error_t * +ikev2_set_profile_tunnel_interface (vlib_main_t * vm, + u8 * name, u32 sw_if_index) +{ + ikev2_profile_t *p; + clib_error_t *r; + + p = ikev2_profile_index_by_name (name); + + if (!p) + { + r = clib_error_return (0, "unknown profile %v", name); + return r; + } + + p->tun_itf = sw_if_index; + + return 0; +} + clib_error_t * ikev2_set_profile_sa_lifetime (vlib_main_t * vm, u8 * name, u64 lifetime, u32 jitter, u32 handover, @@ -3127,6 +3172,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) sa.profile_index = km->profiles - p; sa.is_profile_index_set = 1; sa.state = IKEV2_STATE_SA_INIT; + sa.tun_itf = p->tun_itf; + sa.is_tun_itf_set = 1; ikev2_generate_sa_init_data (&sa); ikev2_payload_add_ke (chain, sa.dh_group, sa.i_dh_data); ikev2_payload_add_nonce (chain, sa.i_nonce); diff --git a/src/plugins/ikev2/ikev2.h b/src/plugins/ikev2/ikev2.h index fd669b3850f..d4222d28c2e 100644 --- a/src/plugins/ikev2/ikev2.h +++ b/src/plugins/ikev2/ikev2.h @@ -392,6 +392,8 @@ clib_error_t *ikev2_set_profile_esp_transforms (vlib_main_t * vm, u8 * name, clib_error_t *ikev2_set_profile_sa_lifetime (vlib_main_t * vm, u8 * name, u64 lifetime, u32 jitter, 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_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); diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c index 365e6e8932f..ae1672c1da4 100644 --- a/src/plugins/ikev2/ikev2_api.c +++ b/src/plugins/ikev2/ikev2_api.c @@ -289,6 +289,33 @@ vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp) REPLY_MACRO (VL_API_IKEV2_SET_SA_LIFETIME_REPLY); } +static void + vl_api_ikev2_set_tunnel_interface_t_handler + (vl_api_ikev2_set_tunnel_interface_t * mp) +{ + vl_api_ikev2_set_tunnel_interface_reply_t *rmp; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + +#if WITH_LIBSSL > 0 + u8 *tmp = format (0, "%s", mp->name); + clib_error_t *error; + + error = ikev2_set_profile_tunnel_interface (vlib_get_main (), tmp, + ntohl (mp->sw_if_index)); + + if (error) + rv = VNET_API_ERROR_UNSPECIFIED; + vec_free (tmp); +#else + rv = VNET_API_ERROR_UNIMPLEMENTED; +#endif + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_IKEV2_SET_TUNNEL_INTERFACE_REPLY); +} + static void vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp) { diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c index 2ca1a5ccfc6..8b9a6cdf8f1 100644 --- a/src/plugins/ikev2/ikev2_cli.c +++ b/src/plugins/ikev2/ikev2_cli.c @@ -184,6 +184,7 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, ip4_address_t ip4; ip4_address_t end_addr; u32 responder_sw_if_index = (u32) ~ 0; + u32 tun_sw_if_index = (u32) ~ 0; ip4_address_t responder_ip4; ikev2_transform_encr_type_t crypto_alg; ikev2_transform_integ_type_t integ_alg; @@ -326,6 +327,13 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, responder_ip4); goto done; } + else if (unformat (line_input, "set %U tunnel %U", + unformat_token, valid_chars, &name, + unformat_vnet_sw_interface, vnm, &tun_sw_if_index)) + { + r = ikev2_set_profile_tunnel_interface (vm, name, tun_sw_if_index); + goto done; + } else if (unformat (line_input, @@ -384,6 +392,7 @@ VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = { "ikev2 profile set auth [rsa-sig|shared-key-mic] [cert-file|string|hex]" " \n" "ikev2 profile set id \n" + "ikev2 profile set tunnel \n" "ikev2 profile set traffic-selector ip-range " " - port-range - " "protocol \n" diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h index aa85b84727a..5afd065b55f 100644 --- a/src/plugins/ikev2/ikev2_priv.h +++ b/src/plugins/ikev2/ikev2_priv.h @@ -358,6 +358,8 @@ typedef struct u64 lifetime_maxdata; u32 lifetime_jitter; u32 handover; + + u32 tun_itf; } ikev2_profile_t; typedef struct @@ -418,6 +420,8 @@ typedef struct u32 last_init_msg_id; u8 is_profile_index_set; u32 profile_index; + u8 is_tun_itf_set; + u32 tun_itf; ikev2_child_sa_t *childs; } ikev2_sa_t; diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c index 69d223f0c48..cd9445d2f38 100644 --- a/src/plugins/ikev2/ikev2_test.c +++ b/src/plugins/ikev2/ikev2_test.c @@ -406,6 +406,12 @@ api_ikev2_set_local_key (vat_main_t * vam) return ret; } +static int +api_ikev2_set_tunnel_interface (vat_main_t * vam) +{ + return (0); +} + static int api_ikev2_set_responder (vat_main_t * vam) { -- 2.16.6