diff options
author | Vladimir Ratnikov <vratnikov@netgate.com> | 2020-01-14 09:48:31 -0500 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2020-01-28 08:14:36 +0000 |
commit | 0d4a61216c2329eec5167d0411481431037ac5c1 (patch) | |
tree | e58415cb89d3603b03f67904d7b0467e6b185e16 /src/plugins/map | |
parent | e9595dba26b32abb673f74b777429ae5640dc325 (diff) |
map: ip4-map-t more RFC compliant
When MTU is not set, ignore_df and mtu check
always returns true and packets are dropped.
This patch puts MTU checks after it was
compared with 0 and set to maximum if not set.
Added trace node.
If MTU is less than the total length value of
the IPv4 packet plus 20, the translator MUST
send an ICMPv4 "Fragmentation Needed" error message
to the IPv4 source address
Type: fix
Fixes: 87663cdf644fb7c94c0fec9460829b7e4e7c35ca
Signed-off-by: Vladimir Ratnikov <vratnikov@netgate.com>
Change-Id: I35b99bc2648984cdbf5b6a57ddec91c586b15bef
Diffstat (limited to 'src/plugins/map')
-rw-r--r-- | src/plugins/map/ip4_map_t.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/plugins/map/ip4_map_t.c b/src/plugins/map/ip4_map_t.c index dca32846480..d243a45cd41 100644 --- a/src/plugins/map/ip4_map_t.c +++ b/src/plugins/map/ip4_map_t.c @@ -22,6 +22,7 @@ typedef enum IP4_MAPT_NEXT_MAPT_TCP_UDP, IP4_MAPT_NEXT_MAPT_ICMP, IP4_MAPT_NEXT_MAPT_FRAGMENTED, + IP4_MAPT_NEXT_ICMP_ERROR, IP4_MAPT_NEXT_DROP, IP4_MAPT_N_NEXT } ip4_mapt_next_t; @@ -575,21 +576,31 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) goto exit; } + dst_port0 = -1; + bool df0 = ip40->flags_and_fragment_offset & clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT); + vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0; + if (PREDICT_FALSE - (df0 && !map_main.frag_ignore_df && (ip4_len0 > d0->mtu))) + (df0 && !map_main.frag_ignore_df + && + ((ip4_len0 + + (sizeof (ip6_header_t) - sizeof (ip4_header_t))) > + vnet_buffer (p0)->map_t.mtu))) { - p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED]; - next0 = IP4_MAPT_NEXT_DROP; - goto exit; + icmp4_error_set_vnet_buffer (p0, ICMP4_destination_unreachable, + ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, + vnet_buffer (p0)->map_t.mtu - + (sizeof (ip6_header_t) - + sizeof (ip4_header_t))); + p0->error = error_node->errors[MAP_ERROR_DF_SET]; + next0 = IP4_MAPT_NEXT_ICMP_ERROR; + goto trace; } - vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0; - - dst_port0 = -1; ip4_map_t_classify (p0, d0, ip40, ip4_len0, &dst_port0, &error0, &next0, l4_dst_port); @@ -626,7 +637,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) next0 = (error0 != MAP_ERROR_NONE) ? IP4_MAPT_NEXT_DROP : next0; p0->error = error_node->errors[error0]; - + trace: if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED)) { map_add_trace (vm, node, p0, d0 - map_main.domains, dst_port0); @@ -730,6 +741,7 @@ VLIB_REGISTER_NODE(ip4_map_t_node) = { [IP4_MAPT_NEXT_MAPT_TCP_UDP] = "ip4-map-t-tcp-udp", [IP4_MAPT_NEXT_MAPT_ICMP] = "ip4-map-t-icmp", [IP4_MAPT_NEXT_MAPT_FRAGMENTED] = "ip4-map-t-fragmented", + [IP4_MAPT_NEXT_ICMP_ERROR] = "ip4-icmp-error", [IP4_MAPT_NEXT_DROP] = "error-drop", }, }; |