From c8e294b0108c0888b824395b814e2ee1dab6cdb6 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 8 Nov 2017 00:18:15 -0800 Subject: NAT64: fixed csum crash (VPP-1055) Change-Id: I28c8abe49c9858966a66530d3dc41c074c6901f3 Signed-off-by: Matus Fabian --- src/vnet/ip/ip4_to_ip6.h | 18 ++++++------------ src/vnet/ip/ip6_to_ip4.h | 35 +++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/vnet/ip/ip4_to_ip6.h b/src/vnet/ip/ip4_to_ip6.h index 6ffc562c842..f2ed13dc381 100644 --- a/src/vnet/ip/ip4_to_ip6.h +++ b/src/vnet/ip/ip4_to_ip6.h @@ -507,6 +507,7 @@ ip4_to_ip6_tcp_udp (vlib_buffer_t * p, ip4_to_ip6_set_fn_t fn, void *ctx) ip6_frag_hdr_t *frag; u32 frag_id; int rv; + ip4_address_t old_src, old_dst; ip4 = vlib_buffer_get_current (p); @@ -534,9 +535,8 @@ ip4_to_ip6_tcp_udp (vlib_buffer_t * p, ip4_to_ip6_set_fn_t fn, void *ctx) checksum = &tcp->checksum; } - csum = ip_csum_sub_even (*checksum, ip4->src_address.as_u32); - csum = ip_csum_sub_even (csum, ip4->dst_address.as_u32); - *checksum = ip_csum_fold (csum); + old_src.as_u32 = ip4->src_address.as_u32; + old_dst.as_u32 = ip4->dst_address.as_u32; // Deal with fragmented packets if (PREDICT_FALSE (ip4->flags_and_fragment_offset & @@ -577,7 +577,9 @@ ip4_to_ip6_tcp_udp (vlib_buffer_t * p, ip4_to_ip6_set_fn_t fn, void *ctx) if ((rv = fn (ip4, ip6, ctx)) != 0) return rv; - csum = ip_csum_add_even (*checksum, ip6->src_address.as_u64[0]); + csum = ip_csum_sub_even (*checksum, old_src.as_u32); + csum = ip_csum_sub_even (csum, old_dst.as_u32); + csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]); csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]); csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]); csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]); @@ -649,11 +651,3 @@ ip4_to_ip6 (vlib_buffer_t * p, ip4_to_ip6_set_fn_t fn, void *ctx) } #endif /* __included_ip4_to_ip6_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/ip/ip6_to_ip4.h b/src/vnet/ip/ip6_to_ip4.h index c14b46c4968..f25c9e408f0 100644 --- a/src/vnet/ip/ip6_to_ip4.h +++ b/src/vnet/ip/ip6_to_ip4.h @@ -255,6 +255,7 @@ icmp6_to_icmp (vlib_buffer_t * p, ip6_to_ip4_set_fn_t fn, void *ctx, icmp46_header_t *icmp; ip_csum_t csum; int rv; + ip6_address_t old_src, old_dst; ip6 = vlib_buffer_get_current (p); ip6_pay_len = clib_net_to_host_u16 (ip6->payload_length); @@ -325,12 +326,10 @@ icmp6_to_icmp (vlib_buffer_t * p, ip6_to_ip4_set_fn_t fn, void *ctx, return -1; } - csum = *inner_L4_checksum; - csum = ip_csum_sub_even (csum, inner_ip6->src_address.as_u64[0]); - csum = ip_csum_sub_even (csum, inner_ip6->src_address.as_u64[1]); - csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[0]); - csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[1]); - *inner_L4_checksum = ip_csum_fold (csum); + old_src.as_u64[0] = inner_ip6->src_address.as_u64[0]; + old_src.as_u64[1] = inner_ip6->src_address.as_u64[1]; + old_dst.as_u64[0] = inner_ip6->dst_address.as_u64[0]; + old_dst.as_u64[1] = inner_ip6->dst_address.as_u64[1]; if ((rv = inner_fn (inner_ip6, inner_ip4, inner_ctx)) != 0) return rv; @@ -363,6 +362,10 @@ icmp6_to_icmp (vlib_buffer_t * p, ip6_to_ip4_set_fn_t fn, void *ctx, { //Update to new pseudo-header csum = *inner_L4_checksum; + csum = ip_csum_sub_even (csum, old_src.as_u64[0]); + csum = ip_csum_sub_even (csum, old_src.as_u64[1]); + csum = ip_csum_sub_even (csum, old_dst.as_u64[0]); + csum = ip_csum_sub_even (csum, old_dst.as_u64[1]); csum = ip_csum_add_even (csum, inner_ip4->src_address.as_u32); csum = ip_csum_add_even (csum, inner_ip4->dst_address.as_u32); *inner_L4_checksum = ip_csum_fold (csum); @@ -488,6 +491,7 @@ ip6_to_ip4_tcp_udp (vlib_buffer_t * p, ip6_to_ip4_set_fn_t fn, void *ctx, u8 l4_protocol; u16 l4_offset; int rv; + ip6_address_t old_src, old_dst; ip6 = vlib_buffer_get_current (p); @@ -504,18 +508,13 @@ ip6_to_ip4_tcp_udp (vlib_buffer_t * p, ip6_to_ip4_set_fn_t fn, void *ctx, { udp_header_t *udp = ip6_next_header (ip6); checksum = &udp->checksum; - //UDP checksum is optional over IPv4 - if (!udp_checksum) - goto no_csum; } - csum = ip_csum_sub_even (*checksum, ip6->src_address.as_u64[0]); - csum = ip_csum_sub_even (csum, ip6->src_address.as_u64[1]); - csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[0]); - csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[1]); - *checksum = ip_csum_fold (csum); + old_src.as_u64[0] = ip6->src_address.as_u64[0]; + old_src.as_u64[1] = ip6->src_address.as_u64[1]; + old_dst.as_u64[0] = ip6->dst_address.as_u64[0]; + old_dst.as_u64[1] = ip6->dst_address.as_u64[1]; -no_csum: ip4 = (ip4_header_t *) u8_ptr_add (ip6, l4_offset - sizeof (*ip4)); vlib_buffer_advance (p, l4_offset - sizeof (*ip4)); @@ -554,7 +553,11 @@ no_csum: } else { - csum = ip_csum_add_even (*checksum, ip4->dst_address.as_u32); + csum = ip_csum_sub_even (*checksum, old_src.as_u64[0]); + csum = ip_csum_sub_even (csum, old_src.as_u64[1]); + csum = ip_csum_sub_even (csum, old_dst.as_u64[0]); + csum = ip_csum_sub_even (csum, old_dst.as_u64[1]); + csum = ip_csum_add_even (csum, ip4->dst_address.as_u32); csum = ip_csum_add_even (csum, ip4->src_address.as_u32); *checksum = ip_csum_fold (csum); } -- cgit 1.2.3-korg