diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2019-10-16 08:42:30 +0200 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2020-08-21 13:37:08 +0200 |
commit | 9cec4121623c18eb5d826420e2078e2a78242362 (patch) | |
tree | 345c4ced2b1c8a527dc8dd11e7a2b2e0c2c71599 /bgpd/bgp_flowspec_util.c | |
parent | bgpd: flowspec code support for ipv6 (diff) | |
download | frr-9cec4121623c18eb5d826420e2078e2a78242362.tar.xz frr-9cec4121623c18eb5d826420e2078e2a78242362.zip |
bgpd: ipv6 flowspec address decoding and validation
as per [0], ipv6 adress format introduces an ipv6 offset that needs to
be extracted too. The change include the validation, decoding for
further usage with policy-routing and decoding for dumping.
[0] https://tools.ietf.org/html/draft-ietf-idr-flow-spec-v6-09
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'bgpd/bgp_flowspec_util.c')
-rw-r--r-- | bgpd/bgp_flowspec_util.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 0e879e816..2dd35696d 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -101,7 +101,7 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs, nlri_content+offset, len - offset, &compare, &error, - afi); + afi, NULL); if (ret <= 0) break; if (prefix_check && @@ -162,13 +162,15 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, uint8_t *nlri_ptr, uint32_t max_len, void *result, int *error, - afi_t afi) + afi_t afi, + uint8_t *ipv6_offset) { char *display = (char *)result; /* for return_string */ struct prefix *prefix = (struct prefix *)result; uint32_t offset = 0; struct prefix prefix_local; int psize; + uint8_t prefix_offset = 0; *error = 0; memset(&prefix_local, 0, sizeof(struct prefix)); @@ -176,8 +178,13 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, prefix_local.prefixlen = nlri_ptr[offset]; psize = PSIZE(prefix_local.prefixlen); offset++; - /* TODO Flowspec IPv6 Support */ - prefix_local.family = AF_INET; + prefix_local.family = afi2family(afi); + if (prefix_local.family == AF_INET6) { + prefix_offset = nlri_ptr[offset]; + if (ipv6_offset) + *ipv6_offset = prefix_offset; + offset++; + } /* Prefix length check. */ if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8) *error = -1; @@ -193,11 +200,28 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, offset += psize; switch (type) { case BGP_FLOWSPEC_RETURN_STRING: - prefix2str(&prefix_local, display, - BGP_FLOWSPEC_STRING_DISPLAY_MAX); + if (prefix_local.family == AF_INET6) { + char str[BGP_FLOWSPEC_STRING_DISPLAY_MAX]; + int ret; + + prefix2str(&prefix_local, str, + BGP_FLOWSPEC_STRING_DISPLAY_MAX); + ret = snprintf(display, BGP_FLOWSPEC_STRING_DISPLAY_MAX, + "%s/off %u", + str, prefix_offset); + if (ret < 0) { + *error = -1; + break; + } + } else + prefix2str(&prefix_local, display, + BGP_FLOWSPEC_STRING_DISPLAY_MAX); break; case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE: - PREFIX_COPY_IPV4(prefix, &prefix_local) + if (prefix_local.family == AF_INET) + PREFIX_COPY_IPV4(prefix, &prefix_local) + else + PREFIX_COPY_IPV6(prefix, &prefix_local) break; case BGP_FLOWSPEC_VALIDATE_ONLY: default: @@ -430,6 +454,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, uint8_t *match_num; uint8_t bitmask = 0; int ret = 0, type; + uint8_t *prefix_offset; while (offset < len - 1 && error >= 0) { type = nlri_content[offset]; @@ -441,16 +466,18 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, if (type == FLOWSPEC_DEST_PREFIX) { bitmask |= PREFIX_DST_PRESENT; prefix = &bpem->dst_prefix; + prefix_offset = &bpem->dst_prefix_offset; } else { bitmask |= PREFIX_SRC_PRESENT; prefix = &bpem->src_prefix; + prefix_offset = &bpem->src_prefix_offset; } ret = bgp_flowspec_ip_address( BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE, nlri_content + offset, len - offset, prefix, &error, - afi); + afi, prefix_offset); if (error < 0) flog_err(EC_BGP_FLOWSPEC_PACKET, "%s: flowspec_ip_address error %d", @@ -462,6 +489,11 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, if (prefix->family == AF_INET && prefix->u.prefix4.s_addr == INADDR_ANY) bpem->match_bitmask_iprule |= bitmask; + else if (prefix->family == AF_INET6 + && !memcmp(&prefix->u.prefix6, + &in6addr_any, + sizeof(struct in6_addr))) + bpem->match_bitmask_iprule |= bitmask; else bpem->match_bitmask |= bitmask; } |