diff options
| author | Russ White <russ@riw.us> | 2023-02-21 08:01:03 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-21 08:01:03 -0500 | 
| commit | ba755d35e508c2452e5459bdd7c0dd67a70a88a4 (patch) | |
| tree | adc08f46788b8012240faec23ae7e7271bb0d40d /bgpd/bgp_rd.c | |
| parent | 39c664c4ea530a9460efa1a78fe669ae56c85f83 (diff) | |
| parent | 616e9f0d9f0458788adf4b30707016c8db383b02 (diff) | |
Merge pull request #12248 from pguibert6WIND/bgpasdot
lib, bgp: add initial support for asdot format
Diffstat (limited to 'bgpd/bgp_rd.c')
| -rw-r--r-- | bgpd/bgp_rd.c | 100 | 
1 files changed, 71 insertions, 29 deletions
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index 6e73ab8d1e..bb9f76b8a3 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -83,12 +83,12 @@ 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; -	char *p2; +	int ret = 0, type = RD_TYPE_UNDEFINED; +	char *p, *p2;  	struct stream *s = NULL;  	char *half = NULL;  	struct in_addr addr; +	as_t as_val;  	prd->family = AF_UNSPEC;  	prd->prefixlen = 64; @@ -97,41 +97,55 @@ 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;  	s = stream_new(RD_BYTES); -	half = XMALLOC(MTYPE_TMP, (p - str) + 1); -	memcpy(half, str, (p - str)); -	half[p - str] = '\0'; - -	p2 = strchr(str, '.'); - -	if (!p2) { -		unsigned long as_val; - -		if (!all_digit(half)) -			goto out; - -		as_val = atol(half); -		if (as_val > 0xffff) { +	/* 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)) -			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);  	ret = 1; @@ -142,12 +156,14 @@ out:  	return ret;  } -char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size) +char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size, +		    enum asnotation_mode asnotation)  {  	const uint8_t *pnt;  	uint16_t type;  	struct rd_as rd_as;  	struct rd_ip rd_ip; +	int len = 0;  	assert(size >= RD_ADDRSTRLEN); @@ -157,11 +173,15 @@ char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size)  	if (type == RD_TYPE_AS) {  		decode_rd_as(pnt + 2, &rd_as); -		snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); +		len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), +				  &rd_as.as); +		snprintfrr(buf + len, size - len, ":%u", rd_as.val);  		return buf;  	} else if (type == RD_TYPE_AS4) {  		decode_rd_as4(pnt + 2, &rd_as); -		snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); +		len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), +				  &rd_as.as); +		snprintfrr(buf + len, size - len, ":%u", rd_as.val);  		return buf;  	} else if (type == RD_TYPE_IP) {  		decode_rd_ip(pnt + 2, &rd_ip); @@ -196,16 +216,38 @@ void form_auto_rd(struct in_addr router_id,  	(void)str2prefix_rd(buf, prd);  } -printfrr_ext_autoreg_p("RD", printfrr_prd); -static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, -			    const void *ptr) +static ssize_t printfrr_prd_asnotation(struct fbuf *buf, +				       struct printfrr_eargs *ea, +				       const void *ptr, +				       enum asnotation_mode asnotation)  {  	char rd_buf[RD_ADDRSTRLEN];  	if (!ptr)  		return bputs(buf, "(null)"); -	prefix_rd2str(ptr, rd_buf, sizeof(rd_buf)); +	prefix_rd2str(ptr, rd_buf, sizeof(rd_buf), asnotation);  	return bputs(buf, rd_buf);  } + +printfrr_ext_autoreg_p("RDP", printfrr_prd); +static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, +			    const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_PLAIN); +} + +printfrr_ext_autoreg_p("RDD", printfrr_prd_dot); +static ssize_t printfrr_prd_dot(struct fbuf *buf, struct printfrr_eargs *ea, +				const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOT); +} + +printfrr_ext_autoreg_p("RDE", printfrr_prd_dotplus); +static ssize_t printfrr_prd_dotplus(struct fbuf *buf, struct printfrr_eargs *ea, +				    const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS); +}  | 
