summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_flowspec_util.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-03-08 19:11:39 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-04-30 11:56:23 +0200
commit47555ee921fadc4910eebce156ea773da8d46324 (patch)
tree0ca895dec73754b9c22c265a16d74022e022006a /bgpd/bgp_flowspec_util.c
parentbgpd: add bgp_pbr_route structure (diff)
downloadfrr-47555ee921fadc4910eebce156ea773da8d46324.tar.xz
frr-47555ee921fadc4910eebce156ea773da8d46324.zip
bgpd: add convert function from flowspec to pbr match
This utility function analyses flowspec nlri and converts it into readable structures. The structure is based on bgp_pbr_match structure previously defined. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'bgpd/bgp_flowspec_util.c')
-rw-r--r--bgpd/bgp_flowspec_util.c334
1 files changed, 277 insertions, 57 deletions
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index 007b27f17..956cf28c2 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -25,6 +25,7 @@
#include "bgp_table.h"
#include "bgp_flowspec_util.h"
#include "bgp_flowspec_private.h"
+#include "bgp_pbr.h"
static void hex2bin(uint8_t *hex, int *bin)
{
@@ -50,6 +51,109 @@ static int hexstr2num(uint8_t *hexstr, int len)
return num;
}
+/* call bgp_flowspec_op_decode
+ * returns offset
+ */
+static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
+ struct bgp_pbr_match_val *mval,
+ uint8_t *match_num, int *error)
+{
+ int ret;
+
+ ret = bgp_flowspec_op_decode(
+ BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
+ nlri_content,
+ len,
+ mval, error);
+ if (*error < 0)
+ zlog_err("%s: flowspec_op_decode error %d",
+ __func__, *error);
+ else
+ *match_num = *error;
+ return ret;
+}
+
+static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
+ struct prefix *input,
+ int prefix_check)
+{
+ uint32_t offset = 0;
+ int type;
+ int ret = 0, error = 0;
+ uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
+ size_t len = pfs->u.prefix_flowspec.prefixlen;
+ struct prefix compare;
+
+ error = 0;
+ while (offset < len-1 && error >= 0) {
+ type = nlri_content[offset];
+ offset++;
+ switch (type) {
+ case FLOWSPEC_DEST_PREFIX:
+ case FLOWSPEC_SRC_PREFIX:
+ memset(&compare, 0, sizeof(struct prefix));
+ ret = bgp_flowspec_ip_address(
+ BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
+ nlri_content+offset,
+ len - offset,
+ &compare, &error);
+ if (ret <= 0)
+ break;
+ if (prefix_check &&
+ compare.prefixlen != input->prefixlen)
+ break;
+ if (compare.family != input->family)
+ break;
+ if ((input->family == AF_INET) &&
+ IPV4_ADDR_SAME(&input->u.prefix4,
+ &compare.u.prefix4))
+ return true;
+ if ((input->family == AF_INET6) &&
+ IPV6_ADDR_SAME(&input->u.prefix6.s6_addr,
+ &compare.u.prefix6.s6_addr))
+ return true;
+ break;
+ case FLOWSPEC_IP_PROTOCOL:
+ case FLOWSPEC_PORT:
+ case FLOWSPEC_DEST_PORT:
+ case FLOWSPEC_SRC_PORT:
+ case FLOWSPEC_ICMP_TYPE:
+ case FLOWSPEC_ICMP_CODE:
+ ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
+ nlri_content+offset,
+ len - offset,
+ NULL, &error);
+ break;
+ case FLOWSPEC_TCP_FLAGS:
+ ret = bgp_flowspec_tcpflags_decode(
+ BGP_FLOWSPEC_VALIDATE_ONLY,
+ nlri_content+offset,
+ len - offset,
+ NULL, &error);
+ break;
+ case FLOWSPEC_PKT_LEN:
+ case FLOWSPEC_DSCP:
+ ret = bgp_flowspec_op_decode(
+ BGP_FLOWSPEC_VALIDATE_ONLY,
+ nlri_content + offset,
+ len - offset, NULL,
+ &error);
+ break;
+ case FLOWSPEC_FRAGMENT:
+ ret = bgp_flowspec_fragment_type_decode(
+ BGP_FLOWSPEC_VALIDATE_ONLY,
+ nlri_content + offset,
+ len - offset, NULL,
+ &error);
+ break;
+ default:
+ error = -1;
+ break;
+ }
+ offset += ret;
+ }
+ return false;
+}
/*
* handle the flowspec address src/dst or generic address NLRI
@@ -122,9 +226,12 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
uint32_t offset = 0;
int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
int len_written;
+ struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
*error = 0;
do {
+ if (loop > BGP_PBR_MATCH_VAL_MAX)
+ *error = -2;
hex2bin(&nlri_ptr[offset], op);
offset++;
len = 2*op[2]+op[3];
@@ -168,7 +275,24 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
ptr += len_written;
break;
case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
- /* TODO : FS OPAQUE */
+ /* limitation: stop converting */
+ if (*error == -2)
+ break;
+ mval->value = value;
+ if (op[5] == 1)
+ mval->compare_operator |=
+ OPERATOR_COMPARE_LESS_THAN;
+ if (op[6] == 1)
+ mval->compare_operator |=
+ OPERATOR_COMPARE_GREATER_THAN;
+ if (op[7] == 1)
+ mval->compare_operator |=
+ OPERATOR_COMPARE_EQUAL_TO;
+ if (op[1] == 1)
+ mval->unary_operator = OPERATOR_UNARY_AND;
+ else
+ mval->unary_operator = OPERATOR_UNARY_OR;
+ mval++;
break;
case BGP_FLOWSPEC_VALIDATE_ONLY:
default:
@@ -203,12 +327,15 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
int op[8];
int len, value_size, loop = 0, value;
char *ptr = (char *)result; /* for return_string */
+ struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
uint32_t offset = 0;
int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
int len_written;
*error = 0;
do {
+ if (loop > BGP_PBR_MATCH_VAL_MAX)
+ *error = -2;
hex2bin(&nlri_ptr[offset], op);
/* if first element, AND bit can not be set */
if (op[1] == 1 && loop == 0)
@@ -252,7 +379,29 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
ptr += len_written;
break;
case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
- /* TODO : FS OPAQUE */
+ /* limitation: stop converting */
+ if (*error == -2)
+ break;
+ mval->value = value;
+ if (op[6] == 1) {
+ /* different from */
+ mval->compare_operator |=
+ OPERATOR_COMPARE_LESS_THAN;
+ mval->compare_operator |=
+ OPERATOR_COMPARE_GREATER_THAN;
+ } else
+ mval->compare_operator |=
+ OPERATOR_COMPARE_EQUAL_TO;
+ if (op[7] == 1)
+ mval->compare_operator |=
+ OPERATOR_COMPARE_EXACT_MATCH;
+ if (op[1] == 1)
+ mval->unary_operator =
+ OPERATOR_UNARY_AND;
+ else
+ mval->unary_operator =
+ OPERATOR_UNARY_OR;
+ mval++;
break;
case BGP_FLOWSPEC_VALIDATE_ONLY:
default:
@@ -284,6 +433,8 @@ int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
int op[8];
int len, value, value_size, loop = 0;
char *ptr = (char *)result; /* for return_string */
+ struct bgp_pbr_fragment_val *mval =
+ (struct bgp_pbr_fragment_val *)result;
uint32_t offset = 0;
int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
int len_written;
@@ -340,7 +491,7 @@ int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
}
break;
case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
- /* TODO : FS OPAQUE */
+ mval->bitmask = (uint8_t)value;
break;
case BGP_FLOWSPEC_VALIDATE_ONLY:
default:
@@ -354,89 +505,158 @@ int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
return offset;
}
-
-static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
- struct prefix *input,
- int prefix_check)
+int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
+ struct bgp_pbr_entry_main *bpem)
{
- uint32_t offset = 0;
- int type;
- int ret = 0, error = 0;
- uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
- size_t len = pfs->u.prefix_flowspec.prefixlen;
- struct prefix compare;
+ int offset = 0, error = 0;
+ struct prefix *prefix;
+ struct bgp_pbr_match_val *mval;
+ uint8_t *match_num;
+ uint8_t bitmask = 0;
+ int ret = 0, type;
- error = 0;
- while (offset < len-1 && error >= 0) {
+ while (offset < len - 1 && error >= 0) {
type = nlri_content[offset];
offset++;
switch (type) {
case FLOWSPEC_DEST_PREFIX:
case FLOWSPEC_SRC_PREFIX:
- memset(&compare, 0, sizeof(struct prefix));
+ bitmask = 0;
+ if (type == FLOWSPEC_DEST_PREFIX) {
+ bitmask |= PREFIX_DST_PRESENT;
+ prefix = &bpem->dst_prefix;
+ } else {
+ bitmask |= PREFIX_SRC_PRESENT;
+ prefix = &bpem->src_prefix;
+ }
ret = bgp_flowspec_ip_address(
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
- nlri_content+offset,
+ nlri_content + offset,
len - offset,
- &compare, &error);
- if (ret <= 0)
- break;
- if (prefix_check &&
- compare.prefixlen != input->prefixlen)
- break;
- if (compare.family != input->family)
- break;
- if ((input->family == AF_INET) &&
- IPV4_ADDR_SAME(&input->u.prefix4,
- &compare.u.prefix4))
- return true;
- if ((input->family == AF_INET6) &&
- IPV6_ADDR_SAME(&input->u.prefix6.s6_addr,
- &compare.u.prefix6.s6_addr))
- return true;
+ prefix, &error);
+ if (error < 0)
+ zlog_err("%s: flowspec_ip_address error %d",
+ __func__, error);
+ else
+ bpem->match_bitmask |= bitmask;
+ offset += ret;
break;
case FLOWSPEC_IP_PROTOCOL:
+ match_num = &(bpem->match_protocol_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->protocol);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_PORT:
+ match_num = &(bpem->match_port_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->port);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_DEST_PORT:
+ match_num = &(bpem->match_dst_port_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->dst_port);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_SRC_PORT:
+ match_num = &(bpem->match_src_port_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->src_port);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_ICMP_TYPE:
- case FLOWSPEC_ICMP_CODE:
- ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
- nlri_content+offset,
- len - offset,
- NULL, &error);
+ match_num = &(bpem->match_icmp_type_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->icmp_type);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
break;
- case FLOWSPEC_TCP_FLAGS:
- ret = bgp_flowspec_tcpflags_decode(
- BGP_FLOWSPEC_VALIDATE_ONLY,
- nlri_content+offset,
- len - offset,
- NULL, &error);
+ case FLOWSPEC_ICMP_CODE:
+ match_num = &(bpem->match_icmp_code_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->icmp_code);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
break;
case FLOWSPEC_PKT_LEN:
+ match_num =
+ &(bpem->match_packet_length_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->packet_length);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
case FLOWSPEC_DSCP:
- ret = bgp_flowspec_op_decode(
- BGP_FLOWSPEC_VALIDATE_ONLY,
- nlri_content + offset,
- len - offset, NULL,
- &error);
+ match_num = &(bpem->match_dscp_num);
+ mval = (struct bgp_pbr_match_val *)
+ &(bpem->dscp);
+ offset += bgp_flowspec_call_non_opaque_decode(
+ nlri_content + offset,
+ len - offset,
+ mval, match_num,
+ &error);
+ break;
+ case FLOWSPEC_TCP_FLAGS:
+ ret = bgp_flowspec_tcpflags_decode(
+ BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
+ nlri_content + offset,
+ len - offset,
+ &bpem->tcpflags, &error);
+ if (error < 0)
+ zlog_err("%s: flowspec_tcpflags_decode error %d",
+ __func__, error);
+ else
+ bpem->match_tcpflags_num = error;
+ /* contains the number of slots used */
+ offset += ret;
break;
case FLOWSPEC_FRAGMENT:
ret = bgp_flowspec_fragment_type_decode(
- BGP_FLOWSPEC_VALIDATE_ONLY,
- nlri_content + offset,
- len - offset, NULL,
- &error);
+ BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
+ nlri_content + offset,
+ len - offset, &bpem->fragment,
+ &error);
+ if (error < 0)
+ zlog_err("%s: flowspec_fragment_type_decode error %d",
+ __func__, error);
+ else
+ bpem->match_bitmask |= FRAGMENT_PRESENT;
+ offset += ret;
break;
default:
- error = -1;
- break;
+ zlog_err("%s: unknown type %d\n", __func__, type);
}
- offset += ret;
}
- return false;
+ return error;
}
+
struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi,
struct bgp_table *rib,
struct prefix *match,