From 6f167d2363949dbbfac767b2c4bebf7b870febed Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 24 Nov 2022 16:13:08 +0100 Subject: [PATCH] bgpd: support for route-distinguisher format with 3 fields The ietf proposes to define a RD with a 3 field separated by the ':' character. The last 2 fields stands for the usual fields, namely AS4B:NN, AS2B,NNNN, IP:NN. The first field stands for the kind of route distinguisher used. Today, except with the route-map, no other RD configuration supports this mode. Handle the support for this in FRR. Link: https://github.com/FRRouting/frr/blob/master/yang/ietf/ietf-routing-types.yang#L258 Signed-off-by: Philippe Guibert --- bgpd/bgp_rd.c | 35 +++++++++++++++++++++++++++++------ bgpd/bgp_rd.h | 1 + 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index f2ecd3de5f..e406d9ca6d 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -99,8 +99,8 @@ void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth) int str2prefix_rd(const char *str, struct prefix_rd *prd) { - int ret = 0; - char *p; + int ret = 0, type = RD_TYPE_UNDEFINED; + char *p, *p2; struct stream *s = NULL; char *half = NULL; struct in_addr addr; @@ -113,30 +113,53 @@ int str2prefix_rd(const char *str, struct prefix_rd *prd) if (!p) goto out; + /* a second ':' is accepted */ + p2 = strchr(p + 1, ':'); + if (p2) { + /* type is in first part */ + half = XMALLOC(MTYPE_TMP, (p - str) + 1); + memcpy(half, str, (p - str)); + half[p - str] = '\0'; + type = atoi(half); + if (type != RD_TYPE_AS && type != RD_TYPE_IP && + type != RD_TYPE_AS4) + goto out; + XFREE(MTYPE_TMP, half); + half = XMALLOC(MTYPE_TMP, (p2 - p)); + memcpy(half, p + 1, (p2 - p - 1)); + half[p2 - p - 1] = '\0'; + p = p2 + 1; + } else { + half = XMALLOC(MTYPE_TMP, (p - str) + 1); + memcpy(half, str, (p - str)); + half[p - str] = '\0'; + } if (!all_digit(p + 1)) goto out; - /* case AS dot format is used */ s = stream_new(RD_BYTES); - half = XMALLOC(MTYPE_TMP, (p - str) + 1); - memcpy(half, str, (p - str)); - half[p - str] = '\0'; /* if it is an AS format or an IP */ if (asn_str2asn(half, &as_val)) { if (as_val > UINT16_MAX) { stream_putw(s, RD_TYPE_AS4); stream_putl(s, as_val); stream_putw(s, atol(p + 1)); + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS4) + goto out; } else { stream_putw(s, RD_TYPE_AS); stream_putw(s, as_val); stream_putl(s, atol(p + 1)); + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS) + goto out; } } else if (inet_aton(half, &addr)) { stream_putw(s, RD_TYPE_IP); stream_put_in_addr(s, &addr); stream_putw(s, atol(p + 1)); + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_IP) + goto out; } else goto out; memcpy(prd->val, s->data, 8); diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h index aa9bc0b872..073eb7e114 100644 --- a/bgpd/bgp_rd.h +++ b/bgpd/bgp_rd.h @@ -27,6 +27,7 @@ #include "prefix.h" /* RD types */ +#define RD_TYPE_UNDEFINED (-1) #define RD_TYPE_AS 0 #define RD_TYPE_IP 1 #define RD_TYPE_AS4 2