1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

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 <flow>'.

Add proper prefix part accessors to flowspec code and use them from BGP
NLRI parsing code.

Thanks to Alex D. for the bugreport.
This commit is contained in:
Ondrej Zajicek (work)
2019-11-18 17:44:34 +01:00
parent 53401bef63
commit 0f88200247
4 changed files with 113 additions and 44 deletions

View File

@@ -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);
}
}