From 6a9bd81886772b5ffeb367736fb83bf95f37435f Mon Sep 17 00:00:00 2001 From: Jan Cavojsky Date: Fri, 26 Jun 2020 15:05:10 +0200 Subject: ikev2: add profile dump API Type: feature Signed-off-by: Jan Cavojsky Change-Id: I84776a50b520134e8a3ca6ae41b4cc29009e6319 --- src/plugins/ikev2/CMakeLists.txt | 1 + src/plugins/ikev2/ikev2.api | 24 +++++ src/plugins/ikev2/ikev2_api.c | 125 +++++++++++++++++++++++++ src/plugins/ikev2/ikev2_cli.c | 18 ++++ src/plugins/ikev2/ikev2_test.c | 189 ++++++++++++++++++++++++++++++++++++++ src/plugins/ikev2/ikev2_types.api | 79 ++++++++++++++++ 6 files changed, 436 insertions(+) create mode 100644 src/plugins/ikev2/ikev2_types.api diff --git a/src/plugins/ikev2/CMakeLists.txt b/src/plugins/ikev2/CMakeLists.txt index dac2465241b..6f2e5a68153 100644 --- a/src/plugins/ikev2/CMakeLists.txt +++ b/src/plugins/ikev2/CMakeLists.txt @@ -24,6 +24,7 @@ add_vpp_plugin(ikev2 ikev2_payload.c API_FILES + ikev2_types.api ikev2.api API_TEST_SOURCES diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api index 325e6549352..e38927ab85c 100644 --- a/src/plugins/ikev2/ikev2.api +++ b/src/plugins/ikev2/ikev2.api @@ -16,6 +16,7 @@ option version = "1.0.1"; +import "plugins/ikev2/ikev2_types.api"; import "vnet/ip/ip_types.api"; import "vnet/interface_types.api"; @@ -41,6 +42,29 @@ define ikev2_plugin_get_version_reply u32 minor; }; +/** \brief Dump all profiles + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define ikev2_profile_dump +{ + u32 client_index; + u32 context; + option status="in_progress"; +}; + +/** \brief Details about all profiles + @param context - returned sender context, to match reply w/ request + @param profile - profile element with encapsulated attributes +*/ +define ikev2_profile_details +{ + u32 context; + vl_api_ikev2_profile_t profile; + option status="in_progress"; +}; + + /** \brief IKEv2: Add/delete profile @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_api.c b/src/plugins/ikev2/ikev2_api.c index ef97898a747..7bac98f9b4f 100644 --- a/src/plugins/ikev2/ikev2_api.c +++ b/src/plugins/ikev2/ikev2_api.c @@ -30,6 +30,11 @@ #include #include + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + extern ikev2_main_t ikev2_main; #define IKEV2_PLUGIN_VERSION_MAJOR 1 @@ -37,6 +42,126 @@ extern ikev2_main_t ikev2_main; #define REPLY_MSG_ID_BASE ikev2_main.msg_id_base #include +static void +cp_transforms (vl_api_ikev2_transforms_set_t * vl_api_ts, + ikev2_transforms_set * ts) +{ + vl_api_ts->crypto_alg = ts->crypto_alg; + vl_api_ts->integ_alg = ts->integ_alg; + vl_api_ts->dh_type = ts->dh_type; + vl_api_ts->crypto_key_size = ts->crypto_key_size; +} + +static void +cp_id (vl_api_ikev2_id_t * vl_api_id, ikev2_id_t * id) +{ + if (!id->data) + return; + + int size_data = 0; + vl_api_id->type = id->type; + size_data = sizeof (vl_api_id->data) - 1; // size without zero ending character + if (vec_len (id->data) < size_data) + size_data = vec_len (id->data); + + vl_api_id->data_len = size_data; + clib_memcpy (vl_api_id->data, id->data, size_data); +} + +static void +cp_ts (vl_api_ikev2_ts_t * vl_api_ts, ikev2_ts_t * ts) +{ + vl_api_ts->ts_type = ts->ts_type; + vl_api_ts->protocol_id = ts->protocol_id; + vl_api_ts->selector_len = ts->selector_len; + vl_api_ts->start_port = ts->start_port; + vl_api_ts->end_port = ts->end_port; + clib_memcpy (&vl_api_ts->start_addr, &ts->start_addr, + sizeof (ip4_address_t)); + clib_memcpy (&vl_api_ts->end_addr, &ts->end_addr, sizeof (ip4_address_t)); +} + +static void +cp_auth (vl_api_ikev2_auth_t * vl_api_auth, ikev2_auth_t * auth) +{ + vl_api_auth->method = auth->method; + vl_api_auth->data_len = vec_len (auth->data); + vl_api_auth->hex = auth->hex; + clib_memcpy (&vl_api_auth->data, auth->data, vec_len (auth->data)); +} + +static void +cp_responder (vl_api_ikev2_responder_t * vl_api_responder, + ikev2_responder_t * responder) +{ + vl_api_responder->sw_if_index = responder->sw_if_index; + clib_memcpy (&vl_api_responder->ip4, &responder->ip4, + sizeof (ip4_address_t)); +} + +static void +send_profile (ikev2_profile_t * profile, vl_api_registration_t * reg, + u32 context) +{ + vl_api_ikev2_profile_details_t *rmp = 0; + + rmp = vl_msg_api_alloc (sizeof (*rmp) + vec_len (profile->auth.data)); + clib_memset (rmp, 0, sizeof (*rmp) + vec_len (profile->auth.data)); + ikev2_main_t *im = &ikev2_main; + rmp->_vl_msg_id = ntohs (VL_API_IKEV2_PROFILE_DETAILS + im->msg_id_base); + rmp->context = context; + + int size_data = sizeof (rmp->profile.name) - 1; + if (vec_len (profile->name) < size_data) + size_data = vec_len (profile->name); + clib_memcpy (rmp->profile.name, profile->name, size_data); + + cp_transforms (&rmp->profile.ike_ts, &profile->ike_ts); + cp_transforms (&rmp->profile.esp_ts, &profile->esp_ts); + + cp_id (&rmp->profile.loc_id, &profile->loc_id); + cp_id (&rmp->profile.rem_id, &profile->rem_id); + + cp_ts (&rmp->profile.rem_ts, &profile->rem_ts); + cp_ts (&rmp->profile.loc_ts, &profile->loc_ts); + + cp_auth (&rmp->profile.auth, &profile->auth); + + cp_responder (&rmp->profile.responder, &profile->responder); + + rmp->profile.udp_encap = profile->udp_encap; + rmp->profile.tun_itf = profile->tun_itf; + + rmp->profile.ipsec_over_udp_port = profile->ipsec_over_udp_port; + + rmp->profile.lifetime = profile->lifetime; + rmp->profile.lifetime_maxdata = profile->lifetime_maxdata; + rmp->profile.lifetime_jitter = profile->lifetime_jitter; + rmp->profile.handover = profile->handover; + + vl_api_ikev2_profile_t_endian (&rmp->profile); + + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_ikev2_profile_dump_t_handler (vl_api_ikev2_profile_dump_t * mp) +{ + ikev2_main_t *im = &ikev2_main; + ikev2_profile_t *profile; + vl_api_registration_t *reg; + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + pool_foreach (profile, im->profiles, + ({ + send_profile (profile, reg, mp->context); + })); + /* *INDENT-ON* */ +} + static void vl_api_ikev2_plugin_get_version_t_handler (vl_api_ikev2_plugin_get_version_t * mp) diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c index b991de4207e..6c75557e41a 100644 --- a/src/plugins/ikev2/ikev2_cli.c +++ b/src/plugins/ikev2/ikev2_cli.c @@ -509,11 +509,29 @@ 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 (~0 != p->responder.sw_if_index) + vlib_cli_output(vm, " responder %U %U", + format_vnet_sw_if_index_name, vnet_get_main(), p->responder.sw_if_index, + format_ip4_address, &p->responder.ip4); if (p->udp_encap) vlib_cli_output(vm, " udp-encap"); if (p->ipsec_over_udp_port != IPSEC_UDP_PORT_NONE) vlib_cli_output(vm, " ipsec-over-udp port %d", p->ipsec_over_udp_port); + + if (p->ike_ts.crypto_alg || p->ike_ts.integ_alg || p->ike_ts.dh_type || p->ike_ts.crypto_key_size) + vlib_cli_output(vm, " ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U", + format_ikev2_transform_encr_type, p->ike_ts.crypto_alg, p->ike_ts.crypto_key_size, + format_ikev2_transform_integ_type, p->ike_ts.integ_alg, + format_ikev2_transform_dh_type, p->ike_ts.dh_type); + + if (p->esp_ts.crypto_alg || p->esp_ts.integ_alg || p->esp_ts.dh_type) + vlib_cli_output(vm, " esp-crypto-alg %U %u esp-integ-alg %U", + format_ikev2_transform_encr_type, p->esp_ts.crypto_alg, p->esp_ts.crypto_key_size, + format_ikev2_transform_integ_type, p->esp_ts.integ_alg); + + vlib_cli_output(vm, " lifetime %d jitter %d handover %d maxdata %d", + p->lifetime, p->lifetime_jitter, p->handover, p->lifetime_maxdata); })); /* *INDENT-ON* */ diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c index 298125d23b0..91722ec2b9a 100644 --- a/src/plugins/ikev2/ikev2_test.c +++ b/src/plugins/ikev2/ikev2_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define __plugin_msg_base ikev2_test_main.msg_id_base @@ -30,11 +31,13 @@ #include #include #include +#include typedef struct { /* API message ID base */ u16 msg_id_base; + u32 ping_id; vat_main_t *vat_main; } ikev2_test_main_t; @@ -54,6 +57,7 @@ unformat_ikev2_auth_method (unformat_input_t * input, va_list * args) return 1; } + uword unformat_ikev2_id_type (unformat_input_t * input, va_list * args) { @@ -68,6 +72,191 @@ unformat_ikev2_id_type (unformat_input_t * input, va_list * args) return 1; } +#define MACRO_FORMAT(lc) \ +u8 * format_ikev2_##lc (u8 * s, va_list * args) \ +{ \ + u32 i = va_arg (*args, u32); \ + char * t = 0; \ + switch (i) { \ + foreach_ikev2_##lc \ + default: \ + return format (s, "unknown (%u)", i); \ + } \ + s = format (s, "%s", t); \ + return s; \ +} + +#define _(v,f,str) case IKEV2_AUTH_METHOD_##f: t = str; break; +MACRO_FORMAT (auth_method) +#undef _ +#define _(v,f,str) case IKEV2_ID_TYPE_##f: t = str; break; + MACRO_FORMAT (id_type) +#undef _ +#define _(v,f,str) case IKEV2_TRANSFORM_ENCR_TYPE_##f: t = str; break; + MACRO_FORMAT (transform_encr_type) +#undef _ +#define _(v,f,str) case IKEV2_TRANSFORM_INTEG_TYPE_##f: t = str; break; + MACRO_FORMAT (transform_integ_type) +#undef _ +#define _(v,f,str) case IKEV2_TRANSFORM_DH_TYPE_##f: t = str; break; + MACRO_FORMAT (transform_dh_type) +#undef _ + u8 *format_ikev2_id_type_and_data (u8 * s, va_list * args) +{ + vl_api_ikev2_id_t *id = va_arg (*args, vl_api_ikev2_id_t *); + + if (id->type == 0) + return format (s, "none"); + + s = format (s, "%U", format_ikev2_id_type, id->type); + + switch (id->type) + { + case 0: + return format (s, "none"); + case IKEV2_ID_TYPE_ID_FQDN: + s = format (s, " %s", id->data); + break; + case IKEV2_ID_TYPE_ID_RFC822_ADDR: + s = format (s, " %s", id->data); + break; + case IKEV2_ID_TYPE_ID_IPV4_ADDR: + s = format (s, " %U", format_ip4_address, id->data); + break; + case IKEV2_ID_TYPE_ID_KEY_ID: + s = format (s, " 0x%U", format_hex_bytes, id->data, id->data_len); + break; + default: + s = format (s, " %s", id->data); + } + + return s; +} + +static int +api_ikev2_profile_dump (vat_main_t * vam) +{ + ikev2_test_main_t *ik = &ikev2_test_main; + vl_api_ikev2_profile_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + /* Construct the API message */ + M (IKEV2_PROFILE_DUMP, mp); + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + if (!ik->ping_id) + ik->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); + mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); + mp_ping->_vl_msg_id = htons (ik->ping_id); + mp_ping->client_index = vam->my_client_index; + + fformat (vam->ofp, "Sending ping id=%d\n", ik->ping_id); + + vam->result_ready = 0; + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static void vl_api_ikev2_profile_details_t_handler + (vl_api_ikev2_profile_details_t * mp) +{ + vat_main_t *vam = ikev2_test_main.vat_main; + vl_api_ikev2_profile_t *p = &mp->profile; + + fformat (vam->ofp, "profile %s\n", p->name); + + if (p->auth.method) + { + if (p->auth.hex) + fformat (vam->ofp, " auth-method %U auth data 0x%U\n", + format_ikev2_auth_method, p->auth.method, + format_hex_bytes, p->auth.data, + clib_net_to_host_u32 (p->auth.data_len)); + else + fformat (vam->ofp, " auth-method %U auth data %v\n", + format_ikev2_auth_method, p->auth.method, format (0, + "%s", + p-> + auth.data)); + } + + if (p->loc_id.type) + { + fformat (vam->ofp, " local id-type data %U\n", + format_ikev2_id_type_and_data, &p->loc_id); + } + + if (p->rem_id.type) + { + fformat (vam->ofp, " remote id-type data %U\n", + format_ikev2_id_type_and_data, &p->rem_id); + } + + if (*((u32 *) & p->loc_ts.end_addr)) + fformat (vam->ofp, " local traffic-selector addr %U - %U port %u - %u" + " protocol %u\n", + format_ip4_address, &p->loc_ts.start_addr, + format_ip4_address, &p->loc_ts.end_addr, + clib_net_to_host_u16 (p->loc_ts.start_port), + clib_net_to_host_u16 (p->loc_ts.end_port), + p->loc_ts.protocol_id); + + if (*((u32 *) & p->rem_ts.end_addr)) + fformat (vam->ofp, " remote traffic-selector addr %U - %U port %u - %u" + " protocol %u\n", + format_ip4_address, &p->rem_ts.start_addr, + format_ip4_address, &p->rem_ts.end_addr, + clib_net_to_host_u16 (p->rem_ts.start_port), + clib_net_to_host_u16 (p->rem_ts.end_port), + p->rem_ts.protocol_id); + u32 tun_itf = clib_net_to_host_u32 (p->tun_itf); + if (~0 != tun_itf) + fformat (vam->ofp, " protected tunnel idx %d\n", tun_itf); + + u32 sw_if_index = clib_net_to_host_u32 (p->responder.sw_if_index); + if (~0 != sw_if_index) + fformat (vam->ofp, " responder idx %d %U\n", + sw_if_index, format_ip4_address, &p->responder.ip4); + + if (p->udp_encap) + fformat (vam->ofp, " udp-encap\n"); + + u32 ipsec_over_udp_port = clib_net_to_host_u16 (p->ipsec_over_udp_port); + if (ipsec_over_udp_port != IPSEC_UDP_PORT_NONE) + fformat (vam->ofp, " ipsec-over-udp port %d\n", ipsec_over_udp_port); + + u32 crypto_key_size = clib_net_to_host_u32 (p->ike_ts.crypto_key_size); + if (p->ike_ts.crypto_alg || p->ike_ts.integ_alg || p->ike_ts.dh_type + || crypto_key_size) + fformat (vam->ofp, " ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U\n", + format_ikev2_transform_encr_type, p->ike_ts.crypto_alg, + crypto_key_size, format_ikev2_transform_integ_type, + p->ike_ts.integ_alg, format_ikev2_transform_dh_type, + p->ike_ts.dh_type); + + crypto_key_size = clib_net_to_host_u32 (p->esp_ts.crypto_key_size); + if (p->esp_ts.crypto_alg || p->esp_ts.integ_alg || p->esp_ts.dh_type) + fformat (vam->ofp, " esp-crypto-alg %U %u esp-integ-alg %U\n", + format_ikev2_transform_encr_type, p->esp_ts.crypto_alg, + crypto_key_size, + format_ikev2_transform_integ_type, p->esp_ts.integ_alg); + + fformat (vam->ofp, " lifetime %d jitter %d handover %d maxdata %d\n", + clib_net_to_host_u64 (p->lifetime), + clib_net_to_host_u32 (p->lifetime_jitter), + clib_net_to_host_u32 (p->handover), + clib_net_to_host_u64 (p->lifetime_maxdata)); + + vam->result_ready = 1; +} + static int api_ikev2_plugin_get_version (vat_main_t * vam) { diff --git a/src/plugins/ikev2/ikev2_types.api b/src/plugins/ikev2/ikev2_types.api new file mode 100644 index 00000000000..1dc4fdc8b88 --- /dev/null +++ b/src/plugins/ikev2/ikev2_types.api @@ -0,0 +1,79 @@ +/* Hey Emacs use -*- mode: C -*- */ +/* + * Copyright (c) 2015-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import "vnet/ip/ip_types.api"; + + +typedef ikev2_id +{ + u8 type; + u8 data_len; + string data[64]; +}; + +typedef ikev2_ts +{ + u8 ts_type; + u8 protocol_id; + u16 selector_len; + u16 start_port; + u16 end_port; + vl_api_ip4_address_t start_addr; + vl_api_ip4_address_t end_addr; +}; + +typedef ikev2_auth +{ + u8 method; + u8 hex; /* hex encoding of the shared secret */ + u32 data_len; + u8 data[data_len]; +}; + +typedef ikev2_responder +{ + u32 sw_if_index; + vl_api_ip4_address_t ip4; +}; + +typedef ikev2_transforms_set +{ + u8 crypto_alg; + u8 integ_alg; + u8 dh_type; + u32 crypto_key_size; +}; + +typedef ikev2_profile +{ + string name[64]; + vl_api_ikev2_id_t loc_id; + vl_api_ikev2_id_t rem_id; + vl_api_ikev2_ts_t loc_ts; + vl_api_ikev2_ts_t rem_ts; + vl_api_ikev2_responder_t responder; + vl_api_ikev2_transforms_set_t ike_ts; + vl_api_ikev2_transforms_set_t esp_ts; + u64 lifetime; + u64 lifetime_maxdata; + u32 lifetime_jitter; + u32 handover; + u16 ipsec_over_udp_port; + u32 tun_itf; + u8 udp_encap; + vl_api_ikev2_auth_t auth; +}; -- cgit 1.2.3-korg