summaryrefslogtreecommitdiff
path: root/bgpd/bgp_flowspec_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_flowspec_util.c')
-rw-r--r--bgpd/bgp_flowspec_util.c99
1 files changed, 85 insertions, 14 deletions
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 764d2f87ae..90e9236385 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -76,6 +76,7 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
return ret;
}
+
bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
struct prefix *input, int prefix_check)
{
@@ -84,6 +85,7 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
int ret = 0, error = 0;
uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
size_t len = pfs->u.prefix_flowspec.prefixlen;
+ afi_t afi = family2afi(pfs->u.prefix_flowspec.family);
struct prefix compare;
error = 0;
@@ -98,7 +100,8 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
nlri_content+offset,
len - offset,
- &compare, &error);
+ &compare, &error,
+ afi, NULL);
if (ret <= 0)
break;
if (prefix_check &&
@@ -115,6 +118,16 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
&compare.u.prefix6.s6_addr))
return true;
break;
+ case FLOWSPEC_FLOW_LABEL:
+ if (afi == AFI_IP) {
+ error = -1;
+ continue;
+ }
+ ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
+ nlri_content+offset,
+ len - offset,
+ NULL, &error);
+ break;
case FLOWSPEC_IP_PROTOCOL:
case FLOWSPEC_PORT:
case FLOWSPEC_DEST_PORT:
@@ -158,13 +171,16 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
uint8_t *nlri_ptr,
uint32_t max_len,
- void *result, int *error)
+ void *result, int *error,
+ 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));
@@ -172,8 +188,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;
@@ -189,11 +210,30 @@ 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) {
+ 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:
@@ -417,7 +457,8 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
}
int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
- struct bgp_pbr_entry_main *bpem)
+ struct bgp_pbr_entry_main *bpem,
+ afi_t afi)
{
int offset = 0, error = 0;
struct prefix *prefix;
@@ -425,6 +466,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];
@@ -436,15 +478,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);
+ prefix, &error,
+ afi, prefix_offset);
if (error < 0)
flog_err(EC_BGP_FLOWSPEC_PACKET,
"%s: flowspec_ip_address error %d",
@@ -456,11 +501,30 @@ 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;
}
offset += ret;
break;
+ case FLOWSPEC_FLOW_LABEL:
+ if (afi == AFI_IP) {
+ error = -1;
+ continue;
+ }
+ match_num = &(bpem->match_flowlabel_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->flow_label);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_IP_PROTOCOL:
match_num = &(bpem->match_protocol_num);
mval = (struct bgp_pbr_match_val *)
@@ -583,7 +647,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
bpem->match_packet_length_num || bpem->match_icmp_code_num ||
bpem->match_icmp_type_num || bpem->match_port_num ||
bpem->match_src_port_num || bpem->match_dst_port_num ||
- bpem->match_protocol_num || bpem->match_bitmask)
+ bpem->match_protocol_num || bpem->match_bitmask ||
+ bpem->match_flowlabel_num)
bpem->type = BGP_PBR_IPSET;
else if ((bpem->match_bitmask_iprule & PREFIX_SRC_PRESENT) ||
(bpem->match_bitmask_iprule & PREFIX_DST_PRESENT))
@@ -599,7 +664,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
/* return 1 if FS entry invalid or no NH IP */
bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
- struct prefix *p)
+ struct prefix *p, afi_t afi)
{
struct bgp_pbr_entry_main api;
int i;
@@ -615,9 +680,15 @@ bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
api_action = &api.actions[i];
if (api_action->action != ACTION_REDIRECT_IP)
continue;
- p->family = AF_INET;
- p->prefixlen = IPV4_MAX_BITLEN;
- p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+ p->family = afi2family(afi);
+ if (afi == AFI_IP) {
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+ } else {
+ p->prefixlen = IPV6_MAX_BITLEN;
+ memcpy(&p->u.prefix6, &api_action->u.zr.redirect_ip_v6,
+ sizeof(struct in6_addr));
+ }
return false;
}
return true;