From 0f88200247cc61175c7a1d98a3e935aedce93f3b Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 18 Nov 2019 17:44:34 +0100 Subject: BGP: Fix processing of IPv6 Flowspec During NLRI parsing of IPv6 Flowspec, dst prefix was not properly extracted from NLRI, therefore a received flow was stored in a different position in flowspec routing table, and was not reachable by command 'show route '. Add proper prefix part accessors to flowspec code and use them from BGP NLRI parsing code. Thanks to Alex D. for the bugreport. --- lib/flowspec.c | 83 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 33 deletions(-) (limited to 'lib/flowspec.c') diff --git a/lib/flowspec.c b/lib/flowspec.c index 87ce0206..e9290b88 100644 --- a/lib/flowspec.c +++ b/lib/flowspec.c @@ -112,7 +112,6 @@ get_value_length(const byte *op) } - /* * Flowspec iterators */ @@ -245,6 +244,45 @@ flow6_next_part(const byte *pos, const byte *end) } +/* + * Flowspec accessors + */ + + +static inline ip4_addr +flow_read_ip4(const byte *px, uint pxlen) +{ + ip4_addr ip = IP4_NONE; + memcpy(&ip, px, BYTES(pxlen)); + return ip4_ntoh(ip); +} + +ip4_addr +flow_read_ip4_part(const byte *part) +{ + return flow_read_ip4(part + 2, part[1]); +} + +static inline ip6_addr +flow_read_ip6(const byte *px, uint pxlen, uint pxoffset) +{ + uint floor_offset = BYTES(pxoffset - (pxoffset % 8)); + uint ceil_len = BYTES(pxlen); + ip6_addr ip = IP6_NONE; + + memcpy(((byte *) &ip) + floor_offset, px, ceil_len - floor_offset); + + return ip6_ntoh(ip); +} + +ip6_addr +flow_read_ip6_part(const byte *part) +{ + return flow_read_ip6(part + 3, part[1], part[2]); +} + + + /* * Flowspec validation */ @@ -779,26 +817,6 @@ flow_builder_set_type(struct flow_builder *fb, enum flow_type type) fb->this_type = type; } -static ip4_addr -flow_read_ip4(const byte *px, uint pxlen) -{ - ip4_addr ip = IP4_NONE; - memcpy(&ip, px, BYTES(pxlen)); - return ip4_ntoh(ip); -} - -static ip6_addr -flow_read_ip6(const byte *px, uint pxlen, uint pxoffset) -{ - uint floor_offset = BYTES(pxoffset - (pxoffset % 8)); - uint ceil_len = BYTES(pxlen); - ip6_addr ip = IP6_NONE; - - memcpy(((byte *) &ip) + floor_offset, px, ceil_len - floor_offset); - - return ip6_ntoh(ip); -} - static void builder_write_parts(struct flow_builder *fb, byte *buf) { @@ -831,9 +849,9 @@ flow_builder4_finalize(struct flow_builder *fb, linpool *lpool) if (fb->parts[FLOW_TYPE_DST_PREFIX].length) { - byte *p = fb->data.data + fb->parts[FLOW_TYPE_DST_PREFIX].offset + 1; - pxlen = *p++; - prefix = flow_read_ip4(p, pxlen); + byte *part = fb->data.data + fb->parts[FLOW_TYPE_DST_PREFIX].offset; + prefix = flow_read_ip4_part(part); + pxlen = part[1]; } *f = NET_ADDR_FLOW4(prefix, pxlen, data_len); @@ -861,10 +879,9 @@ flow_builder6_finalize(struct flow_builder *fb, linpool *lpool) if (fb->parts[FLOW_TYPE_DST_PREFIX].length) { - byte *p = fb->data.data + fb->parts[FLOW_TYPE_DST_PREFIX].offset + 1; - pxlen = *p++; - uint pxoffset = *p++; - prefix = flow_read_ip6(p, pxlen, pxoffset); + byte *part = fb->data.data + fb->parts[FLOW_TYPE_DST_PREFIX].offset; + prefix = flow_read_ip6_part(part); + pxlen = part[1]; } *n = NET_ADDR_FLOW6(prefix, pxlen, data_len); @@ -947,18 +964,18 @@ fragment_val_str(u8 val) static void net_format_flow_ip(buffer *b, const byte *part, int ipv6) { - uint pxlen = *(part+1); + uint pxlen = part[1]; if (ipv6) { - uint pxoffset = *(part+2); + uint pxoffset = part[2]; if (pxoffset) - buffer_print(b, "%I6/%u offset %u; ", flow_read_ip6(part+3,pxlen,pxoffset), pxlen, pxoffset); + buffer_print(b, "%I6/%u offset %u; ", flow_read_ip6_part(part), pxlen, pxoffset); else - buffer_print(b, "%I6/%u; ", flow_read_ip6(part+3,pxlen,0), pxlen); + buffer_print(b, "%I6/%u; ", flow_read_ip6_part(part), pxlen); } else { - buffer_print(b, "%I4/%u; ", flow_read_ip4(part+2,pxlen), pxlen); + buffer_print(b, "%I4/%u; ", flow_read_ip4_part(part), pxlen); } } -- cgit v1.2.3