From 7c1480fd2fc9309bc23d1c6f387320370a1d335a 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 extcommunity rt 1.45:55 > exit > router bgp 1.45 as-notation plain > neighbor 192.0.2.1 remote-as 65500 > address-family ipv4 unicast > network 192.0.2.2/32 route-map rmap > Observed output: > # show bgp ipv4 192.0.2.2/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. After fix: > > # show bgp ipv4 192.0.2.2/32 > [..] > Extended Community: RT:65581:55 > For remind, AS 65581 and AS 1.45 are a unique AS number. > show bgp neighbor > BGP neighbor is 192.0.2.1, remote AS 65500, local AS 65581, external link > [..] Signed-off-by: Philippe Guibert --- bgpd/bgp_ecommunity.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index a8ae177d03e9..90c0123b93ba 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -724,15 +724,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 @@ -750,8 +756,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; @@ -776,19 +785,18 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, if (!digit && (!separator || !val_color_set)) 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 if (as > 0) - ecomm_type = ECOMMUNITY_ENCODE_AS; - else if (val_color) { - ecomm_type = ECOMMUNITY_ENCODE_OPAQUE; - sub_type = ECOMMUNITY_COLOR; - val = val_color; + if (ecomm_type != ECOMMUNITY_ENCODE_IP) { + /* Encode result into extended community for AS format or color. */ + if (as > BGP_AS_MAX) + ecomm_type = ECOMMUNITY_ENCODE_AS4; + else if (as > 0) + ecomm_type = ECOMMUNITY_ENCODE_AS; + else if (val_color) { + ecomm_type = ECOMMUNITY_ENCODE_OPAQUE; + sub_type = ECOMMUNITY_COLOR; + val = val_color; + } } - if (ecommunity_encode(ecomm_type, sub_type, 1, as, ip, val, eval)) goto error; *token = ecommunity_token_val;