diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2018-03-01 16:07:38 +0100 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2018-03-30 14:00:47 +0200 |
commit | fc83654008749f6d656c9704936d81deb1e6e576 (patch) | |
tree | 248ae7da56b3d8d6ae8d0a6443498407796110c0 /bgpd/bgp_flowspec.c | |
parent | bgpd: add flowspec utilities to decode, convert fs nlri (diff) | |
download | frr-fc83654008749f6d656c9704936d81deb1e6e576.tar.xz frr-fc83654008749f6d656c9704936d81deb1e6e576.zip |
bgpd: use bgp flowspec API to validate and receive NLRI
The changes introduce validation of NLRI FS entries at incoming, before
being pushed in FIB. Note that the so called validation only checks for
validity of the incoming flowspec nlri format, and not the validation as
per RFC5575.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'bgpd/bgp_flowspec.c')
-rw-r--r-- | bgpd/bgp_flowspec.c | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index 5d61175dc..ebfa7dae6 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -26,22 +26,84 @@ #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_flowspec.h" +#include "bgpd/bgp_flowspec_util.h" #include "bgpd/bgp_flowspec_private.h" +static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len) +{ + uint32_t offset = 0; + int type; + int ret = 0, error = 0; + + while (offset < len-1) { + type = nlri_content[offset]; + offset++; + switch (type) { + case FLOWSPEC_DEST_PREFIX: + case FLOWSPEC_SRC_PREFIX: + ret = bgp_flowspec_ip_address( + BGP_FLOWSPEC_VALIDATE_ONLY, + nlri_content + offset, + len - offset, NULL, &error); + 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; + if (error < 0) + break; + } + return error; +} + int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int withdraw) { uint8_t *pnt; uint8_t *lim; afi_t afi; + safi_t safi; int psize = 0; uint8_t rlen; struct prefix p; + int ret; + void *temp; /* Start processing the NLRI - there may be multiple in the MP_REACH */ pnt = packet->nlri; lim = pnt + packet->length; afi = packet->afi; + safi = packet->safi; if (afi == AFI_IP6) { zlog_err("BGP flowspec IPv6 not supported"); @@ -70,9 +132,33 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, psize); return -1; } - /* TODO: validate prefix - * and add to FIB - */ + if (bgp_fs_nlri_validate(pnt, psize) < 0) { + zlog_err("Bad flowspec format or NLRI options not supported"); + return -1; + } + p.family = AF_FLOWSPEC; + p.prefixlen = 0; + /* Flowspec encoding is in bytes */ + p.u.prefix_flowspec.prefixlen = psize; + temp = XCALLOC(MTYPE_TMP, psize); + memcpy(temp, pnt, psize); + p.u.prefix_flowspec.ptr = (uintptr_t) temp; + /* Process the route. */ + if (!withdraw) + ret = bgp_update(peer, &p, 0, attr, + afi, safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + NULL, NULL, 0, 0, NULL); + else + ret = bgp_withdraw(peer, &p, 0, attr, + afi, safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + NULL, NULL, 0, NULL); + if (ret) { + zlog_err("Flowspec NLRI failed to be %s.", + attr ? "added" : "withdrawn"); + return -1; + } } return 0; } |