summaryrefslogtreecommitdiffstats
path: root/src/vnet/ip/ip6_to_ip4.h
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2021-11-23 15:55:39 +0100
committerDamjan Marion <dmarion@me.com>2021-12-03 09:35:30 +0000
commit03092c1982468ff6ffe260b0215f910d4c486b04 (patch)
tree0d58999070b677d38e2aa2f5da4341383beedbb3 /src/vnet/ip/ip6_to_ip4.h
parent2008912b56abbf3167faf9b787df76605684d9e1 (diff)
ip: extension header parsing fails for fragment header
Refactor and improve boundary checking on IPv6 extension header handling. Limit parsing of IPv6 extension headers to a maximum of 4 headers and a depth of 256 bytes. Type: fix Signed-off-by: Ole Troan <ot@cisco.com> Change-Id: Ide40aaa2b482ceef7e92f02fa0caeadb3b8f7556 Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/vnet/ip/ip6_to_ip4.h')
-rw-r--r--src/vnet/ip/ip6_to_ip4.h54
1 files changed, 19 insertions, 35 deletions
diff --git a/src/vnet/ip/ip6_to_ip4.h b/src/vnet/ip/ip6_to_ip4.h
index 6a533e3b54e..b1b5bdb2d11 100644
--- a/src/vnet/ip/ip6_to_ip4.h
+++ b/src/vnet/ip/ip6_to_ip4.h
@@ -62,41 +62,25 @@ static u8 icmp6_to_icmp_updater_pointer_table[] =
* @returns 0 on success, non-zero value otherwise.
*/
static_always_inline int
-ip6_parse (vlib_main_t * vm, vlib_buffer_t * b, const ip6_header_t * ip6,
- u32 buff_len, u8 * l4_protocol, u16 * l4_offset,
- u16 * frag_hdr_offset)
+ip6_parse (vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6, u32 buff_len,
+ u8 *l4_protocol, u16 *l4_offset, u16 *frag_hdr_offset)
{
- ip6_ext_header_t *last_hdr, *frag_hdr;
- u32 length;
- if (ip6_walk_ext_hdr
- (vm, b, ip6, IP_PROTOCOL_IPV6_FRAGMENTATION, &length, &frag_hdr,
- &last_hdr))
+ ip6_ext_hdr_chain_t hdr_chain;
+ int res =
+ ip6_ext_header_walk (b, ip6, IP_PROTOCOL_IPV6_FRAGMENTATION, &hdr_chain);
+ if (res < 0)
{
return -1;
}
-
- if (length > 0)
- {
- if (frag_hdr)
- {
- *frag_hdr_offset = (u8 *) frag_hdr - (u8 *) ip6;
- }
- else
- {
- *frag_hdr_offset = 0;
- }
- *l4_protocol = last_hdr->next_hdr;
- }
+ if (hdr_chain.eh[res].protocol == IP_PROTOCOL_IPV6_FRAGMENTATION)
+ *frag_hdr_offset = hdr_chain.eh[res].offset;
else
- {
- *frag_hdr_offset = 0;
- *l4_protocol = ip6->protocol;
- }
- *l4_offset = sizeof (*ip6) + length;
+ *frag_hdr_offset = 0;
- return (buff_len < (*l4_offset + 4)) ||
- (clib_net_to_host_u16 (ip6->payload_length) <
- (*l4_offset + 4 - sizeof (*ip6)));
+ *l4_protocol = hdr_chain.eh[hdr_chain.length - 1].protocol;
+ *l4_offset = hdr_chain.eh[hdr_chain.length - 1].offset;
+
+ return 0;
}
/**
@@ -124,13 +108,13 @@ ip6_get_port (vlib_main_t * vm, vlib_buffer_t * b, ip6_header_t * ip6,
u16 frag_offset;
u8 *l4;
- if (ip6_parse
- (vm, b, ip6, buffer_len, &l4_protocol, &l4_offset, &frag_offset))
- return 0;
-
+ if (ip6_parse (vm, b, ip6, buffer_len, &l4_protocol, &l4_offset,
+ &frag_offset))
+ {
+ return 0;
+ }
if (frag_offset &&
- ip6_frag_hdr_offset (((ip6_frag_hdr_t *)
- u8_ptr_add (ip6, frag_offset))))
+ ip6_frag_hdr_offset (((ip6_frag_hdr_t *) u8_ptr_add (ip6, frag_offset))))
return 0; //Can't deal with non-first fragment for now
if (ip_protocol)