Hi, Thanks for the feedback, I wasn't happy with the detail flag either, I just missed coming back to rethink / change it.
There was a lot of duplicate code i seem to remember, as much of the output is sent regardless. I will take a look over the next couple of days when I get a few minutes to retest etc. I will also check the style(9) I imagine I have the wrong line length configured.... In terms of process, shall I do that first before anything else happens? Sorry not familiar with the review process etc. On Mon, May 18, 2020 at 11:00 AM Claudio Jeker <[email protected]> wrote: > > On Mon, May 18, 2020 at 09:49:24AM +0200, Denis Fondras wrote: > > On Mon, May 18, 2020 at 09:04:06AM +0200, Claudio Jeker wrote: > > > There is a file missing in the diff. > > > > > > One thing I have seen in the original diff from Richard was that the > > > copyright in the new file should be copied from ospfctl.c since this is > > > mostly a copy paste action and not new work. > > > > > > > Stupid me... Here is an update. > > Thank you Claudio. > > Not sure about the detail switches. Like this one: > > > + case IMSG_CTL_SHOW_INTERFACE: > > + ctliface = imsg->data; > > + if(res->action == SHOW_IFACE_DTAIL) > > + output->interface(ctliface, 1); > > + else > > + output->interface(ctliface, 0); > > + break; > > I pushed those down into the show functions so that the show() function in > bgpctl does not do any kind of decision on the output. > > I looked over the code. There is more KNF fixes needed and maybe some > additional changes (like return a response object for all calls) that can > happen in tree. > > OK claudio@ > > > Index: Makefile > > =================================================================== > > RCS file: /cvs/src/usr.sbin/ospfctl/Makefile,v > > retrieving revision 1.5 > > diff -u -p -r1.5 Makefile > > --- Makefile 2 Sep 2016 14:02:48 -0000 1.5 > > +++ Makefile 17 May 2020 10:51:28 -0000 > > @@ -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 > > Index: ospfctl.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/ospfctl/ospfctl.c,v > > retrieving revision 1.66 > > diff -u -p -r1.66 ospfctl.c > > --- ospfctl.c 1 Nov 2019 18:15:28 -0000 1.66 > > +++ ospfctl.c 17 May 2020 11:11:50 -0000 > > @@ -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 *, struct parse_result *); > > > > struct imsgbuf *ibuf; > > +const struct output *output = &show_output; > > > > __dead void > > usage(void) > > @@ -145,10 +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) { > > ifidx = if_nametoindex(res->ifname); > > @@ -159,9 +129,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); > > break; > > @@ -194,9 +161,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); > > break; > > @@ -207,7 +171,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 +178,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 +217,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"); > > + /* no 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 +248,93 @@ 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 +358,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) > > { > > @@ -515,22 +371,13 @@ print_link(int state) > > #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) > > { > > - char *buf; > > - static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ > > - static int idx = 0; > > - unsigned int sec, min, hrs, day; > > - unsigned long long week; > > + char *buf; > > + static char tfbuf[TF_BUFS][TF_LEN];/* ring buffer */ > > + static int idx = 0; > > + unsigned int sec, min, hrs, day; > > + unsigned long long week; > > > > if (t == 0) > > return ("00:00:00"); > > @@ -598,108 +445,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 +470,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 +499,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 +516,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 +528,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 +559,18 @@ get_linkstate(uint8_t if_type, int link_ > > 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); > > -} > > Index: ospfctl.h > > =================================================================== > > RCS file: ospfctl.h > > diff -N ospfctl.h > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > +++ ospfctl.h 18 May 2020 07:45:40 -0000 > > @@ -0,0 +1,53 @@ > > +/* > > + * Copyright (c) 2005 Claudio Jeker <[email protected]> > > + * Copyright (c) 2004, 2005 Esben Norby <[email protected]> > > + * Copyright (c) 2003 Henning Brauer <[email protected]> > > + * > > + * 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); > > Index: output.c > > =================================================================== > > RCS file: output.c > > diff -N output.c > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > +++ output.c 18 May 2020 07:46:25 -0000 > > @@ -0,0 +1,669 @@ > > +/* > > + * Copyright (c) 2005 Claudio Jeker <[email protected]> > > + * Copyright (c) 2004, 2005 Esben Norby <[email protected]> > > + * Copyright (c) 2003 Henning Brauer <[email protected]> > > + * Copyright (c) 2020 Richard Chivers <[email protected]> > > + * > > + * 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); > > + 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 > > +}; > > > > -- > :wq Claudio
