diff options
author | 2025-02-06 09:00:47 +0000 | |
---|---|---|
committer | 2025-02-18 09:15:06 +0000 | |
commit | 0b04d71ce78d7ab7a9b2d6f323431cf14f9ed848 (patch) | |
tree | d03f327e8034c212becc8bb121a1b77d65bc4f32 /src/vnet/ipsec | |
parent | 9ab79f54da29f391019ede4436896d8c5e66d6b8 (diff) |
ipsec: enable support for ipv6 udp ipsec encapsulation in policy mode
IPSec traffic may be sent encapsulated inside UDP packagaes.
In case of esp packgaes decryption is required (according to defined policies),
whereas IKE traffic should be bypassed (relevant policy needs to be defined).
With this patch required behaviour is provided.
Type: feature
Change-Id: If99c7bf121db881c0bdf2b45e6fdca87c0d872a5
Signed-off-by: Piotr Bronowski <piotrx.bronowski@intel.com>
Diffstat (limited to 'src/vnet/ipsec')
-rw-r--r-- | src/vnet/ipsec/ipsec_input.c | 81 |
1 files changed, 49 insertions, 32 deletions
diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index a1ee83d0d74..a20c8317144 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -854,39 +854,43 @@ ipsec6_esp_packet_process (vlib_main_t *vm, ipsec_main_t *im, &tuples[0], &ip0->src_address, &ip0->dst_address, clib_net_to_host_u32 (esp0->spi), IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT); - if (im->fp_spd_ipv6_in_is_enabled && - PREDICT_TRUE (INDEX_INVALID != spd0->fp_spd.ip6_in_lookup_hash_idx)) - { - ipsec_fp_in_policy_match_n (&spd0->fp_spd, ip_v6, tuples, policies, 1); - p0 = policies[0]; - } - else /* linear search if fast path is not enabled */ + if (esp0->spi != 0) { - p0 = ipsec6_input_protect_policy_match ( - spd0, &ip0->src_address, &ip0->dst_address, - clib_net_to_host_u32 (esp0->spi)); - } - has_space0 = vlib_buffer_has_space (b[0], (clib_address_t) (esp0 + 1) - - (clib_address_t) ip0); + if (im->fp_spd_ipv6_in_is_enabled && + PREDICT_TRUE (INDEX_INVALID != spd0->fp_spd.ip6_in_lookup_hash_idx)) + { + ipsec_fp_in_policy_match_n (&spd0->fp_spd, ip_v6, tuples, policies, + 1); + p0 = policies[0]; + } + else /* linear search if fast path is not enabled */ + { + p0 = ipsec6_input_protect_policy_match ( + spd0, &ip0->src_address, &ip0->dst_address, + clib_net_to_host_u32 (esp0->spi)); + } + has_space0 = vlib_buffer_has_space (b[0], (clib_address_t) (esp0 + 1) - + (clib_address_t) ip0); - if (PREDICT_TRUE ((p0 != NULL) && (has_space0))) - { - *ipsec_matched += 1; + if (PREDICT_TRUE ((p0 != NULL) && (has_space0))) + { + *ipsec_matched += 1; - pi0 = p0 - im->policies; - vlib_increment_combined_counter ( - &ipsec_spd_policy_counters, thread_index, pi0, 1, - clib_net_to_host_u16 (ip0->payload_length)); + pi0 = p0 - im->policies; + vlib_increment_combined_counter ( + &ipsec_spd_policy_counters, thread_index, pi0, 1, + clib_net_to_host_u16 (ip0->payload_length)); - vnet_buffer (b[0])->ipsec.sad_index = p0->sa_index; - next[0] = im->esp6_decrypt_next_index; - vlib_buffer_advance (b[0], ((u8 *) esp0 - (u8 *) ip0)); - goto trace0; - } - else - { - p0 = NULL; - pi0 = ~0; + vnet_buffer (b[0])->ipsec.sad_index = p0->sa_index; + next[0] = im->esp6_decrypt_next_index; + vlib_buffer_advance (b[0], ((u8 *) esp0 - (u8 *) ip0)); + goto trace0; + } + else + { + p0 = NULL; + pi0 = ~0; + } } if (im->fp_spd_ipv6_in_is_enabled && @@ -999,7 +1003,6 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, ip4_ipsec_config_t *c0; ipsec_spd_t *spd0; ipsec_policy_t *p0 = 0; - ah_header_t *ah0; u32 header_size = sizeof (ip0[0]); u64 ipsec_unprocessed = 0, ipsec_matched = 0; u64 ipsec_dropped = 0, ipsec_bypassed = 0; @@ -1018,9 +1021,21 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, spd0 = pool_elt_at_index (im->spds, c0->spd_index); ip0 = vlib_buffer_get_current (b0); - ah0 = (ah_header_t *) ((u8 *) ip0 + header_size); - if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) + if (ip0->protocol == IP_PROTOCOL_UDP) + { + udp_header_t *udp0 = (udp_header_t *) ((u8 *) ip0 + header_size); + + /* RFC5996 Section 2.23: "Port 4500 is reserved for + * UDP-encapsulated ESP and IKE." + * RFC5996 Section 3.1: "IKE messages use UDP ports 500 and/or + 4500" + */ + if ((clib_host_to_net_u16 (500) == udp0->dst_port) || + (clib_host_to_net_u16 (4500) == udp0->dst_port)) + esp0 = (esp_header_t *) ((u8 *) udp0 + sizeof (udp_header_t)); + } + else if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) esp0 = (esp_header_t *) ((u8 *) ip0 + header_size); if (esp0 != NULL) @@ -1032,6 +1047,8 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, } else if (ip0->protocol == IP_PROTOCOL_IPSEC_AH) { + ah_header_t *ah0 = (ah_header_t *) ((u8 *) ip0 + header_size); + p0 = ipsec6_input_protect_policy_match ( spd0, &ip0->src_address, &ip0->dst_address, clib_net_to_host_u32 (ah0->spi)); |