diff options
Diffstat (limited to 'src/vnet/ipsec/esp_decrypt.c')
-rw-r--r-- | src/vnet/ipsec/esp_decrypt.c | 120 |
1 files changed, 102 insertions, 18 deletions
diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c index 710c8f17762..48f08f42e33 100644 --- a/src/vnet/ipsec/esp_decrypt.c +++ b/src/vnet/ipsec/esp_decrypt.c @@ -22,12 +22,12 @@ #include <vnet/ipsec/ipsec.h> #include <vnet/ipsec/esp.h> #include <vnet/ipsec/ipsec_io.h> +#include <vnet/ipsec/ipsec_tun.h> #define foreach_esp_decrypt_next \ _(DROP, "error-drop") \ _(IP4_INPUT, "ip4-input-no-checksum") \ -_(IP6_INPUT, "ip6-input") \ -_(IPSEC_GRE_INPUT, "ipsec-gre-input") +_(IP6_INPUT, "ip6-input") #define _(v, s) ESP_DECRYPT_NEXT_##v, typedef enum @@ -93,7 +93,7 @@ typedef struct { u8 icv_sz; u8 iv_sz; - ipsec_sa_flags_t flags:8; + ipsec_sa_flags_t flags; u32 sa_index; }; u64 sa_data; @@ -111,7 +111,7 @@ STATIC_ASSERT_SIZEOF (esp_decrypt_packet_data_t, 2 * sizeof (u64)); always_inline uword esp_decrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, - int is_ip6) + int is_ip6, int is_tun) { ipsec_main_t *im = &ipsec_main; u32 thread_index = vm->thread_index; @@ -378,7 +378,7 @@ esp_decrypt_inline (vlib_main_t * vm, u16 adv = pd->iv_sz + esp_sz; u16 tail = sizeof (esp_footer_t) + f->pad_length + pd->icv_sz; - if ((pd->flags & tun_flags) == 0) /* transport mode */ + if ((pd->flags & tun_flags) == 0 && !is_tun) /* transport mode */ { u8 udp_sz = (is_ip6 == 0 && pd->flags & IPSEC_SA_FLAG_UDP_ENCAP) ? sizeof (udp_header_t) : 0; @@ -437,12 +437,50 @@ esp_decrypt_inline (vlib_main_t * vm, { next[0] = ESP_DECRYPT_NEXT_DROP; b[0]->error = node->errors[ESP_DECRYPT_ERROR_DECRYPTION_FAILED]; + goto trace; + } + if (is_tun) + { + if (ipsec_sa_is_set_IS_PROTECT (sa0)) + { + /* + * Check that the reveal IP header matches that + * of the tunnel we are protecting + */ + const ipsec_tun_protect_t *itp; + + itp = + ipsec_tun_protect_get (vnet_buffer (b[0])-> + ipsec.protect_index); + if (PREDICT_TRUE (f->next_header == IP_PROTOCOL_IP_IN_IP)) + { + const ip4_header_t *ip4; + + ip4 = vlib_buffer_get_current (b[0]); + + if (!ip46_address_is_equal_v4 (&itp->itp_tun.src, + &ip4->dst_address) || + !ip46_address_is_equal_v4 (&itp->itp_tun.dst, + &ip4->src_address)) + next[0] = ESP_DECRYPT_NEXT_DROP; + + } + else if (f->next_header == IP_PROTOCOL_IPV6) + { + const ip6_header_t *ip6; + + ip6 = vlib_buffer_get_current (b[0]); + + if (!ip46_address_is_equal_v6 (&itp->itp_tun.src, + &ip6->dst_address) || + !ip46_address_is_equal_v6 (&itp->itp_tun.dst, + &ip6->src_address)) + next[0] = ESP_DECRYPT_NEXT_DROP; + } + } } } - if (PREDICT_FALSE (ipsec_sa_is_set_IS_GRE (sa0))) - next[0] = ESP_DECRYPT_NEXT_IPSEC_GRE_INPUT; - trace: if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED)) { @@ -477,7 +515,28 @@ VLIB_NODE_FN (esp4_decrypt_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - return esp_decrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ ); + return esp_decrypt_inline (vm, node, from_frame, 0, 0); +} + +VLIB_NODE_FN (esp4_decrypt_tun_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return esp_decrypt_inline (vm, node, from_frame, 0, 1); +} + +VLIB_NODE_FN (esp6_decrypt_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return esp_decrypt_inline (vm, node, from_frame, 1, 0); +} + +VLIB_NODE_FN (esp6_decrypt_tun_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return esp_decrypt_inline (vm, node, from_frame, 1, 1); } /* *INDENT-OFF* */ @@ -497,16 +556,7 @@ VLIB_REGISTER_NODE (esp4_decrypt_node) = { #undef _ }, }; -/* *INDENT-ON* */ -VLIB_NODE_FN (esp6_decrypt_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return esp_decrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ ); -} - -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (esp6_decrypt_node) = { .name = "esp6-decrypt", .vector_size = sizeof (u32), @@ -523,6 +573,40 @@ VLIB_REGISTER_NODE (esp6_decrypt_node) = { #undef _ }, }; + +VLIB_REGISTER_NODE (esp4_decrypt_tun_node) = { + .name = "esp4-decrypt-tun", + .vector_size = sizeof (u32), + .format_trace = format_esp_decrypt_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(esp_decrypt_error_strings), + .error_strings = esp_decrypt_error_strings, + + .n_next_nodes = ESP_DECRYPT_N_NEXT, + .next_nodes = { +#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n, + foreach_esp_decrypt_next +#undef _ + }, +}; + +VLIB_REGISTER_NODE (esp6_decrypt_tun_node) = { + .name = "esp6-decrypt-tun", + .vector_size = sizeof (u32), + .format_trace = format_esp_decrypt_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(esp_decrypt_error_strings), + .error_strings = esp_decrypt_error_strings, + + .n_next_nodes = ESP_DECRYPT_N_NEXT, + .next_nodes = { +#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n, + foreach_esp_decrypt_next +#undef _ + }, +}; /* *INDENT-ON* */ /* |