diff options
author | Russ White <russ@riw.us> | 2023-02-21 14:01:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-21 14:01:03 +0100 |
commit | ba755d35e508c2452e5459bdd7c0dd67a70a88a4 (patch) | |
tree | adc08f46788b8012240faec23ae7e7271bb0d40d /bgpd/bgp_rd.c | |
parent | Merge pull request #12849 from opensourcerouting/fix/tests_enum (diff) | |
parent | bgpd: handle case where passed RD is null (diff) | |
download | frr-ba755d35e508c2452e5459bdd7c0dd67a70a88a4.tar.xz frr-ba755d35e508c2452e5459bdd7c0dd67a70a88a4.zip |
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 6e73ab8d1..bb9f76b8a 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); +} |