Please provide a properly formatted diff.

On Thu, May 14, 2020 at 07:16:31AM +0100, Richard Chivers wrote:
> Hi,
> 
> I have done the work to implement ospfctl json support, but as
> discussed i will provide it in two diffs.
> 
> This first one externalises the output aspect of ospfctl and there are
> some things like tail that are not needed specifically for straight
> standard output, but are required for json support.
> 
> I also wasn't sure what to do with Copyright messages at the top of
> files, any advice appreciated.
> 
> In terms of outstanding issues, not sure how big to make the array in
> print_baudrate, I guessed 32 would cover things?
> 
> Many of the functions that return output fragments are called print,
> when they actually return strings. in bgpctl many of these seem to
> have been renamed to fmt_. I have left these as is for now to again
> reduce the size of the change.
> 
> 
> diff --git a/usr.sbin/ospfctl/Makefile b/usr.sbin/ospfctl/Makefile
> index cfd5e4ccb71..6560e0d5f89 100644
> --- a/usr.sbin/ospfctl/Makefile
> +++ b/usr.sbin/ospfctl/Makefile
> @@ -3,7 +3,7 @@
> .PATH: ${.CURDIR}/../ospfd
> PROG= ospfctl
> -SRCS= logmsg.c ospfctl.c parser.c
> +SRCS= logmsg.c ospfctl.c output.c parser.c
> CFLAGS+= -Wall
> CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
> CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
> diff --git a/usr.sbin/ospfctl/ospfctl.c b/usr.sbin/ospfctl/ospfctl.c
> index 2d7189793d8..e04124853a1 100644
> --- a/usr.sbin/ospfctl/ospfctl.c
> +++ b/usr.sbin/ospfctl/ospfctl.c
> @@ -35,42 +35,16 @@
> #include "ospf.h"
> #include "ospfd.h"
> +#include "ospfctl.h"
> #include "ospfe.h"
> #include "parser.h"
> __dead void usage(void);
> -int show_summary_msg(struct imsg *);
> -uint64_t get_ifms_type(uint8_t);
> -int show_interface_msg(struct imsg *);
> -int show_interface_detail_msg(struct imsg *);
> -const char *print_link(int);
> -const char *fmt_timeframe(time_t t);
> -const char *fmt_timeframe_core(time_t t);
> -const char *log_id(u_int32_t );
> -const char *log_adv_rtr(u_int32_t);
> -void show_database_head(struct in_addr, char *, u_int8_t);
> -int show_database_msg(struct imsg *);
> -char *print_ls_type(u_int8_t);
> -void show_db_hdr_msg_detail(struct lsa_hdr *);
> -char *print_rtr_link_type(u_int8_t);
> -const char *print_ospf_flags(u_int8_t);
> -int show_db_msg_detail(struct imsg *imsg);
> -int show_nbr_msg(struct imsg *);
> -const char *print_ospf_options(u_int8_t);
> -int show_nbr_detail_msg(struct imsg *);
> -int show_rib_msg(struct imsg *);
> -void show_rib_head(struct in_addr, u_int8_t, u_int8_t);
> -const char *print_ospf_rtr_flags(u_int8_t);
> -int show_rib_detail_msg(struct imsg *);
> -void show_fib_head(void);
> -int show_fib_msg(struct imsg *);
> -void show_interface_head(void);
> -const char * get_media_descr(uint64_t);
> -const char * get_linkstate(uint8_t, int);
> -void print_baudrate(u_int64_t);
> -int show_fib_interface_msg(struct imsg *);
> +
> +int show(struct imsg *imsg, struct parse_result *res);
> struct imsgbuf *ibuf;
> +const struct output *output = &show_output;
> __dead void
> usage(void)
> @@ -145,9 +119,6 @@ main(int argc, char *argv[])
> imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
> break;
> case SHOW_IFACE:
> - printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n",
> - "Interface", "Address", "State", "HelloTimer", "Linkstate",
> - "Uptime", "nc", "ac");
> /*FALLTHROUGH*/
> case SHOW_IFACE_DTAIL:
> if (*res->ifname) {
> @@ -159,8 +130,6 @@ main(int argc, char *argv[])
> &ifidx, sizeof(ifidx));
> break;
> case SHOW_NBR:
> - printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
> - "State", "DeadTime", "Address", "Iface","Uptime");
> /*FALLTHROUGH*/
> case SHOW_NBR_DTAIL:
> imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
> @@ -194,8 +163,6 @@ main(int argc, char *argv[])
> imsg_compose(ibuf, IMSG_CTL_SHOW_DB_OPAQ, 0, 0, -1, NULL, 0);
> break;
> case SHOW_RIB:
> - printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
> - "Nexthop", "Path Type", "Type", "Cost", "Uptime");
> /*FALLTHROUGH*/
> case SHOW_RIB_DTAIL:
> imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
> @@ -207,7 +174,6 @@ main(int argc, char *argv[])
> else
> imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
> &res->addr, sizeof(res->addr));
> - show_fib_head();
> break;
> case SHOW_FIB_IFACE:
> if (*res->ifname)
> @@ -215,7 +181,6 @@ main(int argc, char *argv[])
> res->ifname, sizeof(res->ifname));
> else
> imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
> - show_interface_head();
> break;
> case FIB:
> errx(1, "fib couple|decouple");
> @@ -255,72 +220,30 @@ main(int argc, char *argv[])
> if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
> err(1, "write error");
> - while (!done) {
> - if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
> - errx(1, "imsg_read error");
> - if (n == 0)
> - errx(1, "pipe closed");
> + // Don't attempt output for certain commands such as log verbose
> + if(!done){
> + output->head(res);
> while (!done) {
> - if ((n = imsg_get(ibuf, &imsg)) == -1)
> - errx(1, "imsg_get error");
> + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
> + errx(1, "imsg_read error");
> if (n == 0)
> - break;
> - switch (res->action) {
> - case SHOW:
> - case SHOW_SUM:
> - done = show_summary_msg(&imsg);
> - break;
> - case SHOW_IFACE:
> - done = show_interface_msg(&imsg);
> - break;
> - case SHOW_IFACE_DTAIL:
> - done = show_interface_detail_msg(&imsg);
> - break;
> - case SHOW_NBR:
> - done = show_nbr_msg(&imsg);
> - break;
> - case SHOW_NBR_DTAIL:
> - done = show_nbr_detail_msg(&imsg);
> - break;
> - case SHOW_DB:
> - case SHOW_DBBYAREA:
> - case SHOW_DBSELF:
> - done = show_database_msg(&imsg);
> - break;
> - case SHOW_DBEXT:
> - case SHOW_DBNET:
> - case SHOW_DBRTR:
> - case SHOW_DBSUM:
> - case SHOW_DBASBR:
> - case SHOW_DBOPAQ:
> - done = show_db_msg_detail(&imsg);
> - break;
> - case SHOW_RIB:
> - done = show_rib_msg(&imsg);
> - break;
> - case SHOW_RIB_DTAIL:
> - done = show_rib_detail_msg(&imsg);
> - break;
> - case SHOW_FIB:
> - done = show_fib_msg(&imsg);
> - break;
> - case SHOW_FIB_IFACE:
> - done = show_fib_interface_msg(&imsg);
> - break;
> - case NONE:
> - case FIB:
> - case FIB_COUPLE:
> - case FIB_DECOUPLE:
> - case FIB_RELOAD:
> - case LOG_VERBOSE:
> - case LOG_BRIEF:
> - case RELOAD:
> - break;
> + errx(1, "pipe closed");
> +
> + while (!done) {
> + if ((n = imsg_get(ibuf, &imsg)) == -1)
> + errx(1, "imsg_get error");
> + if (n == 0)
> + break;
> +
> + done = show(&imsg, res);
> + imsg_free(&imsg);
> }
> - imsg_free(&imsg);
> }
> +
> + output->tail();
> }
> +
> close(ctl_sock);
> free(ibuf);
> @@ -328,45 +251,94 @@ main(int argc, char *argv[])
> }
> int
> -show_summary_msg(struct imsg *imsg)
> +show(struct imsg *imsg, struct parse_result *res)
> {
> struct ctl_sum *sum;
> struct ctl_sum_area *sumarea;
> + struct ctl_iface *ctliface;
> + struct ctl_nbr *nbr;
> + struct ctl_rt *rt;
> + struct kroute *k;
> + struct kif *kif;
> +
> + static struct in_addr area_id;
> + struct area *area;
> + static u_int8_t lasttype;
> + static char ifname[IF_NAMESIZE];
> + struct iface *iface;
> + struct lsa *lsa;
> + struct lsa_hdr *lsa_hdr;
> switch (imsg->hdr.type) {
> case IMSG_CTL_SHOW_SUM:
> sum = imsg->data;
> - printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
> - printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
> - printf("RFC1583 compatibility flag is ");
> - if (sum->rfc1583compat)
> - printf("enabled\n");
> - else
> - printf("disabled\n");
> -
> - printf("SPF delay is %d msec(s), hold time between two SPFs "
> - "is %d msec(s)\n", sum->spf_delay, sum->spf_hold_time);
> - printf("Number of external LSA(s) %d (Checksum sum 0x%x)\n",
> - sum->num_ext_lsa, sum->ext_lsa_cksum);
> - printf("Number of areas attached to this router: %d\n",
> - sum->num_area);
> + output->summary(sum);
> break;
> case IMSG_CTL_SHOW_SUM_AREA:
> sumarea = imsg->data;
> - printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
> - printf(" Number of interfaces in this area: %d\n",
> - sumarea->num_iface);
> - printf(" Number of fully adjacent neighbors in this "
> - "area: %d\n", sumarea->num_adj_nbr);
> - printf(" SPF algorithm executed %d time(s)\n",
> - sumarea->num_spf_calc);
> - printf(" Number LSA(s) %d (Checksum sum 0x%x)\n",
> - sumarea->num_lsa, sumarea->lsa_cksum);
> + output->summary_area(sumarea);
> + break;
> + case IMSG_CTL_SHOW_INTERFACE:
> + ctliface = imsg->data;
> + if(res->action == SHOW_IFACE_DTAIL)
> + output->interface(ctliface, 1);
> + else
> + output->interface(ctliface, 0);
> + break;
> + case IMSG_CTL_SHOW_NBR:
> + nbr = imsg->data;
> + if(res->action == SHOW_NBR_DTAIL)
> + output->neighbor(nbr, 1);
> + else
> + output->neighbor(nbr, 0);
> + break;
> + case IMSG_CTL_SHOW_RIB:
> + rt = imsg->data;
> + if(res->action == SHOW_RIB_DTAIL)
> + output->rib(rt, 1);
> + else
> + output->rib(rt, 0);
> + break;
> + case IMSG_CTL_KROUTE:
> + if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
> + errx(1, "wrong imsg len");
> + k = imsg->data;
> + output->fib(k);
> + break;
> + case IMSG_CTL_IFINFO:
> + kif = imsg->data;
> + output->fib_interface(kif);
> + break;
> + case IMSG_CTL_SHOW_DB_EXT:
> + case IMSG_CTL_SHOW_DB_NET:
> + case IMSG_CTL_SHOW_DB_RTR:
> + case IMSG_CTL_SHOW_DB_SUM:
> + case IMSG_CTL_SHOW_DB_ASBR:
> + case IMSG_CTL_SHOW_DB_OPAQ:
> + lsa = imsg->data;
> + output->db(lsa, area_id, lasttype, ifname);
> + lasttype = lsa->hdr.type;
> + break;
> + case IMSG_CTL_SHOW_DATABASE:
> + case IMSG_CTL_SHOW_DB_SELF:
> + lsa_hdr = imsg->data;
> + output->db_simple(lsa_hdr, area_id, lasttype, ifname);
> + lasttype = lsa_hdr->type;
> + break;
> + case IMSG_CTL_AREA:
> + area = imsg->data;
> + area_id = area->id;
> + lasttype = 0;
> + break;
> + case IMSG_CTL_IFACE:
> + iface = imsg->data;
> + strlcpy(ifname, iface->name, sizeof(ifname));
> + lasttype = 0;
> break;
> case IMSG_CTL_END:
> - printf("\n");
> return (1);
> default:
> + warnx("unknown imsg %d received", imsg->hdr.type);
> break;
> }
> @@ -390,118 +362,6 @@ get_ifms_type(uint8_t if_type)
> }
> }
> -int
> -show_interface_msg(struct imsg *imsg)
> -{
> - struct ctl_iface *iface;
> - char *netid;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_INTERFACE:
> - iface = imsg->data;
> -
> - if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
> - mask2prefixlen(iface->mask.s_addr)) == -1)
> - err(1, NULL);
> - printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n",
> - iface->name, netid, if_state_name(iface->state),
> - iface->hello_timer.tv_sec < 0 ? "-" :
> - fmt_timeframe_core(iface->hello_timer.tv_sec),
> - get_linkstate(iface->if_type, iface->linkstate),
> - fmt_timeframe_core(iface->uptime),
> - iface->nbr_cnt, iface->adj_cnt);
> - free(netid);
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -int
> -show_interface_detail_msg(struct imsg *imsg)
> -{
> - struct ctl_iface *iface;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_INTERFACE:
> - iface = imsg->data;
> - printf("\n");
> - printf("Interface %s, line protocol is %s\n",
> - iface->name, print_link(iface->flags));
> - printf(" Internet address %s/%d, ",
> - inet_ntoa(iface->addr),
> - mask2prefixlen(iface->mask.s_addr));
> - printf("Area %s\n", inet_ntoa(iface->area));
> - printf(" Linkstate %s,",
> - get_linkstate(iface->if_type, iface->linkstate));
> - printf(" mtu %d\n", iface->mtu);
> - printf(" Router ID %s, network type %s, cost: %d\n",
> - inet_ntoa(iface->rtr_id),
> - if_type_name(iface->type), iface->metric);
> - printf(" Transmit delay is %d sec(s), state %s, priority %d\n",
> - iface->transmit_delay, if_state_name(iface->state),
> - iface->priority);
> - printf(" Designated Router (ID) %s, ",
> - inet_ntoa(iface->dr_id));
> - printf("interface address %s\n", inet_ntoa(iface->dr_addr));
> - printf(" Backup Designated Router (ID) %s, ",
> - inet_ntoa(iface->bdr_id));
> - printf("interface address %s\n", inet_ntoa(iface->bdr_addr));
> - if (iface->dead_interval == FAST_RTR_DEAD_TIME) {
> - printf(" Timer intervals configured, "
> - "hello %d msec, dead %d, wait %d, retransmit %d\n",
> - iface->fast_hello_interval, iface->dead_interval,
> - iface->dead_interval, iface->rxmt_interval);
> -
> - } else {
> - printf(" Timer intervals configured, "
> - "hello %d, dead %d, wait %d, retransmit %d\n",
> - iface->hello_interval, iface->dead_interval,
> - iface->dead_interval, iface->rxmt_interval);
> - }
> - if (iface->passive)
> - printf(" Passive interface (No Hellos)\n");
> - else if (iface->hello_timer.tv_sec < 0)
> - printf(" Hello timer not running\n");
> - else
> - printf(" Hello timer due in %s+%ldmsec\n",
> - fmt_timeframe_core(iface->hello_timer.tv_sec),
> - iface->hello_timer.tv_usec / 1000);
> - printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime));
> - printf(" Neighbor count is %d, adjacent neighbor count is "
> - "%d\n", iface->nbr_cnt, iface->adj_cnt);
> - if (iface->auth_type > 0) {
> - switch (iface->auth_type) {
> - case AUTH_SIMPLE:
> - printf(" Simple password authentication "
> - "enabled\n");
> - break;
> - case AUTH_CRYPT:
> - printf(" Message digest authentication "
> - "enabled\n");
> - printf(" Primary key id is %d\n",
> - iface->auth_keyid);
> - break;
> - default:
> - break;
> - }
> - }
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> const char *
> print_link(int state)
> {
> @@ -514,15 +374,6 @@ print_link(int state)
> #define TF_BUFS 8
> #define TF_LEN 9
> -const char *
> -fmt_timeframe(time_t t)
> -{
> - if (t == 0)
> - return ("Never");
> - else
> - return (fmt_timeframe_core(time(NULL) - t));
> -}
> -
> const char *
> fmt_timeframe_core(time_t t)
> {
> @@ -598,108 +449,6 @@ mask2prefixlen(in_addr_t ina)
> return (33 - ffs(ntohl(ina)));
> }
> -void
> -show_database_head(struct in_addr aid, char *ifname, u_int8_t type)
> -{
> - char *header, *format;
> - int cleanup = 0;
> -
> - switch (type) {
> - case LSA_TYPE_ROUTER:
> - format = "Router Link States";
> - break;
> - case LSA_TYPE_NETWORK:
> - format = "Net Link States";
> - break;
> - case LSA_TYPE_SUM_NETWORK:
> - format = "Summary Net Link States";
> - break;
> - case LSA_TYPE_SUM_ROUTER:
> - format = "Summary Router Link States";
> - break;
> - case LSA_TYPE_EXTERNAL:
> - format = NULL;
> - if ((header = strdup("Type-5 AS External Link States")) == NULL)
> - err(1, NULL);
> - break;
> - case LSA_TYPE_LINK_OPAQ:
> - format = "Type-9 Link Local Opaque Link States";
> - break;
> - case LSA_TYPE_AREA_OPAQ:
> - format = "Type-10 Area Local Opaque Link States";
> - break;
> - case LSA_TYPE_AS_OPAQ:
> - format = NULL;
> - if ((header = strdup("Type-11 AS Wide Opaque Link States")) ==
> - NULL)
> - err(1, NULL);
> - break;
> - default:
> - if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
> - err(1, NULL);
> - cleanup = 1;
> - break;
> - }
> - if (type == LSA_TYPE_LINK_OPAQ) {
> - if (asprintf(&header, "%s (Area %s Interface %s)", format,
> - inet_ntoa(aid), ifname) == -1)
> - err(1, NULL);
> - } else if (type != LSA_TYPE_EXTERNAL && type != LSA_TYPE_AS_OPAQ)
> - if (asprintf(&header, "%s (Area %s)", format,
> - inet_ntoa(aid)) == -1)
> - err(1, NULL);
> -
> - printf("\n%-15s %s\n\n", "", header);
> - free(header);
> - if (cleanup)
> - free(format);
> -}
> -
> -int
> -show_database_msg(struct imsg *imsg)
> -{
> - static struct in_addr area_id;
> - static char ifname[IF_NAMESIZE];
> - static u_int8_t lasttype;
> - struct area *area;
> - struct iface *iface;
> - struct lsa_hdr *lsa;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_DATABASE:
> - case IMSG_CTL_SHOW_DB_SELF:
> - lsa = imsg->data;
> - if (lsa->type != lasttype) {
> - show_database_head(area_id, ifname, lsa->type);
> - printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
> - "Adv Router", "Age", "Seq#", "Checksum");
> - }
> - printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
> - log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
> - ntohs(lsa->age), ntohl(lsa->seq_num),
> - ntohs(lsa->ls_chksum));
> - lasttype = lsa->type;
> - break;
> - case IMSG_CTL_AREA:
> - area = imsg->data;
> - area_id = area->id;
> - lasttype = 0;
> - break;
> - case IMSG_CTL_IFACE:
> - iface = imsg->data;
> - strlcpy(ifname, iface->name, sizeof(ifname));
> - lasttype = 0;
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> char *
> print_ls_type(u_int8_t type)
> {
> @@ -725,47 +474,6 @@ print_ls_type(u_int8_t type)
> }
> }
> -void
> -show_db_hdr_msg_detail(struct lsa_hdr *lsa)
> -{
> - printf("LS age: %d\n", ntohs(lsa->age));
> - printf("Options: %s\n", print_ospf_options(lsa->opts));
> - printf("LS Type: %s\n", print_ls_type(lsa->type));
> -
> - switch (lsa->type) {
> - case LSA_TYPE_ROUTER:
> - printf("Link State ID: %s\n", log_id(lsa->ls_id));
> - break;
> - case LSA_TYPE_NETWORK:
> - printf("Link State ID: %s (address of Designated Router)\n",
> - log_id(lsa->ls_id));
> - break;
> - case LSA_TYPE_SUM_NETWORK:
> - printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
> - break;
> - case LSA_TYPE_SUM_ROUTER:
> - printf("Link State ID: %s (ASBR Router ID)\n",
> - log_id(lsa->ls_id));
> - break;
> - case LSA_TYPE_EXTERNAL:
> - printf("Link State ID: %s (External Network Number)\n",
> - log_id(lsa->ls_id));
> - break;
> - case LSA_TYPE_LINK_OPAQ:
> - case LSA_TYPE_AREA_OPAQ:
> - case LSA_TYPE_AS_OPAQ:
> - printf("Link State ID: %s Type %d ID %d\n", log_id(lsa->ls_id),
> - LSA_24_GETHI(ntohl(lsa->ls_id)),
> - LSA_24_GETLO(ntohl(lsa->ls_id)));
> - break;
> - }
> -
> - printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
> - printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
> - printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
> - printf("Length: %d\n", ntohs(lsa->len));
> -}
> -
> char *
> print_rtr_link_type(u_int8_t type)
> {
> @@ -795,190 +503,6 @@ print_ospf_flags(u_int8_t opts)
> return (optbuf);
> }
> -int
> -show_db_msg_detail(struct imsg *imsg)
> -{
> - static struct in_addr area_id;
> - static char ifname[IF_NAMESIZE];
> - static u_int8_t lasttype;
> - struct in_addr addr, data;
> - struct area *area;
> - struct iface *iface;
> - struct lsa *lsa;
> - struct lsa_rtr_link *rtr_link;
> - struct lsa_asext *asext;
> - u_int16_t i, nlinks, off;
> -
> - /* XXX sanity checks! */
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_DB_EXT:
> - lsa = imsg->data;
> - if (lsa->hdr.type != lasttype)
> - show_database_head(area_id, ifname, lsa->hdr.type);
> - show_db_hdr_msg_detail(&lsa->hdr);
> - addr.s_addr = lsa->data.asext.mask;
> - printf("Network Mask: %s\n", inet_ntoa(addr));
> -
> - asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
> -
> - printf(" Metric type: ");
> - if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
> - printf("2\n");
> - else
> - printf("1\n");
> - printf(" Metric: %d\n", ntohl(asext->metric)
> - & LSA_METRIC_MASK);
> - addr.s_addr = asext->fw_addr;
> - printf(" Forwarding Address: %s\n", inet_ntoa(addr));
> - printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag));
> -
> - lasttype = lsa->hdr.type;
> - break;
> - case IMSG_CTL_SHOW_DB_NET:
> - lsa = imsg->data;
> - if (lsa->hdr.type != lasttype)
> - show_database_head(area_id, ifname, lsa->hdr.type);
> - show_db_hdr_msg_detail(&lsa->hdr);
> - addr.s_addr = lsa->data.net.mask;
> - printf("Network Mask: %s\n", inet_ntoa(addr));
> -
> - nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
> - - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
> - off = sizeof(lsa->hdr) + sizeof(u_int32_t);
> - printf("Number of Routers: %d\n", nlinks);
> -
> - for (i = 0; i < nlinks; i++) {
> - addr.s_addr = lsa->data.net.att_rtr[i];
> - printf(" Attached Router: %s\n", inet_ntoa(addr));
> - }
> -
> - printf("\n");
> - lasttype = lsa->hdr.type;
> - break;
> - case IMSG_CTL_SHOW_DB_RTR:
> - lsa = imsg->data;
> - if (lsa->hdr.type != lasttype)
> - show_database_head(area_id, ifname, lsa->hdr.type);
> - show_db_hdr_msg_detail(&lsa->hdr);
> - printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
> - nlinks = ntohs(lsa->data.rtr.nlinks);
> - printf("Number of Links: %d\n\n", nlinks);
> -
> - off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
> -
> - for (i = 0; i < nlinks; i++) {
> - rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
> -
> - printf(" Link connected to: %s\n",
> - print_rtr_link_type(rtr_link->type));
> -
> - addr.s_addr = rtr_link->id;
> - data.s_addr = rtr_link->data;
> -
> - switch (rtr_link->type) {
> - case LINK_TYPE_POINTTOPOINT:
> - case LINK_TYPE_VIRTUAL:
> - printf(" Link ID (Neighbors Router ID):"
> - " %s\n", inet_ntoa(addr));
> - printf(" Link Data (Router Interface "
> - "address): %s\n", inet_ntoa(data));
> - break;
> - case LINK_TYPE_TRANSIT_NET:
> - printf(" Link ID (Designated Router "
> - "address): %s\n", inet_ntoa(addr));
> - printf(" Link Data (Router Interface "
> - "address): %s\n", inet_ntoa(data));
> - break;
> - case LINK_TYPE_STUB_NET:
> - printf(" Link ID (Network ID): %s\n",
> - inet_ntoa(addr));
> - printf(" Link Data (Network Mask): %s\n",
> - inet_ntoa(data));
> - break;
> - default:
> - printf(" Link ID (Unknown): %s\n",
> - inet_ntoa(addr));
> - printf(" Link Data (Unknown): %s\n",
> - inet_ntoa(data));
> - break;
> - }
> -
> - printf(" Metric: %d\n\n", ntohs(rtr_link->metric));
> -
> - off += sizeof(struct lsa_rtr_link) +
> - rtr_link->num_tos * sizeof(u_int32_t);
> - }
> -
> - lasttype = lsa->hdr.type;
> - break;
> - case IMSG_CTL_SHOW_DB_SUM:
> - case IMSG_CTL_SHOW_DB_ASBR:
> - lsa = imsg->data;
> - if (lsa->hdr.type != lasttype)
> - show_database_head(area_id, ifname, lsa->hdr.type);
> - show_db_hdr_msg_detail(&lsa->hdr);
> - addr.s_addr = lsa->data.sum.mask;
> - printf("Network Mask: %s\n", inet_ntoa(addr));
> - printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
> - LSA_METRIC_MASK);
> - lasttype = lsa->hdr.type;
> - break;
> - case IMSG_CTL_SHOW_DB_OPAQ:
> - lsa = imsg->data;
> - if (lsa->hdr.type != lasttype)
> - show_database_head(area_id, ifname, lsa->hdr.type);
> - show_db_hdr_msg_detail(&lsa->hdr);
> - /* XXX should we hexdump the data? */
> - lasttype = lsa->hdr.type;
> - break;
> - case IMSG_CTL_AREA:
> - area = imsg->data;
> - area_id = area->id;
> - lasttype = 0;
> - break;
> - case IMSG_CTL_IFACE:
> - iface = imsg->data;
> - strlcpy(ifname, iface->name, sizeof(ifname));
> - lasttype = 0;
> - break;
> - case IMSG_CTL_END:
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -int
> -show_nbr_msg(struct imsg *imsg)
> -{
> - struct ctl_nbr *nbr;
> - char *state;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_NBR:
> - nbr = imsg->data;
> - if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
> - if_state_name(nbr->iface_state)) == -1)
> - err(1, NULL);
> - printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
> - nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
> - printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name,
> - nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
> - free(state);
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> const char *
> print_ospf_options(u_int8_t opts)
> {
> @@ -996,128 +520,6 @@ print_ospf_options(u_int8_t opts)
> return (optbuf);
> }
> -int
> -show_nbr_detail_msg(struct imsg *imsg)
> -{
> - struct ctl_nbr *nbr;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_NBR:
> - nbr = imsg->data;
> - printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
> - printf("interface address %s\n", inet_ntoa(nbr->addr));
> - printf(" Area %s, interface %s\n", inet_ntoa(nbr->area),
> - nbr->name);
> - printf(" Neighbor priority is %d, "
> - "State is %s, %d state changes\n",
> - nbr->priority, nbr_state_name(nbr->nbr_state),
> - nbr->state_chng_cnt);
> - printf(" DR is %s, ", inet_ntoa(nbr->dr));
> - printf("BDR is %s\n", inet_ntoa(nbr->bdr));
> - printf(" Options %s\n", print_ospf_options(nbr->options));
> - printf(" Dead timer due in %s\n",
> - fmt_timeframe_core(nbr->dead_timer));
> - printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime));
> - printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt);
> - printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt);
> - printf(" Link State Retransmission List %d\n",
> - nbr->ls_retrans_lst_cnt);
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -int
> -show_rib_msg(struct imsg *imsg)
> -{
> - struct ctl_rt *rt;
> - char *dstnet;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_RIB:
> - rt = imsg->data;
> - switch (rt->d_type) {
> - case DT_NET:
> - if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
> - rt->prefixlen) == -1)
> - err(1, NULL);
> - break;
> - case DT_RTR:
> - if (asprintf(&dstnet, "%s",
> - inet_ntoa(rt->prefix)) == -1)
> - err(1, NULL);
> - break;
> - default:
> - errx(1, "Invalid route type");
> - }
> -
> - printf("%-20s %-16s%s %-12s %-9s %-7d %s\n", dstnet,
> - inet_ntoa(rt->nexthop), rt->connected ? "C" : " ",
> - path_type_name(rt->p_type),
> - dst_type_name(rt->d_type), rt->cost,
> - rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
> - free(dstnet);
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -void
> -show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
> -{
> - char *header, *format, *format2;
> -
> - switch (p_type) {
> - case PT_INTRA_AREA:
> - case PT_INTER_AREA:
> - switch (d_type) {
> - case DT_NET:
> - format = "Network Routing Table";
> - format2 = "";
> - break;
> - case DT_RTR:
> - format = "Router Routing Table";
> - format2 = "Type";
> - break;
> - default:
> - errx(1, "unknown route type");
> - }
> - break;
> - case PT_TYPE1_EXT:
> - case PT_TYPE2_EXT:
> - format = NULL;
> - format2 = "Cost 2";
> - if ((header = strdup("External Routing Table")) == NULL)
> - err(1, NULL);
> - break;
> - default:
> - errx(1, "unknown route type");
> - }
> -
> - if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
> - if (asprintf(&header, "%s (Area %s)", format,
> - inet_ntoa(aid)) == -1)
> - err(1, NULL);
> -
> - printf("\n%-18s %s\n", "", header);
> - free(header);
> -
> - printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
> - "Nexthop", "Adv Router", "Path type", "Cost", format2);
> -}
> -
> const char *
> print_ospf_rtr_flags(u_int8_t opts)
> {
> @@ -1130,155 +532,6 @@ print_ospf_rtr_flags(u_int8_t opts)
> return (optbuf);
> }
> -int
> -show_rib_detail_msg(struct imsg *imsg)
> -{
> - static struct in_addr area_id;
> - struct ctl_rt *rt;
> - struct area *area;
> - char *dstnet;
> - static u_int8_t lasttype;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_SHOW_RIB:
> - rt = imsg->data;
> -
> - switch (rt->p_type) {
> - case PT_INTRA_AREA:
> - case PT_INTER_AREA:
> - switch (rt->d_type) {
> - case DT_NET:
> - if (lasttype != RIB_NET)
> - show_rib_head(rt->area, rt->d_type,
> - rt->p_type);
> - if (asprintf(&dstnet, "%s/%d",
> - inet_ntoa(rt->prefix), rt->prefixlen) == -1)
> - err(1, NULL);
> - lasttype = RIB_NET;
> - break;
> - case DT_RTR:
> - if (lasttype != RIB_RTR)
> - show_rib_head(rt->area, rt->d_type,
> - rt->p_type);
> - if (asprintf(&dstnet, "%s",
> - inet_ntoa(rt->prefix)) == -1)
> - err(1, NULL);
> - lasttype = RIB_RTR;
> - break;
> - default:
> - errx(1, "unknown route type");
> - }
> - printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
> - printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
> - path_type_name(rt->p_type), rt->cost);
> - free(dstnet);
> -
> - if (rt->d_type == DT_RTR)
> - printf(" %-7s",
> - print_ospf_rtr_flags(rt->flags));
> -
> - printf("\n");
> - break;
> - case PT_TYPE1_EXT:
> - case PT_TYPE2_EXT:
> - if (lasttype != RIB_EXT)
> - show_rib_head(rt->area, rt->d_type, rt->p_type);
> -
> - if (asprintf(&dstnet, "%s/%d",
> - inet_ntoa(rt->prefix), rt->prefixlen) == -1)
> - err(1, NULL);
> -
> - printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
> - printf("%-15s %-12s %-7d %-7d\n",
> - inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
> - rt->cost, rt->cost2);
> - free(dstnet);
> -
> - lasttype = RIB_EXT;
> - break;
> - default:
> - errx(1, "unknown route type");
> - }
> - break;
> - case IMSG_CTL_AREA:
> - area = imsg->data;
> - area_id = area->id;
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -void
> -show_fib_head(void)
> -{
> - printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
> - printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination", 
> "Nexthop");
> -}
> -
> -int
> -show_fib_msg(struct imsg *imsg)
> -{
> - struct kroute *k;
> - char *p;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_KROUTE:
> - if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
> - errx(1, "wrong imsg len");
> - k = imsg->data;
> -
> - if (k->flags & F_DOWN)
> - printf(" ");
> - else
> - printf("*");
> -
> - if (!(k->flags & F_KERNEL))
> - printf("O");
> - else if (k->flags & F_CONNECTED)
> - printf("C");
> - else if (k->flags & F_STATIC)
> - printf("S");
> - else
> - printf(" ");
> -
> - printf(" ");
> - printf("%4d ", k->priority);
> - if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
> - -1)
> - err(1, NULL);
> - printf("%-20s ", 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);
> - printf("\n");
> -
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> -
> -void
> -show_interface_head(void)
> -{
> - printf("%-15s%-15s%s\n", "Interface", "Flags",
> - "Link state");
> -}
> -
> const struct if_status_description
> if_status_descriptions[] = LINK_STATE_DESCRIPTIONS;
> const struct ifmedia_description
> @@ -1310,48 +563,18 @@ get_linkstate(uint8_t if_type, int link_state)
> return (buf);
> }
> -void
> +const char *
> print_baudrate(u_int64_t baudrate)
> {
> + static char buf[32];
> if (baudrate > IF_Gbps(1))
> - printf("%llu GBit/s", baudrate / IF_Gbps(1));
> + snprintf(buf, sizeof(buf), "%llu GBit/s", baudrate / IF_Gbps(1));
> else if (baudrate > IF_Mbps(1))
> - printf("%llu MBit/s", baudrate / IF_Mbps(1));
> + snprintf(buf, sizeof(buf), "%llu MBit/s", baudrate / IF_Mbps(1));
> else if (baudrate > IF_Kbps(1))
> - printf("%llu KBit/s", baudrate / IF_Kbps(1));
> + snprintf(buf, sizeof(buf), "%llu KBit/s", baudrate / IF_Kbps(1));
> else
> - printf("%llu Bit/s", baudrate);
> + snprintf(buf, sizeof(buf), "%llu Bit/s", baudrate);
> + return (buf);
> }
> -int
> -show_fib_interface_msg(struct imsg *imsg)
> -{
> - struct kif *k;
> - uint64_t ifms_type;
> -
> - switch (imsg->hdr.type) {
> - case IMSG_CTL_IFINFO:
> - k = imsg->data;
> - printf("%-15s", k->ifname);
> - printf("%-15s", k->flags & IFF_UP ? "UP" : "");
> - ifms_type = get_ifms_type(k->if_type);
> - if (ifms_type)
> - printf("%s, ", get_media_descr(ifms_type));
> -
> - printf("%s", get_linkstate(k->if_type, k->link_state));
> -
> - if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
> - printf(", ");
> - print_baudrate(k->baudrate);
> - }
> - printf("\n");
> - break;
> - case IMSG_CTL_END:
> - printf("\n");
> - return (1);
> - default:
> - break;
> - }
> -
> - return (0);
> -}
> diff --git a/usr.sbin/ospfctl/ospfctl.h b/usr.sbin/ospfctl/ospfctl.h
> new file mode 100644
> index 00000000000..3077307cce6
> --- /dev/null
> +++ b/usr.sbin/ospfctl/ospfctl.h
> @@ -0,0 +1,55 @@
> +/*
> +* Copyright (c) 2005 Claudio Jeker <clau...@openbsd.org>
> + * Copyright (c) 2004, 2005 Esben Norby <no...@openbsd.org>
> + * Copyright (c) 2003 Henning Brauer <henn...@openbsd.org>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +struct parse_result;
> +
> +struct output {
> + void (*head)(struct parse_result *);
> + void (*interface)(struct ctl_iface *, int);
> + void (*summary)(struct ctl_sum *);
> + void (*summary_area)(struct ctl_sum_area *);
> + void (*neighbor)(struct ctl_nbr *, int);
> + void (*rib)(struct ctl_rt *, int);
> + void (*fib)(struct kroute *);
> + void (*fib_interface)(struct kif *);
> + void (*db)(struct lsa *, struct in_addr, u_int8_t,
> + char ifname[IF_NAMESIZE]);
> + void (*db_simple)(struct lsa_hdr *, struct in_addr, u_int8_t,
> + char ifname[IF_NAMESIZE]);
> + void (*tail)(void);
> +};
> +
> +extern const struct output show_output, json_output;
> +
> +
> +
> +#define EOL0(flag) ((flag & F_CTL_SSV) ? ';' : '\n')
> +
> +const char *fmt_timeframe_core(time_t);
> +const char *get_linkstate(uint8_t, int);
> +const char *print_ospf_rtr_flags(u_int8_t);
> +const char *print_ospf_options(u_int8_t);
> +uint64_t get_ifms_type(uint8_t);
> +const char *get_media_descr(uint64_t);
> +const char *print_baudrate(u_int64_t);
> +const char *print_link(int);
> +char *print_ls_type(u_int8_t);
> +const char *log_id(u_int32_t );
> +const char *log_adv_rtr(u_int32_t);
> +const char *print_ospf_flags(u_int8_t);
> +char *print_rtr_link_type(u_int8_t);
> diff --git a/usr.sbin/ospfctl/output.c b/usr.sbin/ospfctl/output.c
> new file mode 100644
> index 00000000000..f31eeb3c460
> --- /dev/null
> +++ b/usr.sbin/ospfctl/output.c
> @@ -0,0 +1,650 @@
> +/*
> + * Copyright (c) 2020 Richard Chivers <r.chiv...@zengenti.com>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <net/if_media.h>
> +#include <net/if_types.h>
> +
> +#include <err.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include "ospf.h"
> +#include "ospfd.h"
> +#include "ospfctl.h"
> +#include "ospfe.h"
> +#include "parser.h"
> +
> +static void
> +show_head(struct parse_result *res)
> +{
> + switch (res->action) {
> + case SHOW_IFACE:
> + printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n",
> + "Interface", "Address", "State", "HelloTimer", "Linkstate",
> + "Uptime", "nc", "ac");
> + break;
> + case SHOW_FIB:
> + printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
> + printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination",
> + "Nexthop");
> + break;
> + case SHOW_FIB_IFACE:
> + printf("%-15s%-15s%s\n", "Interface", "Flags", "Link state");
> + break;
> + case SHOW_NBR:
> + printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
> + "State", "DeadTime", "Address", "Iface","Uptime");
> + break;
> + case SHOW_RIB:
> + printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
> + "Nexthop", "Path Type", "Type", "Cost", "Uptime");
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static void
> +show_summary(struct ctl_sum *sum)
> +{
> + printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
> + printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
> + printf("RFC1583 compatibility flag is ");
> + if (sum->rfc1583compat)
> + printf("enabled\n");
> + else
> + printf("disabled\n");
> +
> + printf("SPF delay is %d msec(s), hold time between two SPFs "
> + "is %d msec(s)\n", sum->spf_delay, sum->spf_hold_time);
> + printf("Number of external LSA(s) %d (Checksum sum 0x%x)\n",
> + sum->num_ext_lsa, sum->ext_lsa_cksum);
> + printf("Number of areas attached to this router: %d\n",
> + sum->num_area);
> +}
> +
> +static void
> +show_summary_area(struct ctl_sum_area *sumarea){
> + printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
> + printf(" Number of interfaces in this area: %d\n",
> + sumarea->num_iface);
> + printf(" Number of fully adjacent neighbors in this "
> + "area: %d\n", sumarea->num_adj_nbr);
> + printf(" SPF algorithm executed %d time(s)\n",
> + sumarea->num_spf_calc);
> + printf(" Number LSA(s) %d (Checksum sum 0x%x)\n",
> + sumarea->num_lsa, sumarea->lsa_cksum);
> +}
> +
> +static void
> +show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
> +{
> + char *header, *format, *format2;
> +
> + switch (p_type) {
> + case PT_INTRA_AREA:
> + case PT_INTER_AREA:
> + switch (d_type) {
> + case DT_NET:
> + format = "Network Routing Table";
> + format2 = "";
> + break;
> + case DT_RTR:
> + format = "Router Routing Table";
> + format2 = "Type";
> + break;
> + default:
> + errx(1, "unknown route type");
> + }
> + break;
> + case PT_TYPE1_EXT:
> + case PT_TYPE2_EXT:
> + format = NULL;
> + format2 = "Cost 2";
> + if ((header = strdup("External Routing Table")) == NULL)
> + err(1, NULL);
> + break;
> + default:
> + errx(1, "unknown route type");
> + }
> +
> + if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
> + if (asprintf(&header, "%s (Area %s)", format,
> + inet_ntoa(aid)) == -1)
> + err(1, NULL);
> +
> + printf("\n%-18s %s\n", "", header);
> + free(header);
> +
> + printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
> + "Nexthop", "Adv Router", "Path type", "Cost", format2);
> +}
> +
> +static void
> +show_interface(struct ctl_iface *iface, int detail)
> +{
> + char *netid;
> +
> + // This wasn't previously executed on detail call
> + if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
> + mask2prefixlen(iface->mask.s_addr)) == -1)
> + err(1, NULL);
> +
> + if(detail){
> + printf("\n");
> + printf("Interface %s, line protocol is %s\n",
> + iface->name, print_link(iface->flags));
> + printf(" Internet address %s/%d, ",
> + inet_ntoa(iface->addr),
> + mask2prefixlen(iface->mask.s_addr));
> + printf("Area %s\n", inet_ntoa(iface->area));
> + printf(" Linkstate %s,",
> + get_linkstate(iface->if_type, iface->linkstate));
> + printf(" mtu %d\n", iface->mtu);
> + printf(" Router ID %s, network type %s, cost: %d\n",
> + inet_ntoa(iface->rtr_id),
> + if_type_name(iface->type), iface->metric);
> + printf(" Transmit delay is %d sec(s), state %s, priority %d\n",
> + iface->transmit_delay, if_state_name(iface->state),
> + iface->priority);
> + printf(" Designated Router (ID) %s, ",
> + inet_ntoa(iface->dr_id));
> + printf("interface address %s\n", inet_ntoa(iface->dr_addr));
> + printf(" Backup Designated Router (ID) %s, ",
> + inet_ntoa(iface->bdr_id));
> + printf("interface address %s\n", inet_ntoa(iface->bdr_addr));
> + if (iface->dead_interval == FAST_RTR_DEAD_TIME) {
> + printf(" Timer intervals configured, "
> + "hello %d msec, dead %d, wait %d, retransmit %d\n",
> + iface->fast_hello_interval, iface->dead_interval,
> + iface->dead_interval, iface->rxmt_interval);
> +
> + } else {
> + printf(" Timer intervals configured, "
> + "hello %d, dead %d, wait %d, retransmit %d\n",
> + iface->hello_interval, iface->dead_interval,
> + iface->dead_interval, iface->rxmt_interval);
> + }
> + if (iface->passive)
> + printf(" Passive interface (No Hellos)\n");
> + else if (iface->hello_timer.tv_sec < 0)
> + printf(" Hello timer not running\n");
> + else
> + printf(" Hello timer due in %s+%ldmsec\n",
> + fmt_timeframe_core(iface->hello_timer.tv_sec),
> + iface->hello_timer.tv_usec / 1000);
> + printf(" Uptime %s\n", fmt_timeframe_core(iface->uptime));
> + printf(" Neighbor count is %d, adjacent neighbor count is "
> + "%d\n", iface->nbr_cnt, iface->adj_cnt);
> + if (iface->auth_type > 0) {
> + switch (iface->auth_type) {
> + case AUTH_SIMPLE:
> + printf(" Simple password authentication "
> + "enabled\n");
> + break;
> + case AUTH_CRYPT:
> + printf(" Message digest authentication "
> + "enabled\n");
> + printf(" Primary key id is %d\n",
> + iface->auth_keyid);
> + break;
> + default:
> + break;
> + }
> + }
> + }else{
> + printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n",
> + iface->name, netid, if_state_name(iface->state),
> + iface->hello_timer.tv_sec < 0 ? "-" :
> + fmt_timeframe_core(iface->hello_timer.tv_sec),
> + get_linkstate(iface->if_type, iface->linkstate),
> + fmt_timeframe_core(iface->uptime),
> + iface->nbr_cnt, iface->adj_cnt);
> + }
> + free(netid);
> +}
> +
> +
> +static void
> +show_neighbor(struct ctl_nbr *nbr, int detail)
> +{
> + char *state;
> + if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
> + if_state_name(nbr->iface_state)) == -1)
> + err(1, NULL);
> +
> + if(detail){
> + printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
> + printf("interface address %s\n", inet_ntoa(nbr->addr));
> + printf(" Area %s, interface %s\n", inet_ntoa(nbr->area),
> + nbr->name);
> + printf(" Neighbor priority is %d, "
> + "State is %s, %d state changes\n",
> + nbr->priority, nbr_state_name(nbr->nbr_state),
> + nbr->state_chng_cnt);
> + printf(" DR is %s, ", inet_ntoa(nbr->dr));
> + printf("BDR is %s\n", inet_ntoa(nbr->bdr));
> + printf(" Options %s\n", print_ospf_options(nbr->options));
> + printf(" Dead timer due in %s\n",
> + fmt_timeframe_core(nbr->dead_timer));
> + printf(" Uptime %s\n", fmt_timeframe_core(nbr->uptime));
> + printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt);
> + printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt);
> + printf(" Link State Retransmission List %d\n",
> + nbr->ls_retrans_lst_cnt);
> + }else{
> + printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
> + nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
> + printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name,
> + nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
> + }
> + free(state);
> +}
> +
> +static void
> +show_rib(struct ctl_rt *rt, int detail)
> +{
> + char *dstnet;
> + static u_int8_t lasttype;
> + if(detail){
> + switch (rt->p_type) {
> + case PT_INTRA_AREA:
> + case PT_INTER_AREA:
> + switch (rt->d_type) {
> + case DT_NET:
> + if (lasttype != RIB_NET)
> + show_rib_head(rt->area, rt->d_type,
> + rt->p_type);
> + if (asprintf(&dstnet, "%s/%d",
> + inet_ntoa(rt->prefix), rt->prefixlen) == -1)
> + err(1, NULL);
> + lasttype = RIB_NET;
> + break;
> + case DT_RTR:
> + if (lasttype != RIB_RTR)
> + show_rib_head(rt->area, rt->d_type,
> + rt->p_type);
> + if (asprintf(&dstnet, "%s",
> + inet_ntoa(rt->prefix)) == -1)
> + err(1, NULL);
> + lasttype = RIB_RTR;
> + break;
> + default:
> + errx(1, "unknown route type");
> + }
> + printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
> + printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
> + path_type_name(rt->p_type), rt->cost);
> + free(dstnet);
> +
> + if (rt->d_type == DT_RTR)
> + printf(" %-7s",
> + print_ospf_rtr_flags(rt->flags));
> +
> + printf("\n");
> + break;
> + case PT_TYPE1_EXT:
> + case PT_TYPE2_EXT:
> + if (lasttype != RIB_EXT)
> + show_rib_head(rt->area, rt->d_type, rt->p_type);
> +
> + if (asprintf(&dstnet, "%s/%d",
> + inet_ntoa(rt->prefix), rt->prefixlen) == -1)
> + err(1, NULL);
> +
> + printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
> + printf("%-15s %-12s %-7d %-7d\n",
> + inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
> + rt->cost, rt->cost2);
> + free(dstnet);
> +
> + lasttype = RIB_EXT;
> + break;
> + default:
> + errx(1, "unknown route type");
> + }
> + }else{
> + switch (rt->d_type) {
> + case DT_NET:
> + if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
> + rt->prefixlen) == -1)
> + err(1, NULL);
> + break;
> + case DT_RTR:
> + if (asprintf(&dstnet, "%s",
> + inet_ntoa(rt->prefix)) == -1)
> + err(1, NULL);
> + break;
> + default:
> + errx(1, "Invalid route type");
> + }
> +
> + printf("%-20s %-16s%s %-12s %-9s %-7d %s\n", dstnet,
> + inet_ntoa(rt->nexthop), rt->connected ? "C" : " ",
> + path_type_name(rt->p_type),
> + dst_type_name(rt->d_type), rt->cost,
> + rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
> + free(dstnet);
> + }
> +}
> +
> +static void
> +show_fib(struct kroute *k)
> +{
> + char *p;
> + if (k->flags & F_DOWN)
> + printf(" ");
> + else
> + printf("*");
> +
> + if (!(k->flags & F_KERNEL))
> + printf("O");
> + else if (k->flags & F_CONNECTED)
> + printf("C");
> + else if (k->flags & F_STATIC)
> + printf("S");
> + else
> + printf(" ");
> +
> + printf(" ");
> + printf("%4d ", k->priority);
> + if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
> + -1)
> + err(1, NULL);
> + printf("%-20s ", 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);
> + printf("\n");
> +}
> +
> +static void
> +show_fib_interface(struct kif *k)
> +{
> + uint64_t ifms_type;
> + printf("%-15s", k->ifname);
> + printf("%-15s", k->flags & IFF_UP ? "UP" : "");
> + ifms_type = get_ifms_type(k->if_type);
> + if (ifms_type)
> + printf("%s, ", get_media_descr(ifms_type));
> +
> + printf("%s", get_linkstate(k->if_type, k->link_state));
> +
> + if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
> + printf(", ");
> + printf("%s", print_baudrate(k->baudrate));
> + }
> + printf("\n");
> +}
> +
> +static void
> +show_database_head(struct in_addr aid, char *ifname, u_int8_t type)
> +{
> + char *header, *format;
> + int cleanup = 0;
> +
> + switch (type) {
> + case LSA_TYPE_ROUTER:
> + format = "Router Link States";
> + break;
> + case LSA_TYPE_NETWORK:
> + format = "Net Link States";
> + break;
> + case LSA_TYPE_SUM_NETWORK:
> + format = "Summary Net Link States";
> + break;
> + case LSA_TYPE_SUM_ROUTER:
> + format = "Summary Router Link States";
> + break;
> + case LSA_TYPE_EXTERNAL:
> + format = NULL;
> + if ((header = strdup("Type-5 AS External Link States")) == NULL)
> + err(1, NULL);
> + break;
> + case LSA_TYPE_LINK_OPAQ:
> + format = "Type-9 Link Local Opaque Link States";
> + break;
> + case LSA_TYPE_AREA_OPAQ:
> + format = "Type-10 Area Local Opaque Link States";
> + break;
> + case LSA_TYPE_AS_OPAQ:
> + format = NULL;
> + if ((header = strdup("Type-11 AS Wide Opaque Link States")) ==
> + NULL)
> + err(1, NULL);
> + break;
> + default:
> + if (asprintf(&format, "LSA type %x", ntohs(type)) == -1)
> + err(1, NULL);
> + cleanup = 1;
> + break;
> + }
> + if (type == LSA_TYPE_LINK_OPAQ) {
> + if (asprintf(&header, "%s (Area %s Interface %s)", format,
> + inet_ntoa(aid), ifname) == -1)
> + err(1, NULL);
> + } else if (type != LSA_TYPE_EXTERNAL && type != LSA_TYPE_AS_OPAQ)
> + if (asprintf(&header, "%s (Area %s)", format,
> + inet_ntoa(aid)) == -1)
> + err(1, NULL);
> +
> + printf("\n%-15s %s\n\n", "", header);
> + free(header);
> + if (cleanup)
> + free(format);
> +}
> +
> +static void
> +show_db_hdr_msg_detail(struct lsa_hdr *lsa)
> +{
> + printf("LS age: %d\n", ntohs(lsa->age));
> + printf("Options: %s\n", print_ospf_options(lsa->opts));
> + printf("LS Type: %s\n", print_ls_type(lsa->type));
> +
> + switch (lsa->type) {
> + case LSA_TYPE_ROUTER:
> + printf("Link State ID: %s\n", log_id(lsa->ls_id));
> + break;
> + case LSA_TYPE_NETWORK:
> + printf("Link State ID: %s (address of Designated Router)\n",
> + log_id(lsa->ls_id));
> + break;
> + case LSA_TYPE_SUM_NETWORK:
> + printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
> + break;
> + case LSA_TYPE_SUM_ROUTER:
> + printf("Link State ID: %s (ASBR Router ID)\n",
> + log_id(lsa->ls_id));
> + break;
> + case LSA_TYPE_EXTERNAL:
> + printf("Link State ID: %s (External Network Number)\n",
> + log_id(lsa->ls_id));
> + break;
> + case LSA_TYPE_LINK_OPAQ:
> + case LSA_TYPE_AREA_OPAQ:
> + case LSA_TYPE_AS_OPAQ:
> + printf("Link State ID: %s Type %d ID %d\n", log_id(lsa->ls_id),
> + LSA_24_GETHI(ntohl(lsa->ls_id)),
> + LSA_24_GETLO(ntohl(lsa->ls_id)));
> + break;
> + }
> +
> + printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
> + printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
> + printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
> + printf("Length: %d\n", ntohs(lsa->len));
> +}
> +
> +static void
> +show_db_simple(struct lsa_hdr *lsa, struct in_addr area_id, u_int8_t 
> lasttype,
> + char ifname[IF_NAMESIZE])
> +{
> + if (lsa->type != lasttype) {
> + show_database_head(area_id, ifname, lsa->type);
> + printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
> + "Adv Router", "Age", "Seq#", "Checksum");
> + }
> + printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
> + log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
> + ntohs(lsa->age), ntohl(lsa->seq_num),
> + ntohs(lsa->ls_chksum));
> +}
> +static void
> +show_db(struct lsa *lsa, struct in_addr area_id, u_int8_t lasttype,
> + char ifname[IF_NAMESIZE])
> +{
> + struct in_addr addr, data;
> + struct lsa_asext *asext;
> + struct lsa_rtr_link *rtr_link;
> + u_int16_t i, nlinks, off;
> + if (lsa->hdr.type != lasttype)
> + show_database_head(area_id, ifname, lsa->hdr.type);
> + show_db_hdr_msg_detail(&lsa->hdr);
> +
> + switch (lsa->hdr.type) {
> + case LSA_TYPE_EXTERNAL:
> + addr.s_addr = lsa->data.asext.mask;
> + printf("Network Mask: %s\n", inet_ntoa(addr));
> +
> + asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
> +
> + printf(" Metric type: ");
> + if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
> + printf("2\n");
> + else
> + printf("1\n");
> + printf(" Metric: %d\n", ntohl(asext->metric)
> + & LSA_METRIC_MASK);
> + addr.s_addr = asext->fw_addr;
> + printf(" Forwarding Address: %s\n", inet_ntoa(addr));
> + printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag));
> + break;
> + case LSA_TYPE_NETWORK:
> + addr.s_addr = lsa->data.net.mask;
> + printf("Network Mask: %s\n", inet_ntoa(addr));
> +
> + nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
> + - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
> + off = sizeof(lsa->hdr) + sizeof(u_int32_t);
> + printf("Number of Routers: %d\n", nlinks);
> +
> + for (i = 0; i < nlinks; i++) {
> + addr.s_addr = lsa->data.net.att_rtr[i];
> + printf(" Attached Router: %s\n", inet_ntoa(addr));
> + }
> +
> + printf("\n");
> + break;
> + case LSA_TYPE_ROUTER:
> + printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
> + nlinks = ntohs(lsa->data.rtr.nlinks);
> + printf("Number of Links: %d\n\n", nlinks);
> +
> + off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
> +
> + for (i = 0; i < nlinks; i++) {
> + rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
> +
> + printf(" Link connected to: %s\n",
> + print_rtr_link_type(rtr_link->type));
> +
> + addr.s_addr = rtr_link->id;
> + data.s_addr = rtr_link->data;
> +
> + switch (rtr_link->type) {
> + case LINK_TYPE_POINTTOPOINT:
> + case LINK_TYPE_VIRTUAL:
> + printf(" Link ID (Neighbors Router ID):"
> + " %s\n", inet_ntoa(addr));
> + printf(" Link Data (Router Interface "
> + "address): %s\n", inet_ntoa(data));
> + break;
> + case LINK_TYPE_TRANSIT_NET:
> + printf(" Link ID (Designated Router "
> + "address): %s\n", inet_ntoa(addr));
> + printf(" Link Data (Router Interface "
> + "address): %s\n", inet_ntoa(data));
> + break;
> + case LINK_TYPE_STUB_NET:
> + printf(" Link ID (Network ID): %s\n",
> + inet_ntoa(addr));
> + printf(" Link Data (Network Mask): %s\n",
> + inet_ntoa(data));
> + break;
> + default:
> + printf(" Link ID (Unknown): %s\n",
> + inet_ntoa(addr));
> + printf(" Link Data (Unknown): %s\n",
> + inet_ntoa(data));
> + break;
> + }
> +
> + printf(" Metric: %d\n\n", ntohs(rtr_link->metric));
> +
> + off += sizeof(struct lsa_rtr_link) +
> + rtr_link->num_tos * sizeof(u_int32_t);
> + }
> + break;
> + case LSA_TYPE_SUM_ROUTER:
> + if (lsa->hdr.type != lasttype)
> + show_database_head(area_id, ifname, lsa->hdr.type);
> + show_db_hdr_msg_detail(&lsa->hdr);
> + addr.s_addr = lsa->data.sum.mask;
> + printf("Network Mask: %s\n", inet_ntoa(addr));
> + printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
> + LSA_METRIC_MASK);
> + break;
> + case LSA_TYPE_LINK_OPAQ:
> + case LSA_TYPE_AREA_OPAQ:
> + case LSA_TYPE_AS_OPAQ:
> + if (lsa->hdr.type != lasttype)
> + show_database_head(area_id, ifname, lsa->hdr.type);
> + show_db_hdr_msg_detail(&lsa->hdr);
> + /* XXX should we hexdump the data? */
> + break;
> + }
> +}
> +
> +static void
> +show_tail(void)
> +{
> + /* nothing */
> +}
> +
> +const struct output show_output = {
> + .head = show_head,
> + .summary = show_summary,
> + .summary_area = show_summary_area,
> + .interface = show_interface,
> + .neighbor = show_neighbor,
> + .rib = show_rib,
> + .fib = show_fib,
> + .fib_interface = show_fib_interface,
> + .db = show_db,
> + .db_simple = show_db_simple,
> + .tail = show_tail
> +};
> 
> 
> On Mon, May 11, 2020 at 1:52 PM Claudio Jeker <cje...@diehard.n-r-g.com> 
> wrote:
> >
> > On Mon, May 11, 2020 at 12:38:38PM +0100, Richard Chivers wrote:
> > > Hi,
> > >
> > > I have done some work over the last few days to implement json support
> > > into ospfctl following the work done recently in bgpctl.
> > >
> > > I have some queries, hoping to get some help with.
> > >
> > > The change involves a refactor of ospfctl, but reuses the recent
> > > json.c written by Claudio, that is in the
> > > usr.sbin/bgpctl directory. At present no changes have been required at 
> > > all.
> > > What is the best approach here, should/could this be centralised 
> > > somewhere?
> >
> > At the moment just copy the files into ospfctl. We did the same thing with
> > other bits in the tree. My json API is super minimal and is for sure not
> > something that should be put into a common framework right now. The way
> > objects and arrays are opened and closed is a bit rough and does not
> > always work well.
> >
> > > In some cases there is room for change, for example ospfctl sh rib &
> > > ospfctl sh rib detail.
> > >
> > > In my view here, it makes sense to have a full list returned rather
> > > than splitting json into multiple lists of Router, Network and
> > > External.
> > > I looked for inspiration in the bgpctl, but couldn't find a similar
> > > pattern. The reason for a single list is that if consuming the json,
> > > I expect you will not want code that has to iterate over three
> > > separate arrays. Just looking for some feedback really. The original
> > > split
> > > made sense for screen use, just not so sure about machine readability.
> > > This issue also applies to ospfctl sh data, which returns 3 lists.
> >
> > A lot of this is depending on the imsgs used between ospfctl and ospfd.
> > IIRC ospfd sends all data in one batch so the multiple lists just happen
> > by ospfctl and indeed for json output it would be best to display the rib
> > as a single array of entries (which have a similar structure but probably
> > per LSA specific attributes).
> >
> > > When I am finished, should I just post the diff on here? Just
> > > conscious it is quite a big refactor, albeit much of the code is
> > > reused just moved into output.c as
> > > was done for bgpctl.
> >
> > Please split it up like I did it for bgpctl. I first did a lot of the
> > moving and cleanup and only later added the new input mode. This makes the
> > individual steps smaller to review.
> >
> > > I am testing each call individually against a set of openbsd 6.6 boxes
> > > we have running, which is great for ospfd. What is the normal
> > > practise for ospf6, is there a script run to replicate code changes or
> > > is it just a case of making very similar changes line by line?
> >
> > There is no script, you do it by hand it is quicker.
> >
> > > Just looking for the general thinking and approach I guess. I don't
> > > currently have ospf6 set-up so that would be some overhead.
> > > Happy to configure it though if needed/expected.
> >
> > Get ospfctl first, after that ospf6ctl can be done (and maybe somebody
> > else will take care of that).
> >
> > > Finally what was the driver under bgpctl for the json output, ours is
> > > for reading metrics to populate telemetry, just interested as the
> > > purpose other
> > > people have. Having this context will help in micro decisions when
> > > implementing the json structure.
> >
> > I'm doing this work to provide JSON payloads to external looking glasses.
> > I would not put the RIB into telemetry (that is just useless churn and
> > load on the telemetry system). In bgpctl the terse outputs are simple
> > space separated outputs for telemetry scripting but I guess people will
> > also use the JSON output for this.
> >
> > > As a final thought is this something that is actually wanted
> > > generally, I assumed it was as bgpctl has gone/is going in that
> > > direction, but just don't want to assume.
> >
> > I see no reason why not. At least I wont veto it.
> >
> > --
> > :wq Claudio
> 

Reply via email to