diff options
Diffstat (limited to 'net/openbgpd/files/patch-bgpctl_bgpctl.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpctl_bgpctl.c | 1529 |
1 files changed, 1529 insertions, 0 deletions
diff --git a/net/openbgpd/files/patch-bgpctl_bgpctl.c b/net/openbgpd/files/patch-bgpctl_bgpctl.c new file mode 100644 index 000000000000..1553efc83281 --- /dev/null +++ b/net/openbgpd/files/patch-bgpctl_bgpctl.c @@ -0,0 +1,1529 @@ +Index: bgpctl/bgpctl.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.c,v +retrieving revision 1.1.1.7 +retrieving revision 1.10 +diff -u -p -r1.1.1.7 -r1.10 +--- bgpctl/bgpctl.c 14 Feb 2010 20:20:14 -0000 1.1.1.7 ++++ bgpctl/bgpctl.c 8 Dec 2012 20:17:55 -0000 1.10 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: bgpctl.c,v 1.142 2009/06/06 06:33:15 eric Exp $ */ ++/* $OpenBSD: bgpctl.c,v 1.167 2012/11/15 19:55:08 sthen Exp $ */ + + /* + * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> +@@ -16,11 +16,19 @@ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#if defined(__FreeBSD__) /* compat */ ++#include "openbsd-compat.h" ++#endif /* defined(__FreeBSD__) */ ++ + #include <sys/types.h> + #include <sys/socket.h> + #include <sys/un.h> + #include <net/if.h> ++#if defined(__FreeBSD__) /* net/if_media.h */ ++#include "if_media.h" ++#else + #include <net/if_media.h> ++#endif /* defined(__FreeBSD__) */ + #include <net/if_types.h> + + #include <err.h> +@@ -29,7 +37,11 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#if defined(__FreeBSD__) /* util.h */ ++#include "util.h" ++#else + #include <util.h> ++#endif /* defined(__FreeBSD__) */ + + #include "bgpd.h" + #include "session.h" +@@ -37,6 +49,11 @@ + #include "log.h" + #include "parser.h" + #include "irrfilter.h" ++#include "mrtparser.h" ++ ++#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */ ++#define LINK_STATE_IS_UP(_s) ((_s) >= LINK_STATE_UP) ++#endif /* defined(__FreeBSD__) */ + + enum neighbor_views { + NV_DEFAULT, +@@ -50,12 +67,14 @@ int show_summary_msg(struct imsg *, in + int show_summary_terse_msg(struct imsg *, int); + int show_neighbor_terse(struct imsg *); + int show_neighbor_msg(struct imsg *, enum neighbor_views); +-void print_neighbor_capa_mp_safi(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_timer(const char *, time_t); + static char *fmt_timeframe(time_t t); + static char *fmt_timeframe_core(time_t t); + void show_fib_head(void); ++void show_fib_tables_head(void); + void show_network_head(void); + void show_fib_flags(u_int16_t); + int show_fib_msg(struct imsg *); +@@ -65,7 +84,7 @@ void show_interface_head(void); + int ift2ifm(int); + const char * get_media_descr(int); + const char * get_linkstate(int, int); +-void print_baudrate(u_int64_t); ++const char * get_baudrate(u_int64_t, char *); + int show_interface_msg(struct imsg *); + void show_rib_summary_head(void); + void print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t); +@@ -73,16 +92,25 @@ const char * print_origin(u_int8_t, int + void print_flags(u_int8_t, int); + int show_rib_summary_msg(struct imsg *); + int show_rib_detail_msg(struct imsg *, int); ++void show_rib_brief(struct ctl_show_rib *, u_char *); ++void show_rib_detail(struct ctl_show_rib *, u_char *, int); ++void show_attr(void *, u_int16_t); + void show_community(u_char *, u_int16_t); +-const char *get_ext_subtype(u_int8_t); + void show_ext_community(u_char *, u_int16_t); + char *fmt_mem(int64_t); + int show_rib_memory_msg(struct imsg *); + void send_filterset(struct imsgbuf *, struct filter_set_head *); + static const char *get_errstr(u_int8_t, u_int8_t); + int show_result(struct imsg *); ++void show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); ++void network_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *); ++void show_mrt_state(struct mrt_bgp_state *, void *); ++void show_mrt_msg(struct mrt_bgp_msg *, void *); ++void mrt_to_bgpd_addr(union mrt_addr *, struct bgpd_addr *); + + struct imsgbuf *ibuf; ++struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg }; ++struct mrt_parser net_mrt = { network_mrt_dump, NULL, NULL }; + + __dead void + usage(void) +@@ -98,7 +126,7 @@ int + main(int argc, char *argv[]) + { + struct sockaddr_un sun; +- int fd, n, done, ch, nodescr = 0; ++ int fd, n, done, ch, nodescr = 0, verbose = 0; + struct imsg imsg; + struct network_config net; + struct parse_result *res; +@@ -128,8 +156,11 @@ main(int argc, char *argv[]) + if ((res = parse(argc, argv)) == NULL) + exit(1); + +- if (res->action == IRRFILTER) ++ if (res->action == IRRFILTER) { ++ if (!(res->flags & (F_IPV4|F_IPV6))) ++ res->flags |= (F_IPV4|F_IPV6); + irr_main(res->as.as, res->flags, res->irr_outdir); ++ } + + memcpy(&neighbor.addr, &res->peeraddr, sizeof(neighbor.addr)); + strlcpy(neighbor.descr, res->peerdesc, sizeof(neighbor.descr)); +@@ -154,7 +185,7 @@ main(int argc, char *argv[]) + case NONE: + case IRRFILTER: + usage(); +- /* not reached */ ++ /* NOTREACHED */ + case SHOW: + case SHOW_SUMMARY: + imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, NULL, 0); +@@ -164,24 +195,32 @@ main(int argc, char *argv[]) + imsg_compose(ibuf, IMSG_CTL_SHOW_TERSE, 0, 0, -1, NULL, 0); + break; + case SHOW_FIB: +- if (!res->addr.af) { +- struct buf *msg; +- +- if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, 0, 0, +- sizeof(res->flags) + sizeof(res->af))) == NULL) ++ if (!res->addr.aid) { ++ struct ibuf *msg; ++ sa_family_t af; ++ ++ af = aid2af(res->aid); ++ if ((msg = imsg_create(ibuf, IMSG_CTL_KROUTE, ++ res->rtableid, 0, sizeof(res->flags) + ++ sizeof(af))) == NULL) + errx(1, "imsg_create failure"); + if (imsg_add(msg, &res->flags, sizeof(res->flags)) == + -1 || +- imsg_add(msg, &res->af, sizeof(res->af)) == -1) ++ imsg_add(msg, &af, sizeof(af)) == -1) + errx(1, "imsg_add failure"); + imsg_close(ibuf, msg); + } else +- imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, +- &res->addr, sizeof(res->addr)); ++ imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, res->rtableid, ++ 0, -1, &res->addr, sizeof(res->addr)); + show_fib_head(); + break; ++ case SHOW_FIB_TABLES: ++ imsg_compose(ibuf, IMSG_CTL_SHOW_FIB_TABLES, 0, 0, -1, NULL, 0); ++ show_fib_tables_head(); ++ break; + case SHOW_NEXTHOP: +- imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_SHOW_NEXTHOP, res->rtableid, 0, -1, ++ NULL, 0); + show_nexthop_head(); + break; + case SHOW_INTERFACE: +@@ -192,7 +231,7 @@ main(int argc, char *argv[]) + case SHOW_NEIGHBOR_TIMERS: + case SHOW_NEIGHBOR_TERSE: + neighbor.show_timers = (res->action == SHOW_NEIGHBOR_TIMERS); +- if (res->peeraddr.af || res->peerdesc[0]) ++ if (res->peeraddr.aid || res->peerdesc[0]) + imsg_compose(ibuf, IMSG_CTL_SHOW_NEIGHBOR, 0, 0, -1, + &neighbor, sizeof(neighbor)); + else +@@ -206,7 +245,7 @@ main(int argc, char *argv[]) + memcpy(&ribreq.as, &res->as, sizeof(res->as)); + type = IMSG_CTL_SHOW_RIB_AS; + } +- if (res->addr.af) { ++ if (res->addr.aid) { + memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); + ribreq.prefixlen = res->prefixlen; + type = IMSG_CTL_SHOW_RIB_PREFIX; +@@ -217,15 +256,35 @@ main(int argc, char *argv[]) + sizeof(res->community)); + type = IMSG_CTL_SHOW_RIB_COMMUNITY; + } +- memcpy(&ribreq.neighbor, &neighbor, +- sizeof(ribreq.neighbor)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); + strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); +- ribreq.af = res->af; ++ ribreq.aid = res->aid; + ribreq.flags = res->flags; + imsg_compose(ibuf, type, 0, 0, -1, &ribreq, sizeof(ribreq)); + if (!(res->flags & F_CTL_DETAIL)) + show_rib_summary_head(); + break; ++ case SHOW_MRT: ++ close(fd); ++ bzero(&ribreq, sizeof(ribreq)); ++ if (res->as.type != AS_NONE) ++ memcpy(&ribreq.as, &res->as, sizeof(res->as)); ++ if (res->addr.aid) { ++ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ++ ribreq.prefixlen = res->prefixlen; ++ } ++ if (res->community.as != COMMUNITY_UNSET && ++ res->community.type != COMMUNITY_UNSET) ++ memcpy(&ribreq.community, &res->community, ++ sizeof(res->community)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); ++ ribreq.aid = res->aid; ++ ribreq.flags = res->flags; ++ show_mrt.arg = &ribreq; ++ if (!(res->flags & F_CTL_DETAIL)) ++ show_rib_summary_head(); ++ mrt_parse(res->mrtfd, &show_mrt, 1); ++ exit(0); + case SHOW_RIB_MEM: + imsg_compose(ibuf, IMSG_CTL_SHOW_RIB_MEM, 0, 0, -1, NULL, 0); + break; +@@ -237,12 +296,14 @@ main(int argc, char *argv[]) + errx(1, "action==FIB"); + break; + case FIB_COUPLE: +- imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, res->rtableid, 0, -1, ++ NULL, 0); + printf("couple request sent.\n"); + done = 1; + break; + case FIB_DECOUPLE: +- imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); ++ imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, res->rtableid, 0, -1, ++ NULL, 0); + printf("decouple request sent.\n"); + done = 1; + break; +@@ -290,12 +351,40 @@ main(int argc, char *argv[]) + break; + case NETWORK_SHOW: + bzero(&ribreq, sizeof(ribreq)); +- ribreq.af = res->af; ++ ribreq.aid = res->aid; + strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib)); + imsg_compose(ibuf, IMSG_CTL_SHOW_NETWORK, 0, 0, -1, + &ribreq, sizeof(ribreq)); + show_network_head(); + break; ++ case NETWORK_MRT: ++ bzero(&ribreq, sizeof(ribreq)); ++ if (res->as.type != AS_NONE) ++ memcpy(&ribreq.as, &res->as, sizeof(res->as)); ++ if (res->addr.aid) { ++ memcpy(&ribreq.prefix, &res->addr, sizeof(res->addr)); ++ ribreq.prefixlen = res->prefixlen; ++ } ++ if (res->community.as != COMMUNITY_UNSET && ++ res->community.type != COMMUNITY_UNSET) ++ memcpy(&ribreq.community, &res->community, ++ sizeof(res->community)); ++ memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor)); ++ ribreq.aid = res->aid; ++ ribreq.flags = res->flags; ++ net_mrt.arg = &ribreq; ++ mrt_parse(res->mrtfd, &net_mrt, 1); ++ done = 1; ++ break; ++ case LOG_VERBOSE: ++ verbose = 1; ++ /* FALLTHROUGH */ ++ case LOG_BRIEF: ++ imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, ++ &verbose, sizeof(verbose)); ++ printf("logging request sent.\n"); ++ done = 1; ++ break; + } + + while (ibuf->w.queued) +@@ -304,13 +393,13 @@ main(int argc, char *argv[]) + + while (!done) { + if ((n = imsg_read(ibuf)) == -1) +- errx(1, "imsg_read error"); ++ err(1, "imsg_read error"); + if (n == 0) + errx(1, "pipe closed"); + + while (!done) { + if ((n = imsg_get(ibuf, &imsg)) == -1) +- errx(1, "imsg_get error"); ++ err(1, "imsg_get error"); + if (n == 0) + break; + +@@ -329,6 +418,8 @@ main(int argc, char *argv[]) + done = show_summary_terse_msg(&imsg, nodescr); + break; + case SHOW_FIB: ++ case SHOW_FIB_TABLES: ++ case NETWORK_SHOW: + done = show_fib_msg(&imsg); + break; + case SHOW_NEXTHOP: +@@ -356,9 +447,6 @@ main(int argc, char *argv[]) + case SHOW_RIB_MEM: + done = show_rib_memory_msg(&imsg); + break; +- case NETWORK_SHOW: +- done = show_fib_msg(&imsg); +- break; + case NEIGHBOR: + case NEIGHBOR_UP: + case NEIGHBOR_DOWN: +@@ -373,6 +461,10 @@ main(int argc, char *argv[]) + case NETWORK_REMOVE: + case NETWORK_FLUSH: + case IRRFILTER: ++ case LOG_VERBOSE: ++ case LOG_BRIEF: ++ case SHOW_MRT: ++ case NETWORK_MRT: + break; + } + imsg_free(&imsg); +@@ -398,8 +490,8 @@ fmt_peer(const char *descr, const struct + } + + ip = log_addr(remote_addr); +- if (masklen != -1 && ((remote_addr->af == AF_INET && masklen != 32) || +- (remote_addr->af == AF_INET6 && masklen != 128))) { ++ if (masklen != -1 && ((remote_addr->aid == AID_INET && masklen != 32) || ++ (remote_addr->aid == AID_INET6 && masklen != 128))) { + if (asprintf(&p, "%s/%u", ip, masklen) == -1) + err(1, NULL); + } else { +@@ -430,7 +522,7 @@ show_summary_msg(struct imsg *imsg, int + p->conf.remote_masklen, nodescr); + if (strlen(s) >= 20) + s[20] = 0; +- printf("%-20s %8s %10llu %10llu %5u %-8s ", ++ printf("%-20s %8s %10" PRIu64 " %10" PRIu64 " %5u %-8s ", + s, log_as(p->conf.remote_as), + p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification + + p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive + +@@ -492,8 +584,8 @@ show_neighbor_terse(struct imsg *imsg) + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_NEIGHBOR: + p = imsg->data; +- printf("%llu %llu %llu %llu %llu %llu %llu " +- "%llu %llu %llu %u %u %llu %llu %llu %llu\n", ++ printf("%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " " ++ "%" PRIu64 " %" PRIu64 " %" PRIu64 " %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", + p->stats.msg_sent_open, p->stats.msg_rcvd_open, + p->stats.msg_sent_notification, + p->stats.msg_rcvd_notification, +@@ -521,13 +613,15 @@ show_neighbor_msg(struct imsg *imsg, enu + struct ctl_timer *t; + struct in_addr ina; + char buf[NI_MAXHOST], pbuf[NI_MAXSERV], *s; ++ int hascapamp = 0; ++ u_int8_t i; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_NEIGHBOR: + p = imsg->data; +- if ((p->conf.remote_addr.af == AF_INET && ++ if ((p->conf.remote_addr.aid == AID_INET && + p->conf.remote_masklen != 32) || +- (p->conf.remote_addr.af == AF_INET6 && ++ (p->conf.remote_addr.aid == AID_INET6 && + p->conf.remote_masklen != 128)) { + if (asprintf(&s, "%s/%u", + log_addr(&p->conf.remote_addr), +@@ -549,9 +643,20 @@ show_neighbor_msg(struct imsg *imsg, enu + printf(", Template"); + if (p->conf.cloned) + printf(", Cloned"); ++ if (p->conf.passive) ++ printf(", Passive"); ++ if (p->conf.ebgp && p->conf.distance > 1) ++ printf(", Multihop (%u)", (int)p->conf.distance); + printf("\n"); + if (p->conf.descr[0]) + printf(" Description: %s\n", p->conf.descr); ++ if (p->conf.max_prefix) { ++ printf(" Max-prefix: %u", p->conf.max_prefix); ++ if (p->conf.max_prefix_restart) ++ printf(" (restart %u)", ++ p->conf.max_prefix_restart); ++ printf("\n"); ++ } + printf(" BGP version 4, remote router-id %s\n", + inet_ntoa(ina)); + printf(" BGP state = %s", statenames[p->state]); +@@ -563,22 +668,24 @@ show_neighbor_msg(struct imsg *imsg, enu + printf(" Last read %s, holdtime %us, keepalive interval %us\n", + fmt_timeframe(p->stats.last_read), + p->holdtime, p->holdtime/3); +- if (p->capa.peer.mp_v4 || p->capa.peer.mp_v6 || +- p->capa.peer.refresh || p->capa.peer.restart || +- p->capa.peer.as4byte) { ++ for (i = 0; i < AID_MAX; i++) ++ if (p->capa.peer.mp[i]) ++ hascapamp = 1; ++ if (hascapamp || p->capa.peer.refresh || ++ p->capa.peer.grestart.restart || p->capa.peer.as4byte) { + printf(" Neighbor capabilities:\n"); +- if (p->capa.peer.mp_v4) { +- printf(" Multiprotocol extensions: IPv4"); +- print_neighbor_capa_mp_safi(p->capa.peer.mp_v4); +- } +- if (p->capa.peer.mp_v6) { +- printf(" Multiprotocol extensions: IPv6"); +- print_neighbor_capa_mp_safi(p->capa.peer.mp_v6); ++ if (hascapamp) { ++ printf(" Multiprotocol extensions: "); ++ print_neighbor_capa_mp(p); ++ printf("\n"); + } + if (p->capa.peer.refresh) + printf(" Route Refresh\n"); +- if (p->capa.peer.restart) +- printf(" Graceful Restart\n"); ++ if (p->capa.peer.grestart.restart) { ++ printf(" Graceful Restart"); ++ print_neighbor_capa_restart(p); ++ printf("\n"); ++ } + if (p->capa.peer.as4byte) + printf(" 4-byte AS numbers\n"); + } +@@ -633,20 +740,38 @@ show_neighbor_msg(struct imsg *imsg, enu + } + + void +-print_neighbor_capa_mp_safi(u_int8_t safi) ++print_neighbor_capa_mp(struct peer *p) + { +- switch (safi) { +- case SAFI_UNICAST: +- printf(" Unicast"); +- break; +- case SAFI_MULTICAST: +- printf(" Multicast"); +- break; +- default: +- printf(" unknown (%u)", safi); +- break; +- } +- printf("\n"); ++ 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 +@@ -654,17 +779,17 @@ print_neighbor_msgstats(struct peer *p) + { + printf(" Message statistics:\n"); + printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); +- printf(" %-15s %10llu %10llu\n", "Opens", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Opens", + p->stats.msg_sent_open, p->stats.msg_rcvd_open); +- printf(" %-15s %10llu %10llu\n", "Notifications", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Notifications", + p->stats.msg_sent_notification, p->stats.msg_rcvd_notification); +- printf(" %-15s %10llu %10llu\n", "Updates", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", + p->stats.msg_sent_update, p->stats.msg_rcvd_update); +- printf(" %-15s %10llu %10llu\n", "Keepalives", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Keepalives", + p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive); +- printf(" %-15s %10llu %10llu\n", "Route Refresh", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Route Refresh", + p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh); +- printf(" %-15s %10llu %10llu\n\n", "Total", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\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, +@@ -673,14 +798,16 @@ print_neighbor_msgstats(struct peer *p) + p->stats.msg_rcvd_rrefresh); + printf(" Update statistics:\n"); + printf(" %-15s %-10s %-10s\n", "", "Sent", "Received"); +- printf(" %-15s %10llu %10llu\n", "Updates", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Updates", + p->stats.prefix_sent_update, p->stats.prefix_rcvd_update); +- printf(" %-15s %10llu %10llu\n", "Withdraws", ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "Withdraws", + p->stats.prefix_sent_withdraw, p->stats.prefix_rcvd_withdraw); ++ printf(" %-15s %10" PRIu64 " %10" PRIu64 "\n", "End-of-Rib", ++ p->stats.prefix_sent_eor, p->stats.prefix_rcvd_eor); + } + + void +-print_timer(const char *name, timer_t d) ++print_timer(const char *name, time_t d) + { + printf(" %-20s ", name); + +@@ -745,6 +872,12 @@ show_fib_head(void) + } + + void ++show_fib_tables_head(void) ++{ ++ printf("%-5s %-20s %-8s\n", "Table", "Description", "State"); ++} ++ ++void + show_network_head(void) + { + printf("flags: S = Static\n"); +@@ -788,56 +921,44 @@ show_fib_flags(u_int16_t flags) + int + show_fib_msg(struct imsg *imsg) + { +- struct kroute *k; +- struct kroute6 *k6; ++ struct kroute_full *kf; ++ struct ktable *kt; + char *p; + + switch (imsg->hdr.type) { + case IMSG_CTL_KROUTE: + case IMSG_CTL_SHOW_NETWORK: +- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) ++ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kf)) + errx(1, "wrong imsg len"); +- k = imsg->data; ++ kf = imsg->data; + +- show_fib_flags(k->flags); ++ show_fib_flags(kf->flags); + +- if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == +- -1) ++ if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), ++ kf->prefixlen) == -1) + err(1, NULL); +- printf("%4i %-20s ", k->priority, p); ++ printf("%4i %-20s ", kf->priority, p); + free(p); + +- if (k->nexthop.s_addr) +- printf("%s", inet_ntoa(k->nexthop)); +- else if (k->flags & F_CONNECTED) +- printf("link#%u", k->ifindex); ++ if (kf->flags & F_CONNECTED) ++ printf("link#%u", kf->ifindex); ++ else ++ printf("%s", log_addr(&kf->nexthop)); + printf("\n"); + + break; +- case IMSG_CTL_KROUTE6: +- case IMSG_CTL_SHOW_NETWORK6: +- if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute6)) ++ case IMSG_CTL_SHOW_FIB_TABLES: ++ if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt)) + errx(1, "wrong imsg len"); +- k6 = imsg->data; +- +- show_fib_flags(k6->flags); ++ kt = imsg->data; + +- if (asprintf(&p, "%s/%u", log_in6addr(&k6->prefix), +- k6->prefixlen) == -1) +- err(1, NULL); +- printf("%4i %-20s ", k6->priority, p); +- free(p); +- +- if (!IN6_IS_ADDR_UNSPECIFIED(&k6->nexthop)) +- printf("%s", log_in6addr(&k6->nexthop)); +- else if (k6->flags & F_CONNECTED) +- printf("link#%u", k6->ifindex); +- printf("\n"); ++ printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr, ++ kt->fib_sync ? "coupled" : "decoupled", ++ kt->fib_sync != kt->fib_conf ? "*" : ""); + + break; + case IMSG_CTL_END: + return (1); +- break; + default: + break; + } +@@ -848,35 +969,70 @@ show_fib_msg(struct imsg *imsg) + void + show_nexthop_head(void) + { +- printf("%-20s %-10s\n", "Nexthop", "State"); ++ printf("Flags: * = nexthop valid\n"); ++ printf("\n %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route", ++ "Prio", "Gateway", "Iface"); + } + + int + show_nexthop_msg(struct imsg *imsg) + { + struct ctl_show_nexthop *p; +- int ifms_type; ++ struct kroute *k; ++ struct kroute6 *k6; ++ char *s; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_NEXTHOP: + p = imsg->data; +- printf("%-20s %-10s", log_addr(&p->addr), +- p->valid ? "valid" : "invalid"); ++ printf("%s %-15s ", p->valid ? "*" : " ", log_addr(&p->addr)); ++ if (!p->krvalid) { ++ printf("\n"); ++ return (0); ++ } ++ switch (p->addr.aid) { ++ case AID_INET: ++ k = &p->kr.kr4; ++ if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix), ++ k->prefixlen) == -1) ++ err(1, NULL); ++ printf("%-20s", s); ++ free(s); ++ printf("%3i %-15s ", k->priority, ++ k->flags & F_CONNECTED ? "connected" : ++ inet_ntoa(k->nexthop)); ++ break; ++ case AID_INET6: ++ k6 = &p->kr.kr6; ++ if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix), ++ k6->prefixlen) == -1) ++ err(1, NULL); ++ printf("%-20s", s); ++ free(s); ++ printf("%3i %-15s ", k6->priority, ++ k6->flags & F_CONNECTED ? "connected" : ++ log_in6addr(&k6->nexthop)); ++ break; ++ default: ++ printf("unknown address family\n"); ++ return (0); ++ } + if (p->kif.ifname[0]) { +- printf("%-8s", p->kif.ifname); +- if (p->kif.flags & IFF_UP) { +- printf("UP"); +- ifms_type = ift2ifm(p->kif.media_type); +- if (ifms_type != 0) +- printf(", %s, %s", +- get_media_descr(ifms_type), +- get_linkstate(ifms_type, +- p->kif.link_state)); +- if (p->kif.baudrate) { +- printf(", "); +- print_baudrate(p->kif.baudrate); +- } +- } ++ char *s1; ++ if (p->kif.baudrate) { ++ if (asprintf(&s1, ", %s", ++ get_baudrate(p->kif.baudrate, ++ "bps")) == -1) ++ err(1, NULL); ++ } else if (asprintf(&s1, ", %s", get_linkstate( ++ p->kif.media_type, p->kif.link_state)) == -1) ++ err(1, NULL); ++ if (asprintf(&s, "%s (%s%s)", p->kif.ifname, ++ p->kif.flags & IFF_UP ? "UP" : "DOWN", s1) == -1) ++ err(1, NULL); ++ printf("%-15s", s); ++ free(s1); ++ free(s); + } + printf("\n"); + break; +@@ -898,9 +1054,8 @@ show_interface_head(void) + "Link state"); + } + +-const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; +-const struct ifmedia_status_description +- ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; ++const struct if_status_description ++ if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; + const struct ifmedia_description + ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; + +@@ -936,36 +1091,36 @@ get_media_descr(int media_type) + const char * + get_linkstate(int media_type, int link_state) + { +- const struct ifmedia_status_description *p; +- int i; +- +- if (link_state == LINK_STATE_UNKNOWN) +- return ("unknown"); +- +- for (i = 0; ifm_status_valid_list[i] != 0; i++) +- for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { +- if (p->ifms_type != media_type || +- p->ifms_valid != ifm_status_valid_list[i]) +- continue; +- if (LINK_STATE_IS_UP(link_state)) +- return (p->ifms_string[1]); +- return (p->ifms_string[0]); +- } ++ const struct if_status_description *p; ++ static char buf[8]; + +- return ("unknown link state"); ++ for (p = if_status_descriptions; p->ifs_string != NULL; p++) { ++ if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) ++ return (p->ifs_string); ++ } ++ snprintf(buf, sizeof(buf), "[#%d]", link_state); ++ return (buf); + } + +-void +-print_baudrate(u_int64_t baudrate) ++const char * ++get_baudrate(u_int64_t baudrate, char *unit) + { ++ static char bbuf[16]; ++ + if (baudrate > IF_Gbps(1)) +- printf("%llu GBit/s", baudrate / IF_Gbps(1)); ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " G%s", ++ baudrate / IF_Gbps(1), unit); + else if (baudrate > IF_Mbps(1)) +- printf("%llu MBit/s", baudrate / IF_Mbps(1)); ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " M%s", ++ baudrate / IF_Mbps(1), unit); + else if (baudrate > IF_Kbps(1)) +- printf("%llu KBit/s", baudrate / IF_Kbps(1)); ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " K%s", ++ baudrate / IF_Kbps(1), unit); + else +- printf("%llu Bit/s", baudrate); ++ snprintf(bbuf, sizeof(bbuf), "%" PRIu64 " %s", ++ baudrate, unit); ++ ++ return (bbuf); + } + + int +@@ -982,17 +1137,12 @@ show_interface_msg(struct imsg *imsg) + printf("%-15s", k->flags & IFF_UP ? "UP" : ""); + + if ((ifms_type = ift2ifm(k->media_type)) != 0) +- printf("%s, %s", get_media_descr(ifms_type), +- get_linkstate(ifms_type, k->link_state)); +- else if (k->link_state == LINK_STATE_UNKNOWN) +- printf("unknown"); +- else +- printf("link state %u", k->link_state); ++ printf("%s, ", get_media_descr(ifms_type)); + +- if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { +- printf(", "); +- print_baudrate(k->baudrate); +- } ++ printf("%s", get_linkstate(k->media_type, k->link_state)); ++ ++ if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) ++ printf(", %s", get_baudrate(k->baudrate, "Bit/s")); + printf("\n"); + break; + case IMSG_CTL_END: +@@ -1008,10 +1158,10 @@ show_interface_msg(struct imsg *imsg) + void + show_rib_summary_head(void) + { +- printf( +- "flags: * = Valid, > = Selected, I = via IBGP, A = Announced\n"); ++ printf("flags: * = Valid, > = Selected, I = via IBGP, A = Announced, " ++ "S = Stale\n"); + printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n"); +- printf("%-5s %-20s%-15s %5s %5s %s\n", "flags", "destination", ++ printf("%-5s %-20s %-15s %5s %5s %s\n", "flags", "destination", + "gateway", "lpref", "med", "aspath origin"); + } + +@@ -1049,26 +1199,30 @@ print_flags(u_int8_t flags, int sum) + char *p = flagstr; + + if (sum) { +- if (flags & F_RIB_ANNOUNCE) ++ if (flags & F_PREF_ANNOUNCE) + *p++ = 'A'; +- if (flags & F_RIB_INTERNAL) ++ if (flags & F_PREF_INTERNAL) + *p++ = 'I'; +- if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_STALE) ++ *p++ = 'S'; ++ if (flags & F_PREF_ELIGIBLE) + *p++ = '*'; +- if (flags & F_RIB_ACTIVE) ++ if (flags & F_PREF_ACTIVE) + *p++ = '>'; + *p = '\0'; + printf("%-5s ", flagstr); + } else { +- if (flags & F_RIB_INTERNAL) ++ if (flags & F_PREF_INTERNAL) + printf("internal"); + else + printf("external"); +- if (flags & F_RIB_ELIGIBLE) ++ if (flags & F_PREF_STALE) ++ printf(", stale"); ++ if (flags & F_PREF_ELIGIBLE) + printf(", valid"); +- if (flags & F_RIB_ACTIVE) ++ if (flags & F_PREF_ACTIVE) + printf(", best"); +- if (flags & F_RIB_ANNOUNCE) ++ if (flags & F_PREF_ANNOUNCE) + printf(", announced"); + } + } +@@ -1077,27 +1231,14 @@ int + show_rib_summary_msg(struct imsg *imsg) + { + struct ctl_show_rib rib; +- char *aspath; + u_char *asdata; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_RIB: + memcpy(&rib, imsg->data, sizeof(rib)); +- +- print_prefix(&rib.prefix, rib.prefixlen, rib.flags); +- printf("%-15s ", log_addr(&rib.exit_nexthop)); +- +- printf(" %5u %5u ", rib.local_pref, rib.med); +- + asdata = imsg->data; + asdata += sizeof(struct ctl_show_rib); +- if (aspath_asprint(&aspath, asdata, rib.aspath_len) == -1) +- err(1, NULL); +- if (strlen(aspath) > 0) +- printf("%s ", aspath); +- free(aspath); +- +- printf("%s\n", print_origin(rib.origin, 1)); ++ show_rib_brief(&rib, asdata); + break; + case IMSG_CTL_END: + return (1); +@@ -1112,108 +1253,21 @@ int + show_rib_detail_msg(struct imsg *imsg, int nodescr) + { + struct ctl_show_rib rib; +- struct in_addr id; +- char *aspath, *s; +- u_char *data; +- u_int32_t as; +- u_int16_t ilen, alen, ioff; +- u_int8_t flags, type; +- time_t now; ++ u_char *asdata; ++ u_int16_t ilen; + + switch (imsg->hdr.type) { + case IMSG_CTL_SHOW_RIB: + memcpy(&rib, imsg->data, sizeof(rib)); +- +- printf("\nBGP routing table entry for %s/%u\n", +- log_addr(&rib.prefix), rib.prefixlen); +- +- data = imsg->data; +- data += sizeof(struct ctl_show_rib); +- if (aspath_asprint(&aspath, data, rib.aspath_len) == -1) +- err(1, NULL); +- if (strlen(aspath) > 0) +- printf(" %s\n", aspath); +- free(aspath); +- +- s = fmt_peer(rib.descr, &rib.remote_addr, -1, nodescr); +- printf(" Nexthop %s ", log_addr(&rib.exit_nexthop)); +- printf("(via %s) from %s (", log_addr(&rib.true_nexthop), s); +- free(s); +- id.s_addr = htonl(rib.remote_id); +- printf("%s)\n", inet_ntoa(id)); +- +- printf(" Origin %s, metric %u, localpref %u, ", +- print_origin(rib.origin, 0), rib.med, rib.local_pref); +- print_flags(rib.flags, 0); +- +- now = time(NULL); +- if (now > rib.lastchange) +- now -= rib.lastchange; +- else +- now = 0; +- +- printf("\n Last update: %s ago\n", +- fmt_timeframe_core(now)); ++ asdata = imsg->data; ++ asdata += sizeof(struct ctl_show_rib); ++ show_rib_detail(&rib, asdata, nodescr); + break; + case IMSG_CTL_SHOW_RIB_ATTR: + ilen = imsg->hdr.len - IMSG_HEADER_SIZE; + if (ilen < 3) + errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- data = imsg->data; +- flags = data[0]; +- type = data[1]; +- +- /* get the attribute length */ +- if (flags & ATTR_EXTLEN) { +- if (ilen < 4) +- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- memcpy(&alen, data+2, sizeof(u_int16_t)); +- alen = ntohs(alen); +- data += 4; +- ilen -= 4; +- } else { +- alen = data[2]; +- data += 3; +- ilen -= 3; +- } +- /* bad imsg len how can that happen!? */ +- if (alen != ilen) +- errx(1, "bad IMSG_CTL_SHOW_RIB_ATTR received"); +- +- switch (type) { +- case ATTR_COMMUNITIES: +- printf(" Communities: "); +- show_community(data, alen); +- printf("\n"); +- break; +- case ATTR_AGGREGATOR: +- memcpy(&as, data, sizeof(as)); +- memcpy(&id, data + sizeof(as), sizeof(id)); +- printf(" Aggregator: %s [%s]\n", +- log_as(htonl(as)), inet_ntoa(id)); +- break; +- case ATTR_ORIGINATOR_ID: +- memcpy(&id, data, sizeof(id)); +- printf(" Originator Id: %s\n", inet_ntoa(id)); +- break; +- case ATTR_CLUSTER_LIST: +- printf(" Cluster ID List:"); +- for (ioff = 0; ioff + sizeof(id) <= ilen; +- ioff += sizeof(id)) { +- memcpy(&id, data + ioff, sizeof(id)); +- printf(" %s", inet_ntoa(id)); +- } +- printf("\n"); +- break; +- case ATTR_EXT_COMMUNITIES: +- printf(" Ext. communities: "); +- show_ext_community(data, alen); +- printf("\n"); +- break; +- default: +- /* ignore unknown attributes */ +- break; +- } ++ show_attr(imsg->data, ilen); + break; + case IMSG_CTL_END: + printf("\n"); +@@ -1225,67 +1279,128 @@ show_rib_detail_msg(struct imsg *imsg, i + return (0); + } + +-char * +-fmt_mem(int64_t num) ++void ++show_rib_brief(struct ctl_show_rib *r, u_char *asdata) + { +- static char buf[16]; ++ char *aspath; + +- if (fmt_scaled(num, buf) == -1) +- snprintf(buf, sizeof(buf), "%lldB", (long long)num); ++ print_prefix(&r->prefix, r->prefixlen, r->flags); ++ printf(" %-15s ", log_addr(&r->exit_nexthop)); ++ printf(" %5u %5u ", r->local_pref, r->med); + +- return (buf); ++ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) ++ err(1, NULL); ++ if (strlen(aspath) > 0) ++ printf("%s ", aspath); ++ free(aspath); ++ ++ printf("%s\n", print_origin(r->origin, 1)); + } + +-int +-show_rib_memory_msg(struct imsg *imsg) ++void ++show_rib_detail(struct ctl_show_rib *r, u_char *asdata, int nodescr) + { +- struct rde_memstats stats; ++ struct in_addr id; ++ char *aspath, *s; ++ time_t now; + +- switch (imsg->hdr.type) { +- case IMSG_CTL_SHOW_RIB_MEM: +- memcpy(&stats, imsg->data, sizeof(stats)); +- printf("RDE memory statistics\n"); +- printf("%10lld IPv4 network entries using %s of memory\n", +- (long long)stats.pt4_cnt, fmt_mem(stats.pt4_cnt * +- sizeof(struct pt_entry4))); +- if (stats.pt6_cnt != 0) +- printf("%10lld IPv6 network entries using " +- "%s of memory\n", (long long)stats.pt6_cnt, +- fmt_mem(stats.pt6_cnt * sizeof(struct pt_entry6))); +- printf("%10lld rib entries using %s of memory\n", +- (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * +- sizeof(struct rib_entry))); +- printf("%10lld prefix entries using %s of memory\n", +- (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * +- sizeof(struct prefix))); +- printf("%10lld BGP path attribute entries using %s of memory\n", +- (long long)stats.path_cnt, fmt_mem(stats.path_cnt * +- sizeof(struct rde_aspath))); +- printf("%10lld BGP AS-PATH attribute entries using " +- "%s of memory,\n\t and holding %lld references\n", +- (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), +- (long long)stats.aspath_refs); +- printf("%10lld BGP attributes entries using %s of memory\n", +- (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * +- sizeof(struct attr))); +- printf("\t and holding %lld references\n", +- (long long)stats.attr_refs); +- printf("%10lld BGP attributes using %s of memory\n", +- (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); +- printf("RIB using %s of memory\n", fmt_mem( +- stats.pt4_cnt * sizeof(struct pt_entry4) + +- stats.pt6_cnt * sizeof(struct pt_entry6) + +- stats.prefix_cnt * sizeof(struct prefix) + +- stats.rib_cnt * sizeof(struct rib_entry) + +- stats.path_cnt * sizeof(struct rde_aspath) + +- stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + +- stats.attr_data)); ++ printf("\nBGP routing table entry for %s/%u\n", ++ log_addr(&r->prefix), r->prefixlen); ++ ++ if (aspath_asprint(&aspath, asdata, r->aspath_len) == -1) ++ err(1, NULL); ++ if (strlen(aspath) > 0) ++ printf(" %s\n", aspath); ++ free(aspath); ++ ++ s = fmt_peer(r->descr, &r->remote_addr, -1, nodescr); ++ printf(" Nexthop %s ", log_addr(&r->exit_nexthop)); ++ printf("(via %s) from %s (", log_addr(&r->true_nexthop), s); ++ free(s); ++ id.s_addr = htonl(r->remote_id); ++ printf("%s)\n", inet_ntoa(id)); ++ ++ printf(" Origin %s, metric %u, localpref %u, weight %u, ", ++ print_origin(r->origin, 0), r->med, r->local_pref, r->weight); ++ print_flags(r->flags, 0); ++ ++ now = time(NULL); ++ if (now > r->lastchange) ++ now -= r->lastchange; ++ else ++ now = 0; ++ ++ printf("\n Last update: %s ago\n", fmt_timeframe_core(now)); ++} ++ ++void ++show_attr(void *b, u_int16_t len) ++{ ++ char *data = b; ++ struct in_addr id; ++ u_int32_t as; ++ u_int16_t alen, ioff; ++ u_int8_t flags, type; ++ ++ data = b; ++ 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"); ++ ++ switch (type) { ++ case ATTR_COMMUNITIES: ++ printf(" Communities: "); ++ show_community(data, alen); ++ printf("\n"); ++ break; ++ case ATTR_AGGREGATOR: ++ memcpy(&as, data, sizeof(as)); ++ memcpy(&id, data + sizeof(as), sizeof(id)); ++ printf(" Aggregator: %s [%s]\n", ++ log_as(ntohl(as)), inet_ntoa(id)); ++ break; ++ case ATTR_ORIGINATOR_ID: ++ memcpy(&id, data, sizeof(id)); ++ printf(" Originator Id: %s\n", inet_ntoa(id)); ++ break; ++ case ATTR_CLUSTER_LIST: ++ printf(" Cluster ID List:"); ++ for (ioff = 0; ioff + sizeof(id) <= alen; ++ ioff += sizeof(id)) { ++ memcpy(&id, data + ioff, sizeof(id)); ++ printf(" %s", inet_ntoa(id)); ++ } ++ printf("\n"); ++ break; ++ case ATTR_EXT_COMMUNITIES: ++ printf(" Ext. communities: "); ++ show_ext_community(data, alen); ++ printf("\n"); + break; + default: ++ /* ignore unknown attributes */ + break; + } +- +- return (1); + } + + void +@@ -1328,30 +1443,6 @@ show_community(u_char *data, u_int16_t l + } + } + +-const char * +-get_ext_subtype(u_int8_t type) +-{ +- static char etype[6]; +- +- switch (type) { +- case EXT_COMMUNITY_ROUTE_TGT: +- return "rt"; /* route target */ +- case EXT_CUMMUNITY_ROUTE_ORIG: +- return "soo"; /* source of origin */ +- case EXT_COMMUNITY_OSPF_DOM_ID: +- return "odi"; /* ospf domain id */ +- case EXT_COMMUNITY_OSPF_RTR_TYPE: +- return "ort"; /* ospf route type */ +- case EXT_COMMUNITY_OSPF_RTR_ID: +- return "ori"; /* ospf router id */ +- case EXT_COMMUNITY_BGP_COLLECT: +- return "bdc"; /* bgp data collection */ +- default: +- snprintf(etype, sizeof(etype), "[%i]", (int)type); +- return etype; +- } +-} +- + void + show_ext_community(u_char *data, u_int16_t len) + { +@@ -1372,34 +1463,101 @@ show_ext_community(u_char *data, u_int16 + case EXT_COMMUNITY_TWO_AS: + memcpy(&as2, data + i + 2, sizeof(as2)); + memcpy(&u32, data + i + 4, sizeof(u32)); +- printf("%s %hu:%u", get_ext_subtype(subtype), as2, u32); ++ printf("%s %s:%u", log_ext_subtype(subtype), ++ log_as(ntohs(as2)), ntohl(u32)); + break; + case EXT_COMMUNITY_IPV4: + memcpy(&ip, data + i + 2, sizeof(ip)); + memcpy(&u16, data + i + 6, sizeof(u16)); +- printf("%s %s:%hu", get_ext_subtype(subtype), +- inet_ntoa(ip), u16); ++ printf("%s %s:%hu", log_ext_subtype(subtype), ++ inet_ntoa(ip), ntohs(u16)); + break; + case EXT_COMMUNITY_FOUR_AS: + memcpy(&as4, data + i + 2, sizeof(as4)); + memcpy(&u16, data + i + 6, sizeof(u16)); +- printf("%s %s:%hu", get_ext_subtype(subtype), +- log_as(as4), u16); ++ printf("%s %s:%hu", log_ext_subtype(subtype), ++ log_as(ntohl(as4)), ntohs(u16)); + break; + case EXT_COMMUNITY_OPAQUE: + memcpy(&ext, data + i, sizeof(ext)); + ext = betoh64(ext) & 0xffffffffffffLL; +- printf("%s 0x%llx", get_ext_subtype(subtype), ext); ++ printf("%s 0x%" PRIx64, log_ext_subtype(subtype), ext); + break; + default: + memcpy(&ext, data + i, sizeof(ext)); +- printf("0x%llx", betoh64(ext)); ++ printf("0x%" PRIx64, betoh64(ext)); + } + if (i + 8 < len) + printf(", "); + } + } + ++char * ++fmt_mem(int64_t num) ++{ ++ static char buf[16]; ++ ++ if (fmt_scaled(num, buf) == -1) ++ snprintf(buf, sizeof(buf), "%lldB", (long long)num); ++ ++ return (buf); ++} ++ ++size_t pt_sizes[AID_MAX] = AID_PTSIZE; ++ ++int ++show_rib_memory_msg(struct imsg *imsg) ++{ ++ struct rde_memstats stats; ++ size_t pts = 0; ++ int i; ++ ++ switch (imsg->hdr.type) { ++ case IMSG_CTL_SHOW_RIB_MEM: ++ memcpy(&stats, imsg->data, sizeof(stats)); ++ printf("RDE memory statistics\n"); ++ for (i = 0; i < AID_MAX; i++) { ++ if (stats.pt_cnt[i] == 0) ++ continue; ++ pts += stats.pt_cnt[i] * pt_sizes[i]; ++ printf("%10lld %s network entries using %s of memory\n", ++ (long long)stats.pt_cnt[i], aid_vals[i].name, ++ fmt_mem(stats.pt_cnt[i] * pt_sizes[i])); ++ } ++ printf("%10lld rib entries using %s of memory\n", ++ (long long)stats.rib_cnt, fmt_mem(stats.rib_cnt * ++ sizeof(struct rib_entry))); ++ printf("%10lld prefix entries using %s of memory\n", ++ (long long)stats.prefix_cnt, fmt_mem(stats.prefix_cnt * ++ sizeof(struct prefix))); ++ printf("%10lld BGP path attribute entries using %s of memory\n", ++ (long long)stats.path_cnt, fmt_mem(stats.path_cnt * ++ sizeof(struct rde_aspath))); ++ printf("%10lld BGP AS-PATH attribute entries using " ++ "%s of memory,\n\t and holding %lld references\n", ++ (long long)stats.aspath_cnt, fmt_mem(stats.aspath_size), ++ (long long)stats.aspath_refs); ++ printf("%10lld BGP attributes entries using %s of memory\n", ++ (long long)stats.attr_cnt, fmt_mem(stats.attr_cnt * ++ sizeof(struct attr))); ++ printf("\t and holding %lld references\n", ++ (long long)stats.attr_refs); ++ printf("%10lld BGP attributes using %s of memory\n", ++ (long long)stats.attr_dcnt, fmt_mem(stats.attr_data)); ++ printf("RIB using %s of memory\n", fmt_mem(pts + ++ stats.prefix_cnt * sizeof(struct prefix) + ++ stats.rib_cnt * sizeof(struct rib_entry) + ++ stats.path_cnt * sizeof(struct rde_aspath) + ++ stats.aspath_size + stats.attr_cnt * sizeof(struct attr) + ++ stats.attr_data)); ++ break; ++ default: ++ break; ++ } ++ ++ return (1); ++} ++ + void + send_filterset(struct imsgbuf *i, struct filter_set_head *set) + { +@@ -1469,6 +1627,183 @@ show_result(struct imsg *imsg) + return (1); + } + ++void ++show_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) ++{ ++ struct ctl_show_rib ctl; ++ struct ctl_show_rib_request *req = arg; ++ struct mrt_rib_entry *mre; ++ u_int16_t i, j; ++ ++ for (i = 0; i < mr->nentries; i++) { ++ mre = &mr->entries[i]; ++ bzero(&ctl, sizeof(ctl)); ++ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); ++ ctl.prefixlen = mr->prefixlen; ++ ctl.lastchange = mre->originated; ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); ++ ctl.origin = mre->origin; ++ ctl.local_pref = mre->local_pref; ++ ctl.med = mre->med; ++ /* weight is not part of the mrt dump so it can't be set */ ++ ctl.aspath_len = mre->aspath_len; ++ ++ if (mre->peer_idx < mp->npeers) { ++ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, ++ &ctl.remote_addr); ++ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; ++ } ++ ++ /* filter by neighbor */ ++ if (req->neighbor.addr.aid != AID_UNSPEC && ++ memcmp(&req->neighbor.addr, &ctl.remote_addr, ++ sizeof(ctl.remote_addr)) != 0) ++ continue; ++ /* filter by AF */ ++ if (req->aid && req->aid != ctl.prefix.aid) ++ return; ++ /* filter by prefix */ ++ if (req->prefix.aid != AID_UNSPEC) { ++ if (!prefix_compare(&req->prefix, &ctl.prefix, ++ req->prefixlen)) { ++ if (req->flags & F_LONGER) { ++ if (req->prefixlen > ctl.prefixlen) ++ return; ++ } else if (req->prefixlen != ctl.prefixlen) ++ return; ++ } else ++ return; ++ } ++ /* filter by AS */ ++ if (req->as.type != AS_NONE && ++ !aspath_match(mre->aspath, mre->aspath_len, ++ req->as.type, req->as.as)) ++ continue; ++ ++ if (req->flags & F_CTL_DETAIL) { ++ show_rib_detail(&ctl, mre->aspath, 1); ++ for (j = 0; j < mre->nattrs; j++) ++ show_attr(mre->attrs[j].attr, ++ mre->attrs[j].attr_len); ++ } else ++ show_rib_brief(&ctl, mre->aspath); ++ } ++} ++ ++void ++network_mrt_dump(struct mrt_rib *mr, struct mrt_peer *mp, void *arg) ++{ ++ struct ctl_show_rib ctl; ++ struct network_config net; ++ struct ctl_show_rib_request *req = arg; ++ struct mrt_rib_entry *mre; ++ struct ibuf *msg; ++ u_int16_t i, j; ++ ++ for (i = 0; i < mr->nentries; i++) { ++ mre = &mr->entries[i]; ++ bzero(&ctl, sizeof(ctl)); ++ mrt_to_bgpd_addr(&mr->prefix, &ctl.prefix); ++ ctl.prefixlen = mr->prefixlen; ++ ctl.lastchange = mre->originated; ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.true_nexthop); ++ mrt_to_bgpd_addr(&mre->nexthop, &ctl.exit_nexthop); ++ ctl.origin = mre->origin; ++ ctl.local_pref = mre->local_pref; ++ ctl.med = mre->med; ++ ctl.aspath_len = mre->aspath_len; ++ ++ if (mre->peer_idx < mp->npeers) { ++ mrt_to_bgpd_addr(&mp->peers[mre->peer_idx].addr, ++ &ctl.remote_addr); ++ ctl.remote_id = mp->peers[mre->peer_idx].bgp_id; ++ } ++ ++ /* filter by neighbor */ ++ if (req->neighbor.addr.aid != AID_UNSPEC && ++ memcmp(&req->neighbor.addr, &ctl.remote_addr, ++ sizeof(ctl.remote_addr)) != 0) ++ continue; ++ /* filter by AF */ ++ if (req->aid && req->aid != ctl.prefix.aid) ++ return; ++ /* filter by prefix */ ++ if (req->prefix.aid != AID_UNSPEC) { ++ if (!prefix_compare(&req->prefix, &ctl.prefix, ++ req->prefixlen)) { ++ if (req->flags & F_LONGER) { ++ if (req->prefixlen > ctl.prefixlen) ++ return; ++ } else if (req->prefixlen != ctl.prefixlen) ++ return; ++ } else ++ return; ++ } ++ /* filter by AS */ ++ if (req->as.type != AS_NONE && ++ !aspath_match(mre->aspath, mre->aspath_len, ++ req->as.type, req->as.as)) ++ continue; ++ ++ bzero(&net, sizeof(net)); ++ memcpy(&net.prefix, &ctl.prefix, sizeof(net.prefix)); ++ net.prefixlen = ctl.prefixlen; ++ net.type = NETWORK_MRTCLONE; ++ /* XXX rtableid */ ++ ++ imsg_compose(ibuf, IMSG_NETWORK_ADD, 0, 0, -1, ++ &net, sizeof(net)); ++ if ((msg = imsg_create(ibuf, IMSG_NETWORK_ASPATH, ++ 0, 0, sizeof(ctl) + mre->aspath_len)) == NULL) ++ errx(1, "imsg_create failure"); ++ if (imsg_add(msg, &ctl, sizeof(ctl)) == -1 || ++ imsg_add(msg, mre->aspath, mre->aspath_len) == -1) ++ errx(1, "imsg_add failure"); ++ imsg_close(ibuf, msg); ++ for (j = 0; j < mre->nattrs; j++) ++ imsg_compose(ibuf, IMSG_NETWORK_ATTR, 0, 0, -1, ++ mre->attrs[j].attr, mre->attrs[j].attr_len); ++ imsg_compose(ibuf, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0); ++ ++ while (ibuf->w.queued) { ++ if (msgbuf_write(&ibuf->w) < 0) ++ err(1, "write error"); ++ } ++ } ++} ++ ++void ++show_mrt_state(struct mrt_bgp_state *ms, void *arg) ++{ ++ printf("show_mrt_state\n"); ++} ++ ++void ++show_mrt_msg(struct mrt_bgp_msg *mm, void *arg) ++{ ++ printf("show_mrt_msg\n"); ++} ++ ++void ++mrt_to_bgpd_addr(union mrt_addr *ma, struct bgpd_addr *ba) ++{ ++ switch (ma->sa.sa_family) { ++ case AF_INET: ++ case AF_INET6: ++ sa2addr(&ma->sa, ba); ++ break; ++ case AF_VPNv4: ++ bzero(ba, sizeof(*ba)); ++ ba->aid = AID_VPN_IPv4; ++ ba->vpn4.rd = ma->svpn4.sv_rd; ++ ba->vpn4.addr.s_addr = ma->svpn4.sv_addr.s_addr; ++ memcpy(ba->vpn4.labelstack, ma->svpn4.sv_label, ++ sizeof(ba->vpn4.labelstack)); ++ break; ++ } ++} ++ + /* following functions are necessary for imsg framework */ + void + log_warnx(const char *emsg, ...) +@@ -1495,3 +1830,9 @@ fatal(const char *emsg) + { + err(1, emsg); + } ++ ++void ++fatalx(const char *emsg) ++{ ++ errx(1, emsg); ++} |