Add API support to dump IPsec SAs
Add an API request message type to dump IPsec SAs. Either all IPsec SAs can be dumped or it can be limited to a single SA ID (numeric ID set at creation time - not an index). Add a handler for incoming messages with the new request type. Add an API response message type containing the data for an IPsec SA. Add VAT support for new message type. Change-Id: Id7828d000efc637dee7f988a87d3f707a8b466b7 Signed-off-by: Matthew Smith <mgsmith@netgate.com>
This commit is contained in:
committed by
Damjan Marion
parent
780fc39506
commit
2802953096
@@ -5232,6 +5232,7 @@ _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply) \
|
||||
_(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
|
||||
_(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply) \
|
||||
_(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply) \
|
||||
_(IPSEC_SA_DETAILS, ipsec_sa_details) \
|
||||
_(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply) \
|
||||
_(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply) \
|
||||
_(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply) \
|
||||
@@ -13774,6 +13775,121 @@ api_ipsec_tunnel_if_add_del (vat_main_t * vam)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
|
||||
{
|
||||
vat_main_t *vam = &vat_main;
|
||||
|
||||
print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
|
||||
"crypto_key %U integ_alg %u integ_key %U use_esn %u "
|
||||
"use_anti_replay %u is_tunnel %u is_tunnel_ip6 %u "
|
||||
"tunnel_src_addr %U tunnel_dst_addr %U "
|
||||
"salt %u seq_outbound %lu last_seq_inbound %lu "
|
||||
"replay_window %lu total_data_size %lu\n",
|
||||
ntohl (mp->sa_id), ntohl (mp->sw_if_index), ntohl (mp->spi),
|
||||
mp->protocol,
|
||||
mp->crypto_alg, format_hex_bytes, mp->crypto_key, mp->crypto_key_len,
|
||||
mp->integ_alg, format_hex_bytes, mp->integ_key, mp->integ_key_len,
|
||||
mp->use_esn, mp->use_anti_replay, mp->is_tunnel, mp->is_tunnel_ip6,
|
||||
(mp->is_tunnel_ip6) ? format_ip6_address : format_ip4_address,
|
||||
mp->tunnel_src_addr,
|
||||
(mp->is_tunnel_ip6) ? format_ip6_address : format_ip4_address,
|
||||
mp->tunnel_dst_addr,
|
||||
ntohl (mp->salt),
|
||||
clib_net_to_host_u64 (mp->seq_outbound),
|
||||
clib_net_to_host_u64 (mp->last_seq_inbound),
|
||||
clib_net_to_host_u64 (mp->replay_window),
|
||||
clib_net_to_host_u64 (mp->total_data_size));
|
||||
}
|
||||
|
||||
#define vl_api_ipsec_sa_details_t_endian vl_noop_handler
|
||||
#define vl_api_ipsec_sa_details_t_print vl_noop_handler
|
||||
|
||||
static void vl_api_ipsec_sa_details_t_handler_json
|
||||
(vl_api_ipsec_sa_details_t * mp)
|
||||
{
|
||||
vat_main_t *vam = &vat_main;
|
||||
vat_json_node_t *node = NULL;
|
||||
struct in_addr src_ip4, dst_ip4;
|
||||
struct in6_addr src_ip6, dst_ip6;
|
||||
|
||||
if (VAT_JSON_ARRAY != vam->json_tree.type)
|
||||
{
|
||||
ASSERT (VAT_JSON_NONE == vam->json_tree.type);
|
||||
vat_json_init_array (&vam->json_tree);
|
||||
}
|
||||
node = vat_json_array_add (&vam->json_tree);
|
||||
|
||||
vat_json_init_object (node);
|
||||
vat_json_object_add_uint (node, "sa_id", ntohl (mp->sa_id));
|
||||
vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
|
||||
vat_json_object_add_uint (node, "spi", ntohl (mp->spi));
|
||||
vat_json_object_add_uint (node, "proto", mp->protocol);
|
||||
vat_json_object_add_uint (node, "crypto_alg", mp->crypto_alg);
|
||||
vat_json_object_add_uint (node, "integ_alg", mp->integ_alg);
|
||||
vat_json_object_add_uint (node, "use_esn", mp->use_esn);
|
||||
vat_json_object_add_uint (node, "use_anti_replay", mp->use_anti_replay);
|
||||
vat_json_object_add_uint (node, "is_tunnel", mp->is_tunnel);
|
||||
vat_json_object_add_uint (node, "is_tunnel_ip6", mp->is_tunnel_ip6);
|
||||
vat_json_object_add_bytes (node, "crypto_key", mp->crypto_key,
|
||||
mp->crypto_key_len);
|
||||
vat_json_object_add_bytes (node, "integ_key", mp->integ_key,
|
||||
mp->integ_key_len);
|
||||
if (mp->is_tunnel_ip6)
|
||||
{
|
||||
clib_memcpy (&src_ip6, mp->tunnel_src_addr, sizeof (src_ip6));
|
||||
vat_json_object_add_ip6 (node, "tunnel_src_addr", src_ip6);
|
||||
clib_memcpy (&dst_ip6, mp->tunnel_dst_addr, sizeof (dst_ip6));
|
||||
vat_json_object_add_ip6 (node, "tunnel_dst_addr", dst_ip6);
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_memcpy (&src_ip4, mp->tunnel_src_addr, sizeof (src_ip4));
|
||||
vat_json_object_add_ip4 (node, "tunnel_src_addr", src_ip4);
|
||||
clib_memcpy (&dst_ip4, mp->tunnel_dst_addr, sizeof (dst_ip4));
|
||||
vat_json_object_add_ip4 (node, "tunnel_dst_addr", dst_ip4);
|
||||
}
|
||||
vat_json_object_add_uint (node, "replay_window",
|
||||
clib_net_to_host_u64 (mp->replay_window));
|
||||
vat_json_object_add_uint (node, "total_data_size",
|
||||
clib_net_to_host_u64 (mp->total_data_size));
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
api_ipsec_sa_dump (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_ipsec_sa_dump_t *mp;
|
||||
vl_api_control_ping_t *mp_ping;
|
||||
u32 sa_id = ~0;
|
||||
int ret;
|
||||
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "sa_id %d", &sa_id))
|
||||
;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
M (IPSEC_SA_DUMP, mp);
|
||||
|
||||
mp->sa_id = ntohl (sa_id);
|
||||
|
||||
S (mp);
|
||||
|
||||
/* Use a control ping for synchronization */
|
||||
M (CONTROL_PING, mp_ping);
|
||||
S (mp_ping);
|
||||
|
||||
W (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
api_ikev2_profile_add_del (vat_main_t * vam)
|
||||
{
|
||||
@@ -20838,6 +20954,7 @@ _(ipsec_tunnel_if_add_del, "local_spi <n> remote_spi <n>\n" \
|
||||
" crypto_alg <alg> local_crypto_key <hex> remote_crypto_key <hex>\n" \
|
||||
" integ_alg <alg> local_integ_key <hex> remote_integ_key <hex>\n" \
|
||||
" local_ip <addr> remote_ip <addr> [esn] [anti_replay] [del]\n") \
|
||||
_(ipsec_sa_dump, "[sa_id <n>]") \
|
||||
_(ikev2_profile_add_del, "name <profile_name> [del]") \
|
||||
_(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n" \
|
||||
"(auth_data 0x<data> | auth_data <data>)") \
|
||||
|
||||
@@ -544,6 +544,75 @@ define ipsec_tunnel_if_add_del_reply {
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Dump IPsec security association
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param sa_id - optional ID of an SA to dump, if ~0 dump all SAs in SAD
|
||||
*/
|
||||
define ipsec_sa_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sa_id;
|
||||
};
|
||||
|
||||
/** \brief IPsec security association database response
|
||||
@param context - sender context which was passed in the request
|
||||
@param sa_id - SA ID, policy-based SAs >=0, tunnel interface SAs = 0
|
||||
@param sw_if_index - sw_if_index of tunnel interface, policy-based SAs = ~0
|
||||
@param spi - security parameter index
|
||||
@param protocol - IPsec protocol (value from ipsec_protocol_t)
|
||||
@param crypto_alg - crypto algorithm (value from ipsec_crypto_alg_t)
|
||||
@param crypto_key_len - length of crypto_key in bytes
|
||||
@param crypto_key - crypto keying material
|
||||
@param integ_alg - integrity algorithm (value from ipsec_integ_alg_t)
|
||||
@param integ_key_len - length of integ_key in bytes
|
||||
@param integ_key - integrity keying material
|
||||
@param use_esn - using extended sequence numbers when non-zero
|
||||
@param use_anti_replay - using anti-replay window when non-zero
|
||||
@param is_tunnel - IPsec tunnel mode when non-zero, else transport mode
|
||||
@param is_tunnel_ipv6 - If using tunnel mode, endpoints are IPv6
|
||||
@param tunnel_src_addr - Tunnel source address if using tunnel mode
|
||||
@param tunnel_dst_addr - Tunnel destination address is using tunnel mode
|
||||
@param salt - 4 byte salt
|
||||
@param seq - current sequence number for outbound
|
||||
@param seq_hi - high 32 bits of ESN for outbound
|
||||
@param last_seq - highest sequence number received inbound
|
||||
@param last_seq_hi - high 32 bits of highest ESN received inbound
|
||||
@param replay_window - bit map of seq nums received relative to last_seq if using anti-replay
|
||||
@param total_data_size - total bytes sent or received
|
||||
*/
|
||||
define ipsec_sa_details {
|
||||
u32 context;
|
||||
u32 sa_id;
|
||||
u32 sw_if_index;
|
||||
|
||||
u32 spi;
|
||||
u8 protocol;
|
||||
|
||||
u8 crypto_alg;
|
||||
u8 crypto_key_len;
|
||||
u8 crypto_key[128];
|
||||
|
||||
u8 integ_alg;
|
||||
u8 integ_key_len;
|
||||
u8 integ_key[128];
|
||||
|
||||
u8 use_esn;
|
||||
u8 use_anti_replay;
|
||||
|
||||
u8 is_tunnel;
|
||||
u8 is_tunnel_ip6;
|
||||
u8 tunnel_src_addr[16];
|
||||
u8 tunnel_dst_addr[16];
|
||||
|
||||
u32 salt;
|
||||
u64 seq_outbound;
|
||||
u64 last_seq_inbound;
|
||||
u64 replay_window;
|
||||
|
||||
u64 total_data_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
|
||||
@@ -53,6 +53,7 @@ _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \
|
||||
_(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry) \
|
||||
_(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry) \
|
||||
_(IPSEC_SA_SET_KEY, ipsec_sa_set_key) \
|
||||
_(IPSEC_SA_DUMP, ipsec_sa_dump) \
|
||||
_(IPSEC_SPD_DUMP, ipsec_spd_dump) \
|
||||
_(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del) \
|
||||
_(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del) \
|
||||
@@ -402,6 +403,111 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
|
||||
}));
|
||||
}
|
||||
|
||||
static void
|
||||
send_ipsec_sa_details (ipsec_sa_t * sa, unix_shared_memory_queue_t * q,
|
||||
u32 context, u32 sw_if_index)
|
||||
{
|
||||
vl_api_ipsec_sa_details_t *mp;
|
||||
|
||||
mp = vl_msg_api_alloc (sizeof (*mp));
|
||||
memset (mp, 0, sizeof (*mp));
|
||||
mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
|
||||
mp->context = context;
|
||||
|
||||
mp->sa_id = htonl (sa->id);
|
||||
mp->sw_if_index = htonl (sw_if_index);
|
||||
|
||||
mp->spi = htonl (sa->spi);
|
||||
mp->protocol = sa->protocol;
|
||||
|
||||
mp->crypto_alg = sa->crypto_alg;
|
||||
mp->crypto_key_len = sa->crypto_key_len;
|
||||
memcpy (mp->crypto_key, sa->crypto_key, sa->crypto_key_len);
|
||||
|
||||
mp->integ_alg = sa->integ_alg;
|
||||
mp->integ_key_len = sa->integ_key_len;
|
||||
memcpy (mp->integ_key, sa->integ_key, sa->integ_key_len);
|
||||
|
||||
mp->use_esn = sa->use_esn;
|
||||
mp->use_anti_replay = sa->use_anti_replay;
|
||||
|
||||
mp->is_tunnel = sa->is_tunnel;
|
||||
mp->is_tunnel_ip6 = sa->is_tunnel_ip6;
|
||||
|
||||
if (sa->is_tunnel)
|
||||
{
|
||||
if (sa->is_tunnel_ip6)
|
||||
{
|
||||
memcpy (mp->tunnel_src_addr, &sa->tunnel_src_addr.ip6, 16);
|
||||
memcpy (mp->tunnel_dst_addr, &sa->tunnel_dst_addr.ip6, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (mp->tunnel_src_addr, &sa->tunnel_src_addr.ip4, 4);
|
||||
memcpy (mp->tunnel_dst_addr, &sa->tunnel_dst_addr.ip4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
mp->salt = clib_host_to_net_u32 (sa->salt);
|
||||
mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
|
||||
mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
|
||||
if (sa->use_esn)
|
||||
{
|
||||
mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
|
||||
mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
|
||||
}
|
||||
if (sa->use_anti_replay)
|
||||
mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
|
||||
mp->total_data_size = clib_host_to_net_u64 (sa->total_data_size);
|
||||
|
||||
vl_msg_api_send_shmem (q, (u8 *) & mp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
|
||||
{
|
||||
unix_shared_memory_queue_t *q;
|
||||
ipsec_main_t *im = &ipsec_main;
|
||||
vnet_main_t *vnm = im->vnet_main;
|
||||
ipsec_sa_t *sa;
|
||||
ipsec_tunnel_if_t *t;
|
||||
u32 *sa_index_to_tun_if_index = 0;
|
||||
|
||||
#if WITH_LIBSSL > 0
|
||||
q = vl_api_client_index_to_input_queue (mp->client_index);
|
||||
if (q == 0 || pool_elts (im->sad) == 0)
|
||||
return;
|
||||
|
||||
vec_validate_init_empty (sa_index_to_tun_if_index, vec_len (im->sad) - 1,
|
||||
~0);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (t, im->tunnel_interfaces,
|
||||
({
|
||||
vnet_hw_interface_t *hi;
|
||||
u32 sw_if_index = ~0;
|
||||
|
||||
hi = vnet_get_hw_interface (vnm, t->hw_if_index);
|
||||
sw_if_index = hi->sw_if_index;
|
||||
sa_index_to_tun_if_index[t->input_sa_index] = sw_if_index;
|
||||
sa_index_to_tun_if_index[t->output_sa_index] = sw_if_index;
|
||||
}));
|
||||
|
||||
pool_foreach (sa, im->sad,
|
||||
({
|
||||
if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == sa->id)
|
||||
send_ipsec_sa_details (sa, q, mp->context,
|
||||
sa_index_to_tun_if_index[sa - im->sad]);
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vec_free (sa_index_to_tun_if_index);
|
||||
#else
|
||||
clib_warning ("unimplemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
|
||||
|
||||
Reference in New Issue
Block a user