From d792d50e440bcd749f46d04eded9c0222a54cb62 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 7 Jun 2023 17:26:52 +0200 Subject: [PATCH] bgpd: fix route-target display with as dotted format The following command results in a wrong route-target display: > # show running-config > [..] > route-map rmap permit 1 > set ext-community rt 1.45:55 > exit > router bgp 65500 > neighbor 1.1.1.1 remote-as 65500 > address-family ipv4 unicast > neighbor 1.1.1.1 route-map rmap in > Observed output: > # show bgp ipv4 3.3.3.3/32 > [..] > Extended Community: RT:1.0.0.45:55 > The decoding of the passed cli string assumes this is an IP address, whereas it is an AS number in dotted format. Consequently, the vty output will use the ip address encoding. Count the number of dots in the extended community format. If a single dot number is detected, the AS format is passed, and used by the vty output. Expected output: > > # show bgp ipv4 3.3.3.3/32 > [..] > Extended Community: RT:65581:55 > Signed-off-by: Philippe Guibert --- bgpd/bgp_ecommunity.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index a555930137b5..d9b228f0eac6 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -543,7 +543,7 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, struct in6_addr ip6; as_t as = 0; uint32_t val = 0; - uint8_t ecomm_type; + uint8_t ecomm_type = 0; char buf[INET_ADDRSTRLEN + 1]; struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr; uint64_t tmp_as = 0; @@ -684,15 +684,21 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, memset(buf, 0, INET_ADDRSTRLEN + 1); memcpy(buf, str, p - str); - if (dot) { + if (dot == 3) { /* Parsing A.B.C.D in: * A.B.C.D:MN */ ret = inet_aton(buf, &ip); if (ret == 0) goto error; + } else if (dot == 1) { + /* Parsing A.B AS number in: + * A.B:MN + */ + if (!asn_str2asn(buf, &as)) + goto error; } else { - /* ASN */ + /* Parsing A AS number in A:MN */ errno = 0; tmp_as = strtoul(buf, &endptr, 10); /* 'unsigned long' is a uint64 on 64-bit @@ -710,8 +716,11 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, } else if (*p == '.') { if (separator) goto error; + /* either IP or AS format */ dot++; - if (dot > 4) + if (dot > 1) + ecomm_type = ECOMMUNITY_ENCODE_IP; + if (dot >= 4) goto error; } else { digit = 1; @@ -729,13 +738,13 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, if (!digit || !separator) goto error; - /* Encode result into extended community. */ - if (dot) - ecomm_type = ECOMMUNITY_ENCODE_IP; - else if (as > BGP_AS_MAX) - ecomm_type = ECOMMUNITY_ENCODE_AS4; - else - ecomm_type = ECOMMUNITY_ENCODE_AS; + if (ecomm_type != ECOMMUNITY_ENCODE_IP) { + /* Encode result into extended community for AS format. */ + if (as > BGP_AS_MAX) + ecomm_type = ECOMMUNITY_ENCODE_AS4; + else + ecomm_type = ECOMMUNITY_ENCODE_AS; + } if (ecommunity_encode(ecomm_type, type, 1, as, ip, val, eval)) goto error; *token = ecommunity_token_val;