Claudio Jeker([email protected]) on 2020.03.19 18:42:28 +0100:
> Move some more output functions to output.c and convert some other
> functions to a fmt_xyz() function that returns a string with the value
> instead of doing a printf(). This is mostly mechanical but please test.
>
ok
> --
> :wq Claudio
>
> Index: bgpctl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
> retrieving revision 1.258
> diff -u -p -r1.258 bgpctl.c
> --- bgpctl.c 24 Jan 2020 05:46:00 -0000 1.258
> +++ bgpctl.c 19 Mar 2020 17:36:18 -0000
> @@ -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_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_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_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
> }
>
> 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 metho
> }
> }
>
> -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
> }
> }
>
> -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));
> + static char buf[12];
>
> - 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 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
> }
> }
>
> -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
> 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, str
> }
>
> 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, voi
> 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;
> Index: bgpctl.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 bgpctl.h
> --- bgpctl.h 9 Jan 2020 11:57:04 -0000 1.3
> +++ bgpctl.h 19 Mar 2020 17:32:00 -0000
> @@ -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 *);
>
> Index: output.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 output.c
> --- output.c 24 Jan 2020 05:46:00 -0000 1.5
> +++ output.c 19 Mar 2020 17:37:55 -0000
> @@ -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, struc
>
> 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, struc
> 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, struc
> 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, struc
> 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
> 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
> 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,
> 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));
>