diff options
Diffstat (limited to 'src/plugins/snat/out2in.c')
-rw-r--r-- | src/plugins/snat/out2in.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/src/plugins/snat/out2in.c b/src/plugins/snat/out2in.c index f0555a1b2d3..7de85eb3cb5 100644 --- a/src/plugins/snat/out2in.c +++ b/src/plugins/snat/out2in.c @@ -86,7 +86,7 @@ vlib_node_registration_t snat_det_out2in_node; #define foreach_snat_out2in_error \ _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ _(OUT2IN_PACKETS, "Good out2in packets processed") \ -_(BAD_ICMP_TYPE, "icmp type not echo-reply") \ +_(BAD_ICMP_TYPE, "unsupported ICMP type") \ _(NO_TRANSLATION, "No translation") typedef enum { @@ -324,6 +324,7 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, snat_session_t *s0 = 0; u8 dont_translate = 0; clib_bihash_kv_8_8_t kv0, value0; + u8 is_addr_only; u32 next0 = ~0; int err; @@ -347,7 +348,7 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, { /* Try to match static mapping by external address and port, destination address and port in packet */ - if (snat_static_mapping_match(sm, key0, &sm0, 1)) + if (snat_static_mapping_match(sm, key0, &sm0, 1, &is_addr_only)) { /* Don't NAT packet aimed at the intfc address */ if (is_interface_addr(sm, node, sw_if_index0, @@ -361,8 +362,10 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, goto out; } - if (icmp_is_error_message (icmp0)) + if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply && + (icmp0->type != ICMP4_echo_request || !is_addr_only))) { + b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE]; next0 = SNAT_OUT2IN_NEXT_DROP; goto out; } @@ -378,8 +381,19 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, } } else - s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, - value0.value); + { + if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply && + icmp0->type != ICMP4_echo_request && + !icmp_is_error_message (icmp0))) + { + b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE]; + next0 = SNAT_OUT2IN_NEXT_DROP; + goto out; + } + + s0 = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions, + value0.value); + } out: *p_key = key0; @@ -410,15 +424,18 @@ u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u8 *p_dont_translate, void *d) { ip4_header_t *ip0; + icmp46_header_t *icmp0; u32 sw_if_index0; u32 rx_fib_index0; snat_session_key_t key0; snat_session_key_t sm0; u8 dont_translate = 0; + u8 is_addr_only; u32 next0 = ~0; int err; ip0 = vlib_buffer_get_current (b0); + icmp0 = (icmp46_header_t *) ip4_next_header (ip0); sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0); @@ -431,7 +448,7 @@ u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, } key0.fib_index = rx_fib_index0; - if (snat_static_mapping_match(sm, key0, &sm0, 1)) + if (snat_static_mapping_match(sm, key0, &sm0, 1, &is_addr_only)) { /* Don't NAT packet aimed at the intfc address */ if (is_interface_addr(sm, node, sw_if_index0, ip0->dst_address.as_u32)) @@ -444,6 +461,15 @@ u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, goto out; } + if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply && + (icmp0->type != ICMP4_echo_request || !is_addr_only) && + !icmp_is_error_message (icmp0))) + { + b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE]; + next0 = SNAT_OUT2IN_NEXT_DROP; + goto out; + } + out: *p_value = sm0; out2: @@ -484,14 +510,6 @@ static inline u32 icmp_out2in (snat_main_t *sm, if (next0 == SNAT_OUT2IN_NEXT_DROP || dont_translate) goto out; - if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply && - !icmp_is_error_message (icmp0))) - { - b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE]; - next0 = SNAT_OUT2IN_NEXT_DROP; - goto out; - } - sum0 = ip_incremental_checksum (0, icmp0, ntohs(ip0->length) - ip4_header_bytes (ip0)); checksum0 = ~ip_csum_fold (sum0); @@ -727,7 +745,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { /* Try to match static mapping by external address and port, destination address and port in packet */ - if (snat_static_mapping_match(sm, key0, &sm0, 1)) + if (snat_static_mapping_match(sm, key0, &sm0, 1, 0)) { b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; /* @@ -862,7 +880,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { /* Try to match static mapping by external address and port, destination address and port in packet */ - if (snat_static_mapping_match(sm, key1, &sm1, 1)) + if (snat_static_mapping_match(sm, key1, &sm1, 1, 0)) { b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; /* @@ -1031,7 +1049,7 @@ snat_out2in_node_fn (vlib_main_t * vm, { /* Try to match static mapping by external address and port, destination address and port in packet */ - if (snat_static_mapping_match(sm, key0, &sm0, 1)) + if (snat_static_mapping_match(sm, key0, &sm0, 1, 0)) { b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; /* @@ -1816,7 +1834,7 @@ snat_out2in_fast_node_fn (vlib_main_t * vm, key0.port = udp0->dst_port; key0.fib_index = rx_fib_index0; - if (snat_static_mapping_match(sm, key0, &sm0, 1)) + if (snat_static_mapping_match(sm, key0, &sm0, 1, 0)) { b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION]; goto trace00; |