diff options
Diffstat (limited to 'src/vnet/ipsec/ipsec_api.c')
-rw-r--r-- | src/vnet/ipsec/ipsec_api.c | 413 |
1 files changed, 381 insertions, 32 deletions
diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c index 11bfa41b4f1..21216b1a614 100644 --- a/src/vnet/ipsec/ipsec_api.c +++ b/src/vnet/ipsec/ipsec_api.c @@ -124,6 +124,7 @@ typedef struct ipsec_dump_walk_ctx_t_ { vl_api_registration_t *reg; u32 context; + u32 sw_if_index; } ipsec_dump_walk_ctx_t; static walk_rc_t @@ -149,12 +150,10 @@ send_ipsec_tunnel_protect_details (index_t itpi, void *arg) sa = ipsec_sa_get (itp->itp_out_sa); mp->tun.sa_out = htonl (sa->id); mp->tun.n_sa_in = itp->itp_n_sa_in; - /* *INDENT-OFF* */ FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa, ({ mp->tun.sa_in[ii++] = htonl (sa->id); })); - /* *INDENT-ON* */ vl_api_send_msg (ctx->reg, (u8 *) mp); @@ -232,7 +231,8 @@ static void vl_api_ipsec_spd_entry_add_del_t_handler p.is_ipv6 = (itype == IP46_TYPE_IP6); - p.protocol = mp->entry.protocol; + p.protocol = + mp->entry.protocol ? mp->entry.protocol : IPSEC_POLICY_PROTOCOL_ANY; p.rport.start = ntohs (mp->entry.remote_port_start); p.rport.stop = ntohs (mp->entry.remote_port_stop); p.lport.start = ntohs (mp->entry.local_port_start); @@ -262,12 +262,69 @@ static void vl_api_ipsec_spd_entry_add_del_t_handler goto out; out: - /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ({ rmp->stat_index = ntohl(stat_index); })); - /* *INDENT-ON* */ +} + +static void +vl_api_ipsec_spd_entry_add_del_v2_t_handler ( + vl_api_ipsec_spd_entry_add_del_v2_t *mp) +{ + vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); + vl_api_ipsec_spd_entry_add_del_reply_t *rmp; + ip46_type_t itype; + u32 stat_index; + int rv; + + stat_index = ~0; + + ipsec_policy_t p; + + clib_memset (&p, 0, sizeof (p)); + + p.id = ntohl (mp->entry.spd_id); + p.priority = ntohl (mp->entry.priority); + + itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start); + ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop); + ip_address_decode (&mp->entry.local_address_start, &p.laddr.start); + ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop); + + p.is_ipv6 = (itype == IP46_TYPE_IP6); + + p.protocol = mp->entry.protocol; + p.rport.start = ntohs (mp->entry.remote_port_start); + p.rport.stop = ntohs (mp->entry.remote_port_stop); + p.lport.start = ntohs (mp->entry.local_port_start); + p.lport.stop = ntohs (mp->entry.local_port_stop); + + rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy); + + if (rv) + goto out; + + /* policy action resolve unsupported */ + if (p.policy == IPSEC_POLICY_ACTION_RESOLVE) + { + clib_warning ("unsupported action: 'resolve'"); + rv = VNET_API_ERROR_UNIMPLEMENTED; + goto out; + } + p.sa_id = ntohl (mp->entry.sa_id); + rv = + ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy, &p.type); + if (rv) + goto out; + + rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index); + if (rv) + goto out; + +out: + REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_V2_REPLY, + ({ rmp->stat_index = ntohl (stat_index); })); } static void vl_api_ipsec_sad_entry_add_del_t_handler @@ -321,18 +378,16 @@ static void vl_api_ipsec_sad_entry_add_del_t_handler ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src); ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst); - rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key, - integ_alg, &integ_key, flags, mp->entry.salt, - htons (mp->entry.udp_src_port), - htons (mp->entry.udp_dst_port), &tun, &sa_index); + rv = ipsec_sa_add_and_lock ( + id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags, + mp->entry.salt, htons (mp->entry.udp_src_port), + htons (mp->entry.udp_dst_port), 0, &tun, &sa_index); out: - /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY, { rmp->stat_index = htonl (sa_index); }); - /* *INDENT-ON* */ } static void vl_api_ipsec_sad_entry_add_del_v2_t_handler @@ -395,18 +450,16 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src); ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst); - rv = ipsec_sa_add_and_lock ( - id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags, - mp->entry.salt, htons (mp->entry.udp_src_port), - htons (mp->entry.udp_dst_port), &tun, &sa_index); + rv = ipsec_sa_add_and_lock ( + id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags, + mp->entry.salt, htons (mp->entry.udp_src_port), + htons (mp->entry.udp_dst_port), 0, &tun, &sa_index); out: - /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY, { rmp->stat_index = htonl (sa_index); }); - /* *INDENT-ON* */ } static int @@ -419,7 +472,7 @@ ipsec_sad_entry_add_v3 (const vl_api_ipsec_sad_entry_v3_t *entry, ipsec_protocol_t proto; ipsec_sa_flags_t flags; u32 id, spi; - tunnel_t tun; + tunnel_t tun = { 0 }; int rv; id = ntohl (entry->sad_id); @@ -453,10 +506,10 @@ ipsec_sad_entry_add_v3 (const vl_api_ipsec_sad_entry_v3_t *entry, ipsec_key_decode (&entry->crypto_key, &crypto_key); ipsec_key_decode (&entry->integrity_key, &integ_key); - return ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key, - integ_alg, &integ_key, flags, entry->salt, - htons (entry->udp_src_port), - htons (entry->udp_dst_port), &tun, sa_index); + return ipsec_sa_add_and_lock ( + id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags, + entry->salt, htons (entry->udp_src_port), htons (entry->udp_dst_port), 0, + &tun, sa_index); } static void @@ -482,6 +535,56 @@ vl_api_ipsec_sad_entry_add_del_v3_t_handler ( { rmp->stat_index = htonl (sa_index); }); } +static int +ipsec_sad_entry_add_v4 (const vl_api_ipsec_sad_entry_v4_t *entry, + u32 *sa_index) +{ + ipsec_key_t crypto_key, integ_key; + ipsec_crypto_alg_t crypto_alg; + ipsec_integ_alg_t integ_alg; + ipsec_protocol_t proto; + ipsec_sa_flags_t flags; + u32 id, spi; + tunnel_t tun = { 0 }; + int rv; + + id = ntohl (entry->sad_id); + spi = ntohl (entry->spi); + + rv = ipsec_proto_decode (entry->protocol, &proto); + + if (rv) + return rv; + + rv = ipsec_crypto_algo_decode (entry->crypto_algorithm, &crypto_alg); + + if (rv) + return rv; + + rv = ipsec_integ_algo_decode (entry->integrity_algorithm, &integ_alg); + + if (rv) + return rv; + + flags = ipsec_sa_flags_decode (entry->flags); + + if (flags & IPSEC_SA_FLAG_IS_TUNNEL) + { + rv = tunnel_decode (&entry->tunnel, &tun); + + if (rv) + return rv; + } + + ipsec_key_decode (&entry->crypto_key, &crypto_key); + ipsec_key_decode (&entry->integrity_key, &integ_key); + + return ipsec_sa_add_and_lock ( + id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags, + entry->salt, htons (entry->udp_src_port), htons (entry->udp_dst_port), + ntohl (entry->anti_replay_window_size), &tun, sa_index); +} + static void vl_api_ipsec_sad_entry_del_t_handler (vl_api_ipsec_sad_entry_del_t *mp) { @@ -507,6 +610,74 @@ vl_api_ipsec_sad_entry_add_t_handler (vl_api_ipsec_sad_entry_add_t *mp) } static void +vl_api_ipsec_sad_entry_add_v2_t_handler (vl_api_ipsec_sad_entry_add_v2_t *mp) +{ + vl_api_ipsec_sad_entry_add_reply_t *rmp; + u32 sa_index = ~0; + int rv; + + rv = ipsec_sad_entry_add_v4 (&mp->entry, &sa_index); + + REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_V2_REPLY, + { rmp->stat_index = htonl (sa_index); }); +} + +static void +vl_api_ipsec_sad_entry_update_t_handler (vl_api_ipsec_sad_entry_update_t *mp) +{ + vl_api_ipsec_sad_entry_update_reply_t *rmp; + u32 id; + tunnel_t tun = { 0 }; + int rv; + + id = ntohl (mp->sad_id); + + if (mp->is_tun) + { + rv = tunnel_decode (&mp->tunnel, &tun); + + if (rv) + goto out; + } + + rv = ipsec_sa_update (id, htons (mp->udp_src_port), htons (mp->udp_dst_port), + &tun, mp->is_tun); + +out: + REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_UPDATE_REPLY); +} + +static void +vl_api_ipsec_sad_bind_t_handler (vl_api_ipsec_sad_bind_t *mp) +{ + vl_api_ipsec_sad_bind_reply_t *rmp; + u32 sa_id; + u32 worker; + int rv; + + sa_id = ntohl (mp->sa_id); + worker = ntohl (mp->worker); + + rv = ipsec_sa_bind (sa_id, worker, true /* bind */); + + REPLY_MACRO (VL_API_IPSEC_SAD_BIND_REPLY); +} + +static void +vl_api_ipsec_sad_unbind_t_handler (vl_api_ipsec_sad_unbind_t *mp) +{ + vl_api_ipsec_sad_unbind_reply_t *rmp; + u32 sa_id; + int rv; + + sa_id = ntohl (mp->sa_id); + + rv = ipsec_sa_bind (sa_id, ~0, false /* bind */); + + REPLY_MACRO (VL_API_IPSEC_SAD_UNBIND_REPLY); +} + +static void send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg, u32 context) { @@ -660,12 +831,10 @@ vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t * if (mp->spd_index_valid) { spd_index = ntohl (mp->spd_index); - /* *INDENT-OFF* */ hash_foreach(k, v, im->spd_index_by_sw_if_index, ({ if (v == spd_index) send_ipsec_spd_interface_details(reg, v, k, mp->context); })); - /* *INDENT-ON* */ } else { @@ -688,12 +857,10 @@ vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp) if (!rv) rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index); - /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY, ({ rmp->sw_if_index = htonl (sw_if_index); })); - /* *INDENT-ON* */ } static void @@ -713,6 +880,9 @@ send_ipsec_itf_details (ipsec_itf_t *itf, void *arg) ipsec_dump_walk_ctx_t *ctx = arg; vl_api_ipsec_itf_details_t *mp; + if (~0 != ctx->sw_if_index && ctx->sw_if_index != itf->ii_sw_if_index) + return (WALK_CONTINUE); + mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_ITF_DETAILS); @@ -738,6 +908,7 @@ vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp) ipsec_dump_walk_ctx_t ctx = { .reg = reg, .context = mp->context, + .sw_if_index = ntohl (mp->sw_if_index), }; ipsec_itf_walk (send_ipsec_itf_details, &ctx); @@ -833,7 +1004,10 @@ send_ipsec_sa_details (ipsec_sa_t * sa, void *arg) mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); } if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa)) - mp->replay_window = clib_host_to_net_u64 (sa->replay_window); + { + mp->replay_window = + clib_host_to_net_u64 (ipsec_sa_anti_replay_get_64b_window (sa)); + } mp->stat_index = clib_host_to_net_u32 (sa->stat_index); @@ -920,7 +1094,10 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg) mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); } if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa)) - mp->replay_window = clib_host_to_net_u64 (sa->replay_window); + { + mp->replay_window = + clib_host_to_net_u64 (ipsec_sa_anti_replay_get_64b_window (sa)); + } mp->stat_index = clib_host_to_net_u32 (sa->stat_index); @@ -1000,7 +1177,10 @@ send_ipsec_sa_v3_details (ipsec_sa_t *sa, void *arg) mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); } if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa)) - mp->replay_window = clib_host_to_net_u64 (sa->replay_window); + { + mp->replay_window = + clib_host_to_net_u64 (ipsec_sa_anti_replay_get_64b_window (sa)); + } mp->stat_index = clib_host_to_net_u32 (sa->stat_index); @@ -1026,8 +1206,179 @@ vl_api_ipsec_sa_v3_dump_t_handler (vl_api_ipsec_sa_v3_dump_t *mp) ipsec_sa_walk (send_ipsec_sa_v3_details, &ctx); } +static walk_rc_t +send_ipsec_sa_v4_details (ipsec_sa_t *sa, void *arg) +{ + ipsec_dump_walk_ctx_t *ctx = arg; + vl_api_ipsec_sa_v4_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V4_DETAILS); + mp->context = ctx->context; + + mp->entry.sad_id = htonl (sa->id); + mp->entry.spi = htonl (sa->spi); + mp->entry.protocol = ipsec_proto_encode (sa->protocol); + + mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg); + ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key); + + mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg); + ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key); + + mp->entry.flags = ipsec_sad_flags_encode (sa); + mp->entry.salt = clib_host_to_net_u32 (sa->salt); + + if (ipsec_sa_is_set_IS_PROTECT (sa)) + { + ipsec_sa_dump_match_ctx_t ctx = { + .sai = sa - ipsec_sa_pool, + .sw_if_index = ~0, + }; + ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx); + + mp->sw_if_index = htonl (ctx.sw_if_index); + } + else + mp->sw_if_index = ~0; + + if (ipsec_sa_is_set_IS_TUNNEL (sa)) + tunnel_encode (&sa->tunnel, &mp->entry.tunnel); + + if (ipsec_sa_is_set_UDP_ENCAP (sa)) + { + mp->entry.udp_src_port = sa->udp_hdr.src_port; + mp->entry.udp_dst_port = sa->udp_hdr.dst_port; + } + + mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq)); + mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq)); + if (ipsec_sa_is_set_USE_ESN (sa)) + { + mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); + mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); + } + if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa)) + { + mp->replay_window = + clib_host_to_net_u64 (ipsec_sa_anti_replay_get_64b_window (sa)); + } + + mp->thread_index = clib_host_to_net_u32 (sa->thread_index); + mp->stat_index = clib_host_to_net_u32 (sa->stat_index); + + vl_api_send_msg (ctx->reg, (u8 *) mp); + + return (WALK_CONTINUE); +} + +static void +vl_api_ipsec_sa_v4_dump_t_handler (vl_api_ipsec_sa_v4_dump_t *mp) +{ + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + ipsec_dump_walk_ctx_t ctx = { + .reg = reg, + .context = mp->context, + }; + + ipsec_sa_walk (send_ipsec_sa_v4_details, &ctx); +} + +static walk_rc_t +send_ipsec_sa_v5_details (ipsec_sa_t *sa, void *arg) +{ + ipsec_dump_walk_ctx_t *ctx = arg; + vl_api_ipsec_sa_v5_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V5_DETAILS); + mp->context = ctx->context; + + mp->entry.sad_id = htonl (sa->id); + mp->entry.spi = htonl (sa->spi); + mp->entry.protocol = ipsec_proto_encode (sa->protocol); + + mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg); + ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key); + + mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg); + ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key); + + mp->entry.flags = ipsec_sad_flags_encode (sa); + mp->entry.salt = clib_host_to_net_u32 (sa->salt); + + if (ipsec_sa_is_set_IS_PROTECT (sa)) + { + ipsec_sa_dump_match_ctx_t ctx = { + .sai = sa - ipsec_sa_pool, + .sw_if_index = ~0, + }; + ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx); + + mp->sw_if_index = htonl (ctx.sw_if_index); + } + else + mp->sw_if_index = ~0; + + if (ipsec_sa_is_set_IS_TUNNEL (sa)) + tunnel_encode (&sa->tunnel, &mp->entry.tunnel); + + if (ipsec_sa_is_set_UDP_ENCAP (sa)) + { + mp->entry.udp_src_port = sa->udp_hdr.src_port; + mp->entry.udp_dst_port = sa->udp_hdr.dst_port; + } + + mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq)); + mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq)); + if (ipsec_sa_is_set_USE_ESN (sa)) + { + mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); + mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi)); + } + if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa)) + { + mp->replay_window = + clib_host_to_net_u64 (ipsec_sa_anti_replay_get_64b_window (sa)); + + mp->entry.anti_replay_window_size = + clib_host_to_net_u32 (IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE (sa)); + } + + mp->thread_index = clib_host_to_net_u32 (sa->thread_index); + mp->stat_index = clib_host_to_net_u32 (sa->stat_index); + + vl_api_send_msg (ctx->reg, (u8 *) mp); + + return (WALK_CONTINUE); +} + +static void +vl_api_ipsec_sa_v5_dump_t_handler (vl_api_ipsec_sa_v5_dump_t *mp) +{ + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + ipsec_dump_walk_ctx_t ctx = { + .reg = reg, + .context = mp->context, + }; + + ipsec_sa_walk (send_ipsec_sa_v5_details, &ctx); +} + static void -vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp) +vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t *mp) { vl_api_registration_t *rp; ipsec_main_t *im = &ipsec_main; @@ -1043,7 +1394,6 @@ vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp) ipsec_ah_backend_t *ab; ipsec_esp_backend_t *eb; - /* *INDENT-OFF* */ pool_foreach (ab, im->ah_backends) { vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); @@ -1068,7 +1418,6 @@ vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp) mp->active = mp->index == im->esp_current_backend ? 1 : 0; vl_api_send_msg (rp, (u8 *)mp); } - /* *INDENT-ON* */ } static void |