summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpctl
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2020-03-20 07:56:35 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2020-03-20 07:56:35 +0000
commit7b5b63f0825840f39895aa8977d896ce423e064c (patch)
tree781d6817556c42dbd2e0168bbb964192b3dd7835 /usr.sbin/bgpctl
parent8e2aa97cb21d73158ade1cc1f6e6c8880f5081c7 (diff)
Reshuffle code more to separate out the output functions into output.c.
Rewrite some functions to return a string instead of calling printf directly. OK benno@
Diffstat (limited to 'usr.sbin/bgpctl')
-rw-r--r--usr.sbin/bgpctl/bgpctl.c750
-rw-r--r--usr.sbin/bgpctl/bgpctl.h28
-rw-r--r--usr.sbin/bgpctl/output.c455
3 files changed, 621 insertions, 612 deletions
diff --git a/usr.sbin/bgpctl/bgpctl.c b/usr.sbin/bgpctl/bgpctl.c
index cb6b57fce7f..67f567ba862 100644
--- a/usr.sbin/bgpctl/bgpctl.c
+++ b/usr.sbin/bgpctl/bgpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpctl.c,v 1.258 2020/01/24 05:46:00 claudio Exp $ */
+/* $OpenBSD: bgpctl.c,v 1.259 2020/03/20 07:56:34 claudio Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -46,11 +46,6 @@
int main(int, char *[]);
int show(struct imsg *, struct parse_result *);
-void show_attr(void *, u_int16_t, int);
-void show_communities(u_char *, size_t, int);
-void show_community(u_char *, u_int16_t);
-void show_large_community(u_char *, u_int16_t);
-void show_ext_community(u_char *, u_int16_t);
void send_filterset(struct imsgbuf *, struct filter_set_head *);
void show_mrt_dump_neighbors(struct mrt_rib *, struct mrt_peer *,
void *);
@@ -425,7 +420,6 @@ show(struct imsg *imsg, struct parse_result *res)
if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt))
errx(1, "wrong imsg len");
kt = imsg->data;
-
show_fib_table(kt);
break;
case IMSG_CTL_SHOW_RIB:
@@ -443,7 +437,7 @@ show(struct imsg *imsg, struct parse_result *res)
warnx("bad IMSG_CTL_SHOW_RIB_COMMUNITIES received");
break;
}
- show_communities(imsg->data, ilen, res->flags);
+ show_communities(imsg->data, ilen, res);
break;
case IMSG_CTL_SHOW_RIB_ATTR:
ilen = imsg->hdr.len - IMSG_HEADER_SIZE;
@@ -451,7 +445,7 @@ show(struct imsg *imsg, struct parse_result *res)
warnx("bad IMSG_CTL_SHOW_RIB_ATTR received");
break;
}
- show_attr(imsg->data, ilen, res->flags);
+ show_attr(imsg->data, ilen, res);
break;
case IMSG_CTL_SHOW_RIB_MEM:
memcpy(&stats, imsg->data, sizeof(stats));
@@ -506,7 +500,7 @@ fmt_peer(const char *descr, const struct bgpd_addr *remote_addr,
}
const char *
-print_auth_method(enum auth_method method)
+fmt_auth_method(enum auth_method method)
{
switch (method) {
case AUTH_MD5SIG:
@@ -525,75 +519,6 @@ print_auth_method(enum auth_method method)
}
}
-void
-print_neighbor_capa_mp(struct peer *p)
-{
- int comma;
- u_int8_t i;
-
- for (i = 0, comma = 0; i < AID_MAX; i++)
- if (p->capa.peer.mp[i]) {
- printf("%s%s", comma ? ", " : "", aid2str(i));
- comma = 1;
- }
-}
-
-void
-print_neighbor_capa_restart(struct peer *p)
-{
- int comma;
- u_int8_t i;
-
- if (p->capa.peer.grestart.timeout)
- printf(": Timeout: %d, ", p->capa.peer.grestart.timeout);
- for (i = 0, comma = 0; i < AID_MAX; i++)
- if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) {
- if (!comma &&
- p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART)
- printf("restarted, ");
- if (comma)
- printf(", ");
- printf("%s", aid2str(i));
- if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD)
- printf(" (preserved)");
- comma = 1;
- }
-}
-
-void
-print_neighbor_msgstats(struct peer *p)
-{
- printf(" Message statistics:\n");
- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
- printf(" %-15s %10llu %10llu\n", "Opens",
- p->stats.msg_sent_open, p->stats.msg_rcvd_open);
- printf(" %-15s %10llu %10llu\n", "Notifications",
- p->stats.msg_sent_notification, p->stats.msg_rcvd_notification);
- printf(" %-15s %10llu %10llu\n", "Updates",
- p->stats.msg_sent_update, p->stats.msg_rcvd_update);
- printf(" %-15s %10llu %10llu\n", "Keepalives",
- p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive);
- printf(" %-15s %10llu %10llu\n", "Route Refresh",
- p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh);
- printf(" %-15s %10llu %10llu\n\n", "Total",
- p->stats.msg_sent_open + p->stats.msg_sent_notification +
- p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
- p->stats.msg_sent_rrefresh,
- p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
- p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
- p->stats.msg_rcvd_rrefresh);
- printf(" Update statistics:\n");
- printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
- printf(" %-15s %10u %10u\n", "Prefixes",
- p->stats.prefix_out_cnt, p->stats.prefix_cnt);
- printf(" %-15s %10llu %10llu\n", "Updates",
- p->stats.prefix_sent_update, p->stats.prefix_rcvd_update);
- printf(" %-15s %10llu %10llu\n", "Withdraws",
- p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw);
- printf(" %-15s %10llu %10llu\n", "End-of-Rib",
- p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor);
-}
-
#define TF_BUFS 8
#define TF_LEN 9
@@ -646,58 +571,49 @@ fmt_monotime(time_t t)
return (fmt_timeframe(ts.tv_sec - t));
}
-void
-show_fib_flags(u_int16_t flags)
+const char *
+fmt_fib_flags(u_int16_t flags)
{
+ static char buf[8];
+
if (flags & F_DOWN)
- printf(" ");
+ strlcpy(buf, " ", sizeof(buf));
else
- printf("*");
+ strlcpy(buf, "*", sizeof(buf));
if (flags & F_BGPD_INSERTED)
- printf("B");
+ strlcat(buf, "B", sizeof(buf));
else if (flags & F_CONNECTED)
- printf("C");
+ strlcat(buf, "C", sizeof(buf));
else if (flags & F_STATIC)
- printf("S");
+ strlcat(buf, "S", sizeof(buf));
else if (flags & F_DYNAMIC)
- printf("D");
+ strlcat(buf, "D", sizeof(buf));
else
- printf(" ");
+ strlcat(buf, " ", sizeof(buf));
if (flags & F_NEXTHOP)
- printf("N");
+ strlcat(buf, "N", sizeof(buf));
else
- printf(" ");
+ strlcat(buf, " ", sizeof(buf));
if (flags & F_REJECT && flags & F_BLACKHOLE)
- printf("f");
+ strlcat(buf, "f", sizeof(buf));
else if (flags & F_REJECT)
- printf("r");
+ strlcat(buf, "r", sizeof(buf));
else if (flags & F_BLACKHOLE)
- printf("b");
+ strlcat(buf, "b", sizeof(buf));
else
- printf(" ");
-
- printf(" ");
-}
+ strlcat(buf, " ", sizeof(buf));
-void
-print_prefix(struct bgpd_addr *prefix, u_int8_t prefixlen, u_int8_t flags,
- u_int8_t ovs)
-{
- char *p;
+ if (strlcat(buf, " ", sizeof(buf)) >= sizeof(buf))
+ errx(1, "%s buffer too small", __func__);
- print_flags(flags, 1);
- printf("%3s ", print_ovs(ovs, 1));
- if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1)
- err(1, NULL);
- printf("%-20s", p);
- free(p);
+ return buf;
}
const char *
-print_origin(u_int8_t origin, int sum)
+fmt_origin(u_int8_t origin, int sum)
{
switch (origin) {
case ORIGIN_IGP:
@@ -711,9 +627,10 @@ print_origin(u_int8_t origin, int sum)
}
}
-void
-print_flags(u_int8_t flags, int sum)
+const char *
+fmt_flags(u_int8_t flags, int sum)
{
+ static char buf[80];
char flagstr[5];
char *p = flagstr;
@@ -731,25 +648,30 @@ print_flags(u_int8_t flags, int sum)
if (flags & F_PREF_ACTIVE)
*p++ = '>';
*p = '\0';
- printf("%-5s ", flagstr);
+ snprintf(buf, sizeof(buf), "%-5s", flagstr);
} else {
if (flags & F_PREF_INTERNAL)
- printf("internal");
+ strlcpy(buf, "internal", sizeof(buf));
else
- printf("external");
+ strlcpy(buf, "external", sizeof(buf));
+
if (flags & F_PREF_STALE)
- printf(", stale");
+ strlcat(buf, ", stale", sizeof(buf));
if (flags & F_PREF_ELIGIBLE)
- printf(", valid");
+ strlcat(buf, ", valid", sizeof(buf));
if (flags & F_PREF_ACTIVE)
- printf(", best");
+ strlcat(buf, ", best", sizeof(buf));
if (flags & F_PREF_ANNOUNCE)
- printf(", announced");
+ strlcat(buf, ", announced", sizeof(buf));
+ if (strlen(buf) >= sizeof(buf) - 1)
+ errx(1, "%s buffer too small", __func__);
}
+
+ return buf;
}
const char *
-print_ovs(u_int8_t validation_state, int sum)
+fmt_ovs(u_int8_t validation_state, int sum)
{
switch (validation_state) {
case ROA_INVALID:
@@ -761,8 +683,86 @@ print_ovs(u_int8_t validation_state, int sum)
}
}
-static const char *
-print_attr(u_int8_t type, u_int8_t flags)
+const char *
+fmt_mem(long long num)
+{
+ static char buf[16];
+
+ if (fmt_scaled(num, buf) == -1)
+ snprintf(buf, sizeof(buf), "%lldB", num);
+
+ return (buf);
+}
+
+const char *
+fmt_errstr(u_int8_t errcode, u_int8_t subcode)
+{
+ static char errbuf[256];
+ const char *errstr = NULL;
+ const char *suberr = NULL;
+ int uk = 0;
+
+ if (errcode == 0) /* no error */
+ return NULL;
+
+ if (errcode < sizeof(errnames)/sizeof(char *))
+ errstr = errnames[errcode];
+
+ switch (errcode) {
+ case ERR_HEADER:
+ if (subcode < sizeof(suberr_header_names)/sizeof(char *))
+ suberr = suberr_header_names[subcode];
+ else
+ uk = 1;
+ break;
+ case ERR_OPEN:
+ if (subcode < sizeof(suberr_open_names)/sizeof(char *))
+ suberr = suberr_open_names[subcode];
+ else
+ uk = 1;
+ break;
+ case ERR_UPDATE:
+ if (subcode < sizeof(suberr_update_names)/sizeof(char *))
+ suberr = suberr_update_names[subcode];
+ else
+ uk = 1;
+ break;
+ case ERR_HOLDTIMEREXPIRED:
+ if (subcode != 0)
+ uk = 1;
+ break;
+ case ERR_FSM:
+ if (subcode < sizeof(suberr_fsm_names)/sizeof(char *))
+ suberr = suberr_fsm_names[subcode];
+ else
+ uk = 1;
+ break;
+ case ERR_CEASE:
+ if (subcode < sizeof(suberr_cease_names)/sizeof(char *))
+ suberr = suberr_cease_names[subcode];
+ else
+ uk = 1;
+ break;
+ default:
+ snprintf(errbuf, sizeof(errbuf),
+ "unknown error code %u subcode %u", errcode, subcode);
+ return (errbuf);
+ }
+
+ if (uk)
+ snprintf(errbuf, sizeof(errbuf),
+ "%s, unknown subcode %u", errstr, subcode);
+ else if (suberr == NULL)
+ return (errstr);
+ else
+ snprintf(errbuf, sizeof(errbuf),
+ "%s, %s", errstr, suberr);
+
+ return (errbuf);
+}
+
+const char *
+fmt_attr(u_int8_t type, u_int8_t flags)
{
#define CHECK_FLAGS(s, t, m) \
if (((s) & ~(ATTR_DEFMASK | (m))) != (t)) pflags = 1
@@ -856,252 +856,46 @@ print_attr(u_int8_t type, u_int8_t flags)
#undef CHECK_FLAGS
}
-void
-show_attr(void *b, u_int16_t len, int flag0)
+const char *
+fmt_community(u_int16_t a, u_int16_t v)
{
- u_char *data = b, *path;
- struct in_addr id;
- struct bgpd_addr prefix;
- char *aspath;
- u_int32_t as;
- u_int16_t alen, ioff, short_as, afi;
- u_int8_t flags, type, safi, aid, prefixlen;
- int i, pos, e2, e4;
-
- if (len < 3)
- errx(1, "show_attr: too short bgp attr");
-
- flags = data[0];
- type = data[1];
-
- /* get the attribute length */
- if (flags & ATTR_EXTLEN) {
- if (len < 4)
- errx(1, "show_attr: too short bgp attr");
- memcpy(&alen, data+2, sizeof(u_int16_t));
- alen = ntohs(alen);
- data += 4;
- len -= 4;
- } else {
- alen = data[2];
- data += 3;
- len -= 3;
- }
-
- /* bad imsg len how can that happen!? */
- if (alen > len)
- errx(1, "show_attr: bad length");
-
- printf(" %s: ", print_attr(type, flags));
-
- switch (type) {
- case ATTR_ORIGIN:
- if (alen == 1)
- printf("%u", *data);
- else
- printf("bad length");
- break;
- case ATTR_ASPATH:
- case ATTR_AS4_PATH:
- /* prefer 4-byte AS here */
- e4 = aspath_verify(data, alen, 1);
- e2 = aspath_verify(data, alen, 0);
- if (e4 == 0 || e4 == AS_ERR_SOFT) {
- path = data;
- } else if (e2 == 0 || e2 == AS_ERR_SOFT) {
- path = aspath_inflate(data, alen, &alen);
- if (path == NULL)
- errx(1, "aspath_inflate failed");
- } else {
- printf("bad AS-Path");
- break;
- }
- if (aspath_asprint(&aspath, path, alen) == -1)
- err(1, NULL);
- printf("%s", aspath);
- free(aspath);
- if (path != data)
- free(path);
- break;
- case ATTR_NEXTHOP:
- if (alen == 4) {
- memcpy(&id, data, sizeof(id));
- printf("%s", inet_ntoa(id));
- } else
- printf("bad length");
- break;
- case ATTR_MED:
- case ATTR_LOCALPREF:
- if (alen == 4) {
- u_int32_t val;
- memcpy(&val, data, sizeof(val));
- val = ntohl(val);
- printf("%u", val);
- } else
- printf("bad length");
- break;
- case ATTR_AGGREGATOR:
- case ATTR_AS4_AGGREGATOR:
- if (alen == 8) {
- memcpy(&as, data, sizeof(as));
- memcpy(&id, data + sizeof(as), sizeof(id));
- as = ntohl(as);
- } else if (alen == 6) {
- memcpy(&short_as, data, sizeof(short_as));
- memcpy(&id, data + sizeof(short_as), sizeof(id));
- as = ntohs(short_as);
- } else {
- printf("bad length");
- break;
- }
- printf("%s [%s]", log_as(as), inet_ntoa(id));
- break;
- case ATTR_COMMUNITIES:
- show_community(data, alen);
- break;
- case ATTR_ORIGINATOR_ID:
- memcpy(&id, data, sizeof(id));
- printf("%s", inet_ntoa(id));
- break;
- case ATTR_CLUSTER_LIST:
- for (ioff = 0; ioff + sizeof(id) <= alen;
- ioff += sizeof(id)) {
- memcpy(&id, data + ioff, sizeof(id));
- printf(" %s", inet_ntoa(id));
- }
- break;
- case ATTR_MP_REACH_NLRI:
- case ATTR_MP_UNREACH_NLRI:
- if (alen < 3) {
- bad_len:
- printf("bad length");
- break;
- }
- memcpy(&afi, data, 2);
- data += 2;
- alen -= 2;
- afi = ntohs(afi);
- safi = *data++;
- alen--;
-
- if (afi2aid(afi, safi, &aid) == -1) {
- printf("bad AFI/SAFI pair");
- break;
- }
- printf(" %s", aid2str(aid));
-
- if (type == ATTR_MP_REACH_NLRI) {
- struct bgpd_addr nexthop;
- u_int8_t nhlen;
- if (len == 0)
- goto bad_len;
- nhlen = *data++;
- alen--;
- if (nhlen > len)
- goto bad_len;
- bzero(&nexthop, sizeof(nexthop));
- switch (aid) {
- case AID_INET6:
- nexthop.aid = aid;
- if (nhlen != 16 && nhlen != 32)
- goto bad_len;
- memcpy(&nexthop.v6.s6_addr, data, 16);
- break;
- case AID_VPN_IPv4:
- if (nhlen != 12)
- goto bad_len;
- nexthop.aid = AID_INET;
- memcpy(&nexthop.v4, data + sizeof(u_int64_t),
- sizeof(nexthop.v4));
- break;
- default:
- printf("unhandled AID #%u", aid);
- goto done;
- }
- /* ignore reserved (old SNPA) field as per RFC4760 */
- data += nhlen + 1;
- alen -= nhlen + 1;
-
- printf(" nexthop: %s", log_addr(&nexthop));
- }
-
- while (alen > 0) {
- switch (aid) {
- case AID_INET6:
- pos = nlri_get_prefix6(data, alen, &prefix,
- &prefixlen);
- break;
- case AID_VPN_IPv4:
- pos = nlri_get_vpn4(data, alen, &prefix,
- &prefixlen, 1);
- break;
- default:
- printf("unhandled AID #%u", aid);
- goto done;
- }
- if (pos == -1) {
- printf("bad %s prefix", aid2str(aid));
- break;
- }
- printf(" %s/%u", log_addr(&prefix), prefixlen);
- data += pos;
- alen -= pos;
- }
- break;
- case ATTR_EXT_COMMUNITIES:
- show_ext_community(data, alen);
- break;
- case ATTR_LARGE_COMMUNITIES:
- show_large_community(data, alen);
- break;
- case ATTR_ATOMIC_AGGREGATE:
- default:
- printf(" len %u", alen);
- if (alen) {
- printf(":");
- for (i=0; i < alen; i++)
- printf(" %02x", *(data+i));
- }
- break;
- }
- done:
- printf("%c", EOL0(flag0));
-}
+ static char buf[12];
-static void
-print_community(u_int16_t a, u_int16_t v)
-{
if (a == COMMUNITY_WELLKNOWN)
switch (v) {
case COMMUNITY_GRACEFUL_SHUTDOWN:
- printf("GRACEFUL_SHUTDOWN");
- break;
+ return "GRACEFUL_SHUTDOWN";
case COMMUNITY_NO_EXPORT:
- printf("NO_EXPORT");
- break;
+ return "NO_EXPORT";
case COMMUNITY_NO_ADVERTISE:
- printf("NO_ADVERTISE");
- break;
+ return "NO_ADVERTISE";
case COMMUNITY_NO_EXPSUBCONFED:
- printf("NO_EXPORT_SUBCONFED");
- break;
+ return "NO_EXPORT_SUBCONFED";
case COMMUNITY_NO_PEER:
- printf("NO_PEER");
- break;
+ return "NO_PEER";
case COMMUNITY_BLACKHOLE:
- printf("BLACKHOLE");
- break;
+ return "BLACKHOLE";
default:
- printf("%hu:%hu", a, v);
break;
}
- else
- printf("%hu:%hu", a, v);
+
+ snprintf(buf, sizeof(buf), "%hu:%hu", a, v);
+ return buf;
}
-static void
-print_ext_community(u_int8_t *data)
+const char *
+fmt_large_community(u_int32_t d1, u_int32_t d2, u_int32_t d3)
{
+ static char buf[33];
+
+ snprintf(buf, sizeof(buf), "%u:%u:%u", d1, d2, d3);
+ return buf;
+}
+
+const char *
+fmt_ext_community(u_int8_t *data)
+{
+ static char buf[32];
u_int64_t ext;
struct in_addr ip;
u_int32_t as4, u32;
@@ -1111,182 +905,68 @@ print_ext_community(u_int8_t *data)
type = data[0];
subtype = data[1];
- printf("%s ", log_ext_subtype(type, subtype));
-
switch (type) {
case EXT_COMMUNITY_TRANS_TWO_AS:
memcpy(&as2, data + 2, sizeof(as2));
memcpy(&u32, data + 4, sizeof(u32));
- printf("%s:%u", log_as(ntohs(as2)), ntohl(u32));
- break;
+ snprintf(buf, sizeof(buf), "%s %s:%u",
+ log_ext_subtype(type, subtype),
+ log_as(ntohs(as2)), ntohl(u32));
+ return buf;
case EXT_COMMUNITY_TRANS_IPV4:
memcpy(&ip, data + 2, sizeof(ip));
memcpy(&u16, data + 6, sizeof(u16));
- printf("%s:%hu", inet_ntoa(ip), ntohs(u16));
- break;
+ snprintf(buf, sizeof(buf), "%s %s:%hu",
+ log_ext_subtype(type, subtype),
+ inet_ntoa(ip), ntohs(u16));
+ return buf;
case EXT_COMMUNITY_TRANS_FOUR_AS:
memcpy(&as4, data + 2, sizeof(as4));
memcpy(&u16, data + 6, sizeof(u16));
- printf("%s:%hu", log_as(ntohl(as4)), ntohs(u16));
- break;
+ snprintf(buf, sizeof(buf), "%s %s:%hu",
+ log_ext_subtype(type, subtype),
+ log_as(ntohl(as4)), ntohs(u16));
+ return buf;
case EXT_COMMUNITY_TRANS_OPAQUE:
case EXT_COMMUNITY_TRANS_EVPN:
memcpy(&ext, data, sizeof(ext));
ext = be64toh(ext) & 0xffffffffffffLL;
- printf("0x%llx", (unsigned long long)ext);
- break;
+ snprintf(buf, sizeof(buf), "%s 0x%llx",
+ log_ext_subtype(type, subtype), (unsigned long long)ext);
+ return buf;
case EXT_COMMUNITY_NON_TRANS_OPAQUE:
memcpy(&ext, data, sizeof(ext));
ext = be64toh(ext) & 0xffffffffffffLL;
switch (ext) {
case EXT_COMMUNITY_OVS_VALID:
- printf("valid ");
- break;
+ snprintf(buf, sizeof(buf), "%s valid ",
+ log_ext_subtype(type, subtype));
+ return buf;
case EXT_COMMUNITY_OVS_NOTFOUND:
- printf("not-found ");
- break;
+ snprintf(buf, sizeof(buf), "%s not-found ",
+ log_ext_subtype(type, subtype));
+ return buf;
case EXT_COMMUNITY_OVS_INVALID:
- printf("invalid ");
- break;
+ snprintf(buf, sizeof(buf), "%s invalid ",
+ log_ext_subtype(type, subtype));
+ return buf;
default:
- printf("0x%llx ", (unsigned long long)ext);
- break;
+ snprintf(buf, sizeof(buf), "%s 0x%llx ",
+ log_ext_subtype(type, subtype),
+ (unsigned long long)ext);
+ return buf;
}
break;
default:
memcpy(&ext, data, sizeof(ext));
- printf("0x%llx", (unsigned long long)be64toh(ext));
+ snprintf(buf, sizeof(buf), "%s 0x%llx",
+ log_ext_subtype(type, subtype),
+ (unsigned long long)be64toh(ext));
+ return buf;
}
}
void
-show_communities(u_char *data, size_t len, int flag0)
-{
- struct community c;
- size_t i;
- u_int64_t ext;
- u_int8_t type = 0, nt;
-
- if (len % sizeof(c))
- return;
-
- for (i = 0; i < len; i += sizeof(c)) {
- memcpy(&c, data + i, sizeof(c));
-
- nt = c.flags;
- if (type != nt) {
- if (type != 0)
- printf("%c", EOL0(flag0));
- printf(" %s:", print_attr(nt,
- ATTR_OPTIONAL | ATTR_TRANSITIVE));
- type = nt;
- }
- printf(" ");
-
- switch (nt) {
- case COMMUNITY_TYPE_BASIC:
- print_community(c.data1, c.data2);
- break;
- case COMMUNITY_TYPE_LARGE:
- printf("%u:%u:%u", c.data1, c.data2, c.data3);
- break;
- case COMMUNITY_TYPE_EXT:
- ext = (u_int64_t)c.data3 << 48;
- switch (c.data3 >> 8) {
- case EXT_COMMUNITY_TRANS_TWO_AS:
- case EXT_COMMUNITY_TRANS_OPAQUE:
- case EXT_COMMUNITY_TRANS_EVPN:
- case EXT_COMMUNITY_NON_TRANS_OPAQUE:
- ext |= ((u_int64_t)c.data1 & 0xffff) << 32;
- ext |= (u_int64_t)c.data2;
- break;
- case EXT_COMMUNITY_TRANS_FOUR_AS:
- case EXT_COMMUNITY_TRANS_IPV4:
- ext |= (u_int64_t)c.data1 << 16;
- ext |= (u_int64_t)c.data2 & 0xffff;
- break;
- }
- ext = htobe64(ext);
-
- print_ext_community((void *)&ext);
- break;
- }
- }
-
- printf("%c", EOL0(flag0));
-}
-
-void
-show_community(u_char *data, u_int16_t len)
-{
- u_int16_t a, v;
- u_int16_t i;
-
- if (len & 0x3)
- return;
-
- for (i = 0; i < len; i += 4) {
- memcpy(&a, data + i, sizeof(a));
- memcpy(&v, data + i + 2, sizeof(v));
- a = ntohs(a);
- v = ntohs(v);
- print_community(a, v);
- if (i + 4 < len)
- printf(" ");
- }
-}
-
-void
-show_large_community(u_char *data, u_int16_t len)
-{
- u_int32_t a, l1, l2;
- u_int16_t i;
-
- if (len % 12)
- return;
-
- for (i = 0; i < len; i += 12) {
- memcpy(&a, data + i, sizeof(a));
- memcpy(&l1, data + i + 4, sizeof(l1));
- memcpy(&l2, data + i + 8, sizeof(l2));
- a = ntohl(a);
- l1 = ntohl(l1);
- l2 = ntohl(l2);
- printf("%u:%u:%u", a, l1, l2);
-
- if (i + 12 < len)
- printf(" ");
- }
-}
-
-void
-show_ext_community(u_char *data, u_int16_t len)
-{
- u_int16_t i;
-
- if (len & 0x7)
- return;
-
- for (i = 0; i < len; i += 8) {
- print_ext_community(data + i);
-
- if (i + 8 < len)
- printf(" ");
- }
-}
-
-const char *
-fmt_mem(long long num)
-{
- static char buf[16];
-
- if (fmt_scaled(num, buf) == -1)
- snprintf(buf, sizeof(buf), "%lldB", num);
-
- return (buf);
-}
-
-void
send_filterset(struct imsgbuf *i, struct filter_set_head *set)
{
struct filter_set *s;
@@ -1299,73 +979,6 @@ send_filterset(struct imsgbuf *i, struct filter_set_head *set)
}
}
-const char *
-get_errstr(u_int8_t errcode, u_int8_t subcode)
-{
- static char errbuf[256];
- const char *errstr = NULL;
- const char *suberr = NULL;
- int uk = 0;
-
- if (errcode == 0) /* no error */
- return NULL;
-
- if (errcode < sizeof(errnames)/sizeof(char *))
- errstr = errnames[errcode];
-
- switch (errcode) {
- case ERR_HEADER:
- if (subcode < sizeof(suberr_header_names)/sizeof(char *))
- suberr = suberr_header_names[subcode];
- else
- uk = 1;
- break;
- case ERR_OPEN:
- if (subcode < sizeof(suberr_open_names)/sizeof(char *))
- suberr = suberr_open_names[subcode];
- else
- uk = 1;
- break;
- case ERR_UPDATE:
- if (subcode < sizeof(suberr_update_names)/sizeof(char *))
- suberr = suberr_update_names[subcode];
- else
- uk = 1;
- break;
- case ERR_HOLDTIMEREXPIRED:
- if (subcode != 0)
- uk = 1;
- break;
- case ERR_FSM:
- if (subcode < sizeof(suberr_fsm_names)/sizeof(char *))
- suberr = suberr_fsm_names[subcode];
- else
- uk = 1;
- break;
- case ERR_CEASE:
- if (subcode < sizeof(suberr_cease_names)/sizeof(char *))
- suberr = suberr_cease_names[subcode];
- else
- uk = 1;
- break;
- default:
- snprintf(errbuf, sizeof(errbuf),
- "unknown error code %u subcode %u", errcode, subcode);
- return (errbuf);
- }
-
- if (uk)
- snprintf(errbuf, sizeof(errbuf),
- "%s, unknown subcode %u", errstr, subcode);
- else if (suberr == NULL)
- return (errstr);
- else
- snprintf(errbuf, sizeof(errbuf),
- "%s, %s", errstr, suberr);
-
- return (errbuf);
-}
-
void
network_bulk(struct parse_result *res)
{
@@ -1514,8 +1127,7 @@ show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
if (req->flags & F_CTL_DETAIL) {
for (j = 0; j < mre->nattrs; j++)
show_attr(mre->attrs[j].attr,
- mre->attrs[j].attr_len,
- req->flags);
+ mre->attrs[j].attr_len, &res);
}
}
}
@@ -1603,7 +1215,7 @@ network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg)
}
static const char *
-print_time(struct timespec *t)
+fmt_time(struct timespec *t)
{
static char timebuf[32];
static struct timespec prevtime;
@@ -1619,7 +1231,7 @@ print_time(struct timespec *t)
void
show_mrt_state(struct mrt_bgp_state *ms, void *arg)
{
- printf("%s %s[%u] -> ", print_time(&ms->time),
+ printf("%s %s[%u] -> ", fmt_time(&ms->time),
log_addr(&ms->src), ms->src_as);
printf("%s[%u]: %s -> %s\n", log_addr(&ms->dst), ms->dst_as,
statenames[ms->old_state], statenames[ms->new_state]);
@@ -1998,7 +1610,7 @@ show_mrt_msg(struct mrt_bgp_msg *mm, void *arg)
u_int16_t len;
u_int8_t type;
- printf("%s %s[%u] -> ", print_time(&mm->time),
+ printf("%s %s[%u] -> ", fmt_time(&mm->time),
log_addr(&mm->src), mm->src_as);
printf("%s[%u]: size %u ", log_addr(&mm->dst), mm->dst_as, mm->msg_len);
p = mm->msg;
diff --git a/usr.sbin/bgpctl/bgpctl.h b/usr.sbin/bgpctl/bgpctl.h
index d6090eb27d2..eb8a242d5d4 100644
--- a/usr.sbin/bgpctl/bgpctl.h
+++ b/usr.sbin/bgpctl/bgpctl.h
@@ -22,6 +22,8 @@ void show_fib(struct kroute_full *);
void show_fib_table(struct ktable *);
void show_nexthop(struct ctl_show_nexthop *);
void show_interface(struct ctl_show_interface *);
+void show_attr(u_char *, size_t, struct parse_result *);
+void show_communities(u_char *, size_t, struct parse_result *);
void show_rib(struct ctl_show_rib *, u_char *, size_t,
struct parse_result *);
void show_rib_hash(struct rde_hashstats *);
@@ -31,20 +33,18 @@ void show_result(u_int);
#define EOL0(flag) ((flag & F_CTL_SSV) ? ';' : '\n')
-void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t, u_int8_t);
-void print_neighbor_capa_mp(struct peer *);
-void print_neighbor_capa_restart(struct peer *);
-void print_neighbor_msgstats(struct peer *);
-void print_flags(u_int8_t, int);
-void show_fib_flags(u_int16_t);
-
-const char *print_ovs(u_int8_t, int);
-const char *print_origin(u_int8_t, int);
-const char *print_auth_method(enum auth_method);
-const char *fmt_mem(long long);
-
+char *fmt_peer(const char *, const struct bgpd_addr *, int);
const char *fmt_timeframe(time_t);
const char *fmt_monotime(time_t);
-char *fmt_peer(const char *, const struct bgpd_addr *, int);
-const char *get_errstr(u_int8_t, u_int8_t);
+const char *fmt_fib_flags(u_int16_t);
+const char *fmt_origin(u_int8_t, int);
+const char *fmt_flags(u_int8_t, int);
+const char *fmt_ovs(u_int8_t, int);
+const char *fmt_auth_method(enum auth_method);
+const char *fmt_mem(long long);
+const char *fmt_errstr(u_int8_t, u_int8_t);
+const char *fmt_attr(u_int8_t, u_int8_t);
+const char *fmt_community(u_int16_t, u_int16_t);
+const char *fmt_large_community(u_int32_t, u_int32_t, u_int32_t);
+const char *fmt_ext_community(u_int8_t *);
diff --git a/usr.sbin/bgpctl/output.c b/usr.sbin/bgpctl/output.c
index d41c19aaacd..771a41fab59 100644
--- a/usr.sbin/bgpctl/output.c
+++ b/usr.sbin/bgpctl/output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: output.c,v 1.5 2020/01/24 05:46:00 claudio Exp $ */
+/* $OpenBSD: output.c,v 1.6 2020/03/20 07:56:34 claudio Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@@ -86,9 +86,9 @@ show_head(struct parse_result *res)
static void
show_summary(struct peer *p)
{
- char *s;
- const char *a;
- size_t alen;
+ char *s;
+ const char *a;
+ size_t alen;
s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
p->conf.remote_masklen);
@@ -125,6 +125,79 @@ show_summary(struct peer *p)
}
static void
+show_neighbor_capa_mp(struct peer *p)
+{
+ int comma;
+ u_int8_t i;
+
+ printf(" Multiprotocol extensions: ");
+ for (i = 0, comma = 0; i < AID_MAX; i++)
+ if (p->capa.peer.mp[i]) {
+ printf("%s%s", comma ? ", " : "", aid2str(i));
+ comma = 1;
+ }
+ printf("\n");
+}
+
+static void
+show_neighbor_capa_restart(struct peer *p)
+{
+ int comma;
+ u_int8_t i;
+
+ printf(" Graceful Restart");
+ if (p->capa.peer.grestart.timeout)
+ printf(": Timeout: %d, ", p->capa.peer.grestart.timeout);
+ for (i = 0, comma = 0; i < AID_MAX; i++)
+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT) {
+ if (!comma &&
+ p->capa.peer.grestart.flags[i] & CAPA_GR_RESTART)
+ printf("restarted, ");
+ if (comma)
+ printf(", ");
+ printf("%s", aid2str(i));
+ if (p->capa.peer.grestart.flags[i] & CAPA_GR_FORWARD)
+ printf(" (preserved)");
+ comma = 1;
+ }
+ printf("\n");
+}
+
+static void
+show_neighbor_msgstats(struct peer *p)
+{
+ printf(" Message statistics:\n");
+ printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
+ printf(" %-15s %10llu %10llu\n", "Opens",
+ p->stats.msg_sent_open, p->stats.msg_rcvd_open);
+ printf(" %-15s %10llu %10llu\n", "Notifications",
+ p->stats.msg_sent_notification, p->stats.msg_rcvd_notification);
+ printf(" %-15s %10llu %10llu\n", "Updates",
+ p->stats.msg_sent_update, p->stats.msg_rcvd_update);
+ printf(" %-15s %10llu %10llu\n", "Keepalives",
+ p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive);
+ printf(" %-15s %10llu %10llu\n", "Route Refresh",
+ p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh);
+ printf(" %-15s %10llu %10llu\n\n", "Total",
+ p->stats.msg_sent_open + p->stats.msg_sent_notification +
+ p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
+ p->stats.msg_sent_rrefresh,
+ p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
+ p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
+ p->stats.msg_rcvd_rrefresh);
+ printf(" Update statistics:\n");
+ printf(" %-15s %-10s %-10s\n", "", "Sent", "Received");
+ printf(" %-15s %10u %10u\n", "Prefixes",
+ p->stats.prefix_out_cnt, p->stats.prefix_cnt);
+ printf(" %-15s %10llu %10llu\n", "Updates",
+ p->stats.prefix_sent_update, p->stats.prefix_rcvd_update);
+ printf(" %-15s %10llu %10llu\n", "Withdraws",
+ p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw);
+ printf(" %-15s %10llu %10llu\n", "End-of-Rib",
+ p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor);
+}
+
+static void
show_neighbor_full(struct peer *p, struct parse_result *res)
{
struct in_addr ina;
@@ -178,7 +251,7 @@ show_neighbor_full(struct peer *p, struct parse_result *res)
printf(" BGP version 4, remote router-id %s",
inet_ntoa(ina));
- printf("%s\n", print_auth_method(p->auth.method));
+ printf("%s\n", fmt_auth_method(p->auth.method));
printf(" BGP state = %s", statenames[p->state]);
if (p->conf.down) {
printf(", marked down");
@@ -202,18 +275,12 @@ show_neighbor_full(struct peer *p, struct parse_result *res)
if (hascapamp || p->capa.peer.refresh ||
p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
printf(" Neighbor capabilities:\n");
- if (hascapamp) {
- printf(" Multiprotocol extensions: ");
- print_neighbor_capa_mp(p);
- printf("\n");
- }
+ if (hascapamp)
+ show_neighbor_capa_mp(p);
if (p->capa.peer.refresh)
printf(" Route Refresh\n");
- if (p->capa.peer.grestart.restart) {
- printf(" Graceful Restart");
- print_neighbor_capa_restart(p);
- printf("\n");
- }
+ if (p->capa.peer.grestart.restart)
+ show_neighbor_capa_restart(p);
if (p->capa.peer.as4byte)
printf(" 4-byte AS numbers\n");
}
@@ -222,7 +289,7 @@ show_neighbor_full(struct peer *p, struct parse_result *res)
if (res->action == SHOW_NEIGHBOR_TIMERS)
return;
- print_neighbor_msgstats(p);
+ show_neighbor_msgstats(p);
printf("\n");
if (*(p->stats.last_shutcomm)) {
printf(" Last received shutdown reason: \"%s\"\n",
@@ -231,11 +298,11 @@ show_neighbor_full(struct peer *p, struct parse_result *res)
if (p->state == STATE_IDLE) {
const char *errstr;
- errstr = get_errstr(p->stats.last_sent_errcode,
+ errstr = fmt_errstr(p->stats.last_sent_errcode,
p->stats.last_sent_suberr);
if (errstr)
printf(" Last error sent: %s\n\n", errstr);
- errstr = get_errstr(p->stats.last_rcvd_errcode,
+ errstr = fmt_errstr(p->stats.last_rcvd_errcode,
p->stats.last_rcvd_suberr);
if (errstr)
printf(" Last error received: %s\n\n", errstr);
@@ -309,11 +376,9 @@ show_fib(struct kroute_full *kf)
{
char *p;
- show_fib_flags(kf->flags);
-
if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), kf->prefixlen) == -1)
err(1, NULL);
- printf("%4i %-20s ", kf->priority, p);
+ printf("%s%4i %-20s ", fmt_fib_flags(kf->flags), kf->priority, p);
free(p);
if (kf->flags & F_CONNECTED)
@@ -397,14 +462,346 @@ show_interface(struct ctl_show_interface *iface)
printf("\n");
}
+void
+show_communities(u_char *data, size_t len, struct parse_result *res)
+{
+ struct community c;
+ size_t i;
+ u_int64_t ext;
+ u_int8_t type = 0, nt;
+
+ if (len % sizeof(c))
+ return;
+
+ for (i = 0; i < len; i += sizeof(c)) {
+ memcpy(&c, data + i, sizeof(c));
+
+ nt = c.flags;
+ if (type != nt) {
+ if (type != 0)
+ printf("%c", EOL0(res->flags));
+ printf(" %s:", fmt_attr(nt,
+ ATTR_OPTIONAL | ATTR_TRANSITIVE));
+ type = nt;
+ }
+
+ switch (nt) {
+ case COMMUNITY_TYPE_BASIC:
+ printf(" %s", fmt_community(c.data1, c.data2));
+ break;
+ case COMMUNITY_TYPE_LARGE:
+ printf(" %s",
+ fmt_large_community(c.data1, c.data2, c.data3));
+ break;
+ case COMMUNITY_TYPE_EXT:
+ ext = (u_int64_t)c.data3 << 48;
+ switch (c.data3 >> 8) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ case EXT_COMMUNITY_TRANS_OPAQUE:
+ case EXT_COMMUNITY_TRANS_EVPN:
+ case EXT_COMMUNITY_NON_TRANS_OPAQUE:
+ ext |= ((u_int64_t)c.data1 & 0xffff) << 32;
+ ext |= (u_int64_t)c.data2;
+ break;
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ case EXT_COMMUNITY_TRANS_IPV4:
+ ext |= (u_int64_t)c.data1 << 16;
+ ext |= (u_int64_t)c.data2 & 0xffff;
+ break;
+ }
+ ext = htobe64(ext);
+
+ printf(" %s", fmt_ext_community((void *)&ext));
+ break;
+ }
+ }
+
+ printf("%c", EOL0(res->flags));
+}
+
+static void
+show_community(u_char *data, u_int16_t len)
+{
+ u_int16_t a, v;
+ u_int16_t i;
+
+ if (len & 0x3)
+ return;
+
+ for (i = 0; i < len; i += 4) {
+ memcpy(&a, data + i, sizeof(a));
+ memcpy(&v, data + i + 2, sizeof(v));
+ a = ntohs(a);
+ v = ntohs(v);
+ printf("%s", fmt_community(a, v));
+
+ if (i + 4 < len)
+ printf(" ");
+ }
+}
+
+static void
+show_large_community(u_char *data, u_int16_t len)
+{
+ u_int32_t a, l1, l2;
+ u_int16_t i;
+
+ if (len % 12)
+ return;
+
+ for (i = 0; i < len; i += 12) {
+ memcpy(&a, data + i, sizeof(a));
+ memcpy(&l1, data + i + 4, sizeof(l1));
+ memcpy(&l2, data + i + 8, sizeof(l2));
+ a = ntohl(a);
+ l1 = ntohl(l1);
+ l2 = ntohl(l2);
+ printf("%s", fmt_large_community(a, l1, l2));
+
+ if (i + 12 < len)
+ printf(" ");
+ }
+}
+
+static void
+show_ext_community(u_char *data, u_int16_t len)
+{
+ u_int16_t i;
+
+ if (len & 0x7)
+ return;
+
+ for (i = 0; i < len; i += 8) {
+ printf("%s", fmt_ext_community(data + i));
+
+ if (i + 8 < len)
+ printf(" ");
+ }
+}
+
+void
+show_attr(u_char *data, size_t len, struct parse_result *res)
+{
+ u_char *path;
+ struct in_addr id;
+ struct bgpd_addr prefix;
+ char *aspath;
+ u_int32_t as;
+ u_int16_t alen, ioff, short_as, afi;
+ u_int8_t flags, type, safi, aid, prefixlen;
+ int i, pos, e2, e4;
+
+ if (len < 3)
+ errx(1, "show_attr: too short bgp attr");
+
+ flags = data[0];
+ type = data[1];
+
+ /* get the attribute length */
+ if (flags & ATTR_EXTLEN) {
+ if (len < 4)
+ errx(1, "show_attr: too short bgp attr");
+ memcpy(&alen, data+2, sizeof(u_int16_t));
+ alen = ntohs(alen);
+ data += 4;
+ len -= 4;
+ } else {
+ alen = data[2];
+ data += 3;
+ len -= 3;
+ }
+
+ /* bad imsg len how can that happen!? */
+ if (alen > len)
+ errx(1, "show_attr: bad length");
+
+ printf(" %s: ", fmt_attr(type, flags));
+
+ switch (type) {
+ case ATTR_ORIGIN:
+ if (alen == 1)
+ printf("%u", *data);
+ else
+ printf("bad length");
+ break;
+ case ATTR_ASPATH:
+ case ATTR_AS4_PATH:
+ /* prefer 4-byte AS here */
+ e4 = aspath_verify(data, alen, 1);
+ e2 = aspath_verify(data, alen, 0);
+ if (e4 == 0 || e4 == AS_ERR_SOFT) {
+ path = data;
+ } else if (e2 == 0 || e2 == AS_ERR_SOFT) {
+ path = aspath_inflate(data, alen, &alen);
+ if (path == NULL)
+ errx(1, "aspath_inflate failed");
+ } else {
+ printf("bad AS-Path");
+ break;
+ }
+ if (aspath_asprint(&aspath, path, alen) == -1)
+ err(1, NULL);
+ printf("%s", aspath);
+ free(aspath);
+ if (path != data)
+ free(path);
+ break;
+ case ATTR_NEXTHOP:
+ if (alen == 4) {
+ memcpy(&id, data, sizeof(id));
+ printf("%s", inet_ntoa(id));
+ } else
+ printf("bad length");
+ break;
+ case ATTR_MED:
+ case ATTR_LOCALPREF:
+ if (alen == 4) {
+ u_int32_t val;
+ memcpy(&val, data, sizeof(val));
+ val = ntohl(val);
+ printf("%u", val);
+ } else
+ printf("bad length");
+ break;
+ case ATTR_AGGREGATOR:
+ case ATTR_AS4_AGGREGATOR:
+ if (alen == 8) {
+ memcpy(&as, data, sizeof(as));
+ memcpy(&id, data + sizeof(as), sizeof(id));
+ as = ntohl(as);
+ } else if (alen == 6) {
+ memcpy(&short_as, data, sizeof(short_as));
+ memcpy(&id, data + sizeof(short_as), sizeof(id));
+ as = ntohs(short_as);
+ } else {
+ printf("bad length");
+ break;
+ }
+ printf("%s [%s]", log_as(as), inet_ntoa(id));
+ break;
+ case ATTR_COMMUNITIES:
+ show_community(data, alen);
+ break;
+ case ATTR_ORIGINATOR_ID:
+ memcpy(&id, data, sizeof(id));
+ printf("%s", inet_ntoa(id));
+ break;
+ case ATTR_CLUSTER_LIST:
+ for (ioff = 0; ioff + sizeof(id) <= alen;
+ ioff += sizeof(id)) {
+ memcpy(&id, data + ioff, sizeof(id));
+ printf(" %s", inet_ntoa(id));
+ }
+ break;
+ case ATTR_MP_REACH_NLRI:
+ case ATTR_MP_UNREACH_NLRI:
+ if (alen < 3) {
+ bad_len:
+ printf("bad length");
+ break;
+ }
+ memcpy(&afi, data, 2);
+ data += 2;
+ alen -= 2;
+ afi = ntohs(afi);
+ safi = *data++;
+ alen--;
+
+ if (afi2aid(afi, safi, &aid) == -1) {
+ printf("bad AFI/SAFI pair");
+ break;
+ }
+ printf(" %s", aid2str(aid));
+
+ if (type == ATTR_MP_REACH_NLRI) {
+ struct bgpd_addr nexthop;
+ u_int8_t nhlen;
+ if (len == 0)
+ goto bad_len;
+ nhlen = *data++;
+ alen--;
+ if (nhlen > len)
+ goto bad_len;
+ bzero(&nexthop, sizeof(nexthop));
+ switch (aid) {
+ case AID_INET6:
+ nexthop.aid = aid;
+ if (nhlen != 16 && nhlen != 32)
+ goto bad_len;
+ memcpy(&nexthop.v6.s6_addr, data, 16);
+ break;
+ case AID_VPN_IPv4:
+ if (nhlen != 12)
+ goto bad_len;
+ nexthop.aid = AID_INET;
+ memcpy(&nexthop.v4, data + sizeof(u_int64_t),
+ sizeof(nexthop.v4));
+ break;
+ default:
+ printf("unhandled AID #%u", aid);
+ goto done;
+ }
+ /* ignore reserved (old SNPA) field as per RFC4760 */
+ data += nhlen + 1;
+ alen -= nhlen + 1;
+
+ printf(" nexthop: %s", log_addr(&nexthop));
+ }
+
+ while (alen > 0) {
+ switch (aid) {
+ case AID_INET6:
+ pos = nlri_get_prefix6(data, alen, &prefix,
+ &prefixlen);
+ break;
+ case AID_VPN_IPv4:
+ pos = nlri_get_vpn4(data, alen, &prefix,
+ &prefixlen, 1);
+ break;
+ default:
+ printf("unhandled AID #%u", aid);
+ goto done;
+ }
+ if (pos == -1) {
+ printf("bad %s prefix", aid2str(aid));
+ break;
+ }
+ printf(" %s/%u", log_addr(&prefix), prefixlen);
+ data += pos;
+ alen -= pos;
+ }
+ break;
+ case ATTR_EXT_COMMUNITIES:
+ show_ext_community(data, alen);
+ break;
+ case ATTR_LARGE_COMMUNITIES:
+ show_large_community(data, alen);
+ break;
+ case ATTR_ATOMIC_AGGREGATE:
+ default:
+ printf(" len %u", alen);
+ if (alen) {
+ printf(":");
+ for (i=0; i < alen; i++)
+ printf(" %02x", *(data+i));
+ }
+ break;
+ }
+ done:
+ printf("%c", EOL0(res->flags));
+}
+
static void
show_rib_brief(struct ctl_show_rib *r, u_char *asdata, size_t aslen)
{
- char *aspath;
+ char *p, *aspath;
- print_prefix(&r->prefix, r->prefixlen, r->flags, r->validation_state);
- printf(" %-15s ", log_addr(&r->exit_nexthop));
- printf(" %5u %5u ", r->local_pref, r->med);
+ if (asprintf(&p, "%s/%u", log_addr(&r->prefix), r->prefixlen) == -1)
+ err(1, NULL);
+ printf("%s %3s %-20s %-15s %5u %5u ",
+ fmt_flags(r->flags, 1), fmt_ovs(r->validation_state, 1), p,
+ log_addr(&r->exit_nexthop), r->local_pref, r->med);
+ free(p);
if (aspath_asprint(&aspath, asdata, aslen) == -1)
err(1, NULL);
@@ -412,7 +809,7 @@ show_rib_brief(struct ctl_show_rib *r, u_char *asdata, size_t aslen)
printf("%s ", aspath);
free(aspath);
- printf("%s\n", print_origin(r->origin, 1));
+ printf("%s\n", fmt_origin(r->origin, 1));
}
static void
@@ -440,9 +837,9 @@ show_rib_detail(struct ctl_show_rib *r, u_char *asdata, size_t aslen,
printf("%s)%c", inet_ntoa(id), EOL0(flag0));
printf(" Origin %s, metric %u, localpref %u, weight %u, ovs %s, ",
- print_origin(r->origin, 0), r->med, r->local_pref, r->weight,
- print_ovs(r->validation_state, 0));
- print_flags(r->flags, 0);
+ fmt_origin(r->origin, 0), r->med, r->local_pref, r->weight,
+ fmt_ovs(r->validation_state, 0));
+ printf("%s", fmt_flags(r->flags, 0));
printf("%c Last update: %s ago%c", EOL0(flag0),
fmt_timeframe(r->age), EOL0(flag0));