diff options
Diffstat (limited to 'src/vnet/ipsec/ipsec_tun.c')
-rw-r--r-- | src/vnet/ipsec/ipsec_tun.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c index 9b76d311bc2..fb530c8dc9f 100644 --- a/src/vnet/ipsec/ipsec_tun.c +++ b/src/vnet/ipsec/ipsec_tun.c @@ -16,6 +16,7 @@ */ #include <vnet/ipsec/ipsec_tun.h> +#include <vnet/ipsec/ipsec_itf.h> #include <vnet/ipsec/esp.h> #include <vnet/udp/udp.h> #include <vnet/adj/adj_delegate.h> @@ -126,14 +127,20 @@ ipsec_tun_protect_from_const_base (const adj_delegate_t * ad) } static u32 -ipsec_tun_protect_get_adj_next (const ipsec_tun_protect_t * itp) +ipsec_tun_protect_get_adj_next (vnet_link_t linkt, + const ipsec_tun_protect_t * itp) { ipsec_main_t *im; ipsec_sa_t *sa; bool is_ip4; u32 next; - is_ip4 = ip46_address_is_ip4 (&itp->itp_tun.src); + + if (itp->itp_flags & IPSEC_PROTECT_ITF) + is_ip4 = linkt == VNET_LINK_IP4; + else + is_ip4 = ip46_address_is_ip4 (&itp->itp_tun.src); + sa = ipsec_sa_get (itp->itp_out_sa); im = &ipsec_main; @@ -169,7 +176,7 @@ ipsec_tun_protect_add_adj (adj_index_t ai, const ipsec_tun_protect_t * itp) { ipsec_tun_protect_sa_by_adj_index[ai] = itp->itp_out_sa; adj_nbr_midchain_update_next_node - (ai, ipsec_tun_protect_get_adj_next (itp)); + (ai, ipsec_tun_protect_get_adj_next (adj_get_link_type (ai), itp)); } } @@ -249,6 +256,9 @@ ipsec_tun_protect_adj_add (adj_index_t ai, void *arg) itp - ipsec_tun_protect_pool); ipsec_tun_protect_add_adj (ai, itp); + if (itp->itp_flags & IPSEC_PROTECT_ITF) + ipsec_itf_adj_stack (ai, itp->itp_out_sa); + return (ADJ_WALK_RC_CONTINUE); } @@ -349,9 +359,14 @@ ipsec_tun_protect_rx_db_remove (ipsec_main_t * im, static adj_walk_rc_t ipsec_tun_protect_adj_remove (adj_index_t ai, void *arg) { + ipsec_tun_protect_t *itp = arg; + adj_delegate_remove (ai, ipsec_tun_adj_delegate_type); ipsec_tun_protect_add_adj (ai, NULL); + if (itp->itp_flags & IPSEC_PROTECT_ITF) + ipsec_itf_adj_unstack (ai); + return (ADJ_WALK_RC_CONTINUE); } @@ -404,8 +419,11 @@ ipsec_tun_protect_set_crypto_addr (ipsec_tun_protect_t * itp) { itp->itp_crypto.src = sa->tunnel_dst_addr; itp->itp_crypto.dst = sa->tunnel_src_addr; - ipsec_sa_set_IS_PROTECT (sa); - itp->itp_flags |= IPSEC_PROTECT_ENCAPED; + if (!(itp->itp_flags & IPSEC_PROTECT_ITF)) + { + ipsec_sa_set_IS_PROTECT (sa); + itp->itp_flags |= IPSEC_PROTECT_ENCAPED; + } } else { @@ -657,6 +675,7 @@ ipsec_tun_protect_update (u32 sw_if_index, pool_get_zero (ipsec_tun_protect_pool, itp); itp->itp_sw_if_index = sw_if_index; + itp->itp_ai = ADJ_INDEX_INVALID; itp->itp_n_sa_in = vec_len (sas_in); for (ii = 0; ii < itp->itp_n_sa_in; ii++) @@ -673,7 +692,24 @@ ipsec_tun_protect_update (u32 sw_if_index, if (rv) goto out; - if (ip46_address_is_zero (&itp->itp_tun.dst)) + if (ip46_address_is_zero (&itp->itp_tun.src)) + { + /* must be one of thos pesky ipsec interfaces that has no encap. + * the encap then MUST comefrom the tunnel mode SA. + */ + ipsec_sa_t *sa; + + sa = ipsec_sa_get (itp->itp_out_sa); + + if (!ipsec_sa_is_set_IS_TUNNEL (sa)) + { + rv = VNET_API_ERROR_INVALID_DST_ADDRESS; + goto out; + } + + itp->itp_flags |= IPSEC_PROTECT_ITF; + } + else if (ip46_address_is_zero (&itp->itp_tun.dst)) { /* tunnel has no destination address, presumably because it's p2mp in which case we use the nh that this is protection for */ @@ -690,7 +726,7 @@ ipsec_tun_protect_update (u32 sw_if_index, /* * add to the tunnel DB for ingress - * - if the SA is in trasnport mode, then the packates will arrivw + * - if the SA is in trasnport mode, then the packates will arrive * with the IP src,dst of the protected tunnel, in which case we can * simply strip the IP header and hand the payload to the protocol * appropriate input handler @@ -752,6 +788,9 @@ ipsec_tun_protect_del (u32 sw_if_index, const ip_address_t * nh) itp = ipsec_tun_protect_get (itpi); ipsec_tun_protect_unconfig (im, itp); + if (ADJ_INDEX_INVALID != itp->itp_ai) + adj_unlock (itp->itp_ai); + clib_mem_free (itp->itp_key); pool_put (ipsec_tun_protect_pool, itp); @@ -828,13 +867,7 @@ ipsec_tun_protect_adj_delegate_adj_created (adj_index_t ai) itpi = ipsec_tun_protect_find (adj->rewrite_header.sw_if_index, &ip); if (INDEX_INVALID != itpi) - { - const ipsec_tun_protect_t *itp; - - itp = ipsec_tun_protect_get (itpi); - adj_delegate_add (adj_get (ai), ipsec_tun_adj_delegate_type, itpi); - ipsec_tun_protect_add_adj (ai, itp); - } + ipsec_tun_protect_adj_add (ai, ipsec_tun_protect_get (itpi)); } static u8 * |