1*91e3b0aeSnorby /* $OpenBSD: ospfctl.c,v 1.15 2005/05/22 20:01:47 norby Exp $ */ 2b49634deSclaudio 3b49634deSclaudio /* 4b49634deSclaudio * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 537355230Snorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6b49634deSclaudio * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 7b49634deSclaudio * 8b49634deSclaudio * Permission to use, copy, modify, and distribute this software for any 9b49634deSclaudio * purpose with or without fee is hereby granted, provided that the above 10b49634deSclaudio * copyright notice and this permission notice appear in all copies. 11b49634deSclaudio * 12b49634deSclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13b49634deSclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14b49634deSclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15b49634deSclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16b49634deSclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17b49634deSclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18b49634deSclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19b49634deSclaudio */ 20b49634deSclaudio 21b49634deSclaudio #include <sys/types.h> 22b49634deSclaudio #include <sys/socket.h> 23b49634deSclaudio #include <sys/un.h> 24b49634deSclaudio #include <netinet/in.h> 25b49634deSclaudio #include <arpa/inet.h> 26c47b7f65Sclaudio #include <net/if_media.h> 27c47b7f65Sclaudio #include <net/if_types.h> 28b49634deSclaudio 29b49634deSclaudio #include <err.h> 30b49634deSclaudio #include <stdio.h> 31b49634deSclaudio #include <stdlib.h> 32b49634deSclaudio #include <string.h> 33b49634deSclaudio #include <unistd.h> 34b49634deSclaudio 35b49634deSclaudio #include "ospf.h" 36b49634deSclaudio #include "ospfd.h" 37b49634deSclaudio #include "ospfe.h" 38b49634deSclaudio #include "parser.h" 39b49634deSclaudio #include "log.h" 40b49634deSclaudio 41cbb557dbShenning __dead void usage(void); 4259df52c7Snorby int show_summary_msg(struct imsg *); 43b49634deSclaudio int show_interface_msg(struct imsg *); 44b49634deSclaudio void print_baudrate(u_long); 45b49634deSclaudio const char *print_if_type(enum iface_type type); 46b49634deSclaudio const char *print_if_state(int); 47b49634deSclaudio const char *print_nbr_state(int); 48b49634deSclaudio const char *print_link(int); 49b49634deSclaudio const char *fmt_timeframe(time_t t); 50b49634deSclaudio const char *fmt_timeframe_core(time_t t); 51b49634deSclaudio const char *log_id(u_int32_t ); 52b49634deSclaudio const char *log_adv_rtr(u_int32_t); 53b49634deSclaudio void show_database_head(struct in_addr, u_int8_t); 54b49634deSclaudio int show_database_msg(struct imsg *); 5532286112Snorby char *print_ls_type(u_int8_t); 5632286112Snorby void show_db_hdr_msg_detail(struct lsa_hdr *); 5732286112Snorby char *print_rtr_link_type(u_int8_t); 5832286112Snorby const char *print_ospf_flags(u_int8_t); 5932286112Snorby int show_db_msg_detail(struct imsg *imsg); 60b49634deSclaudio int show_nbr_msg(struct imsg *); 61b49634deSclaudio const char *print_ospf_options(u_int8_t); 62b49634deSclaudio int show_nbr_detail_msg(struct imsg *); 6337355230Snorby int show_rib_msg(struct imsg *); 6437355230Snorby void show_rib_head(struct in_addr, u_int8_t, u_int8_t); 65*91e3b0aeSnorby const char *print_ospf_rtr_flags(u_int8_t); 6637355230Snorby int show_rib_detail_msg(struct imsg *); 67c47b7f65Sclaudio void show_fib_head(void); 68c47b7f65Sclaudio int show_fib_msg(struct imsg *); 69c47b7f65Sclaudio void show_interface_head(void); 70c47b7f65Sclaudio const char * get_media_descr(int); 71c47b7f65Sclaudio const char * get_linkstate(int, int); 72c47b7f65Sclaudio void print_baudrate(u_long); 73c47b7f65Sclaudio int show_fib_interface_msg(struct imsg *); 74b49634deSclaudio 75b49634deSclaudio struct imsgbuf *ibuf; 76b49634deSclaudio 77cbb557dbShenning __dead void 78b49634deSclaudio usage(void) 79b49634deSclaudio { 80b49634deSclaudio extern char *__progname; 81b49634deSclaudio 82b49634deSclaudio fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname); 83b49634deSclaudio exit(1); 84b49634deSclaudio } 85b49634deSclaudio 86b49634deSclaudio void 87b49634deSclaudio imsg_event_add(struct imsgbuf *i) 88b49634deSclaudio { 89b49634deSclaudio } 90b49634deSclaudio 91b49634deSclaudio int 92b49634deSclaudio main(int argc, char *argv[]) 93b49634deSclaudio { 94b49634deSclaudio struct sockaddr_un sun; 95b49634deSclaudio struct parse_result *res; 96b49634deSclaudio struct imsg imsg; 97b49634deSclaudio unsigned int ifidx = 0; 98b49634deSclaudio int ctl_sock; 99b49634deSclaudio int done = 0; 100b49634deSclaudio int n; 101b49634deSclaudio 102b49634deSclaudio /* parse options */ 103b49634deSclaudio if ((res = parse(argc - 1, argv + 1)) == NULL) 104b49634deSclaudio exit(1); 105b49634deSclaudio 106b49634deSclaudio /* connect to ospfd control socket */ 107b49634deSclaudio if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 108b49634deSclaudio err(1, "socket"); 109b49634deSclaudio 110b49634deSclaudio bzero(&sun, sizeof(sun)); 111b49634deSclaudio sun.sun_family = AF_UNIX; 112b49634deSclaudio strlcpy(sun.sun_path, OSPFD_SOCKET, sizeof(sun.sun_path)); 113b49634deSclaudio if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 114b49634deSclaudio err(1, "connect: %s", OSPFD_SOCKET); 115b49634deSclaudio 116b49634deSclaudio if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 117b49634deSclaudio fatal(NULL); 118b49634deSclaudio imsg_init(ibuf, ctl_sock, NULL); 119b49634deSclaudio done = 0; 120b49634deSclaudio 121b49634deSclaudio /* process user request */ 122b49634deSclaudio switch (res->action) { 123b49634deSclaudio case NONE: 124b49634deSclaudio usage(); 125b49634deSclaudio /* not reached */ 126b49634deSclaudio case SHOW: 12759df52c7Snorby case SHOW_SUM: 12859df52c7Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0); 129b49634deSclaudio break; 130b49634deSclaudio case SHOW_IFACE: 131b49634deSclaudio if (*res->ifname) { 132b49634deSclaudio ifidx = if_nametoindex(res->ifname); 133b49634deSclaudio if (ifidx == 0) 134b49634deSclaudio errx(1, "no such interface %s", res->ifname); 135b49634deSclaudio } 136b49634deSclaudio imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 137b49634deSclaudio &ifidx, sizeof(ifidx)); 138b49634deSclaudio break; 139b49634deSclaudio case SHOW_NBR: 14070d7d860Snorby printf("%-15s %-3s %-17s %-9s %-15s %s\n", "ID", "Pri", 14170d7d860Snorby "State", "DeadTime", "Address", "Interface"); 142b49634deSclaudio case SHOW_NBR_DTAIL: 143b49634deSclaudio imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 144b49634deSclaudio break; 145b49634deSclaudio case SHOW_DB: 146b49634deSclaudio imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0); 147b49634deSclaudio break; 148b49634deSclaudio case SHOW_DBBYAREA: 149b49634deSclaudio imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, 150b49634deSclaudio &res->addr, sizeof(res->addr)); 151b49634deSclaudio break; 15232286112Snorby case SHOW_DBEXT: 15332286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0); 15432286112Snorby break; 15532286112Snorby case SHOW_DBNET: 15632286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0); 15732286112Snorby break; 15832286112Snorby case SHOW_DBRTR: 15932286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0); 16032286112Snorby break; 16132286112Snorby case SHOW_DBSELF: 16232286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0); 16332286112Snorby break; 16432286112Snorby case SHOW_DBSUM: 16532286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0); 16632286112Snorby break; 16732286112Snorby case SHOW_DBASBR: 16832286112Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0); 16932286112Snorby break; 17037355230Snorby case SHOW_RIB: 17137355230Snorby printf("%-20s %-17s %-12s %-9s %-7s\n", "Destination", 17237355230Snorby "Nexthop", "Path Type", "Type", "Cost"); 17337355230Snorby case SHOW_RIB_DTAIL: 17437355230Snorby imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0); 17537355230Snorby break; 176c47b7f65Sclaudio case SHOW_FIB: 177c47b7f65Sclaudio if (!res->addr.s_addr) 178c47b7f65Sclaudio imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 179c47b7f65Sclaudio &res->flags, sizeof(res->flags)); 180c47b7f65Sclaudio else 181c47b7f65Sclaudio imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, 182c47b7f65Sclaudio &res->addr, sizeof(res->addr)); 183c47b7f65Sclaudio show_fib_head(); 184c47b7f65Sclaudio break; 185c47b7f65Sclaudio case SHOW_FIB_IFACE: 1864c561fb6Sclaudio if (*res->ifname) 1874c561fb6Sclaudio imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, 1884c561fb6Sclaudio res->ifname, sizeof(res->ifname)); 1894c561fb6Sclaudio else 190c47b7f65Sclaudio imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 191c47b7f65Sclaudio show_interface_head(); 192c47b7f65Sclaudio break; 193b49634deSclaudio case RELOAD: 194b49634deSclaudio imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 195b49634deSclaudio printf("reload request sent.\n"); 196b49634deSclaudio done = 1; 197b49634deSclaudio break; 198b49634deSclaudio } 199b49634deSclaudio 200b49634deSclaudio while (ibuf->w.queued) 201b49634deSclaudio if (msgbuf_write(&ibuf->w) < 0) 202b49634deSclaudio err(1, "write error"); 203b49634deSclaudio 204b49634deSclaudio while (!done) { 205b49634deSclaudio if ((n = imsg_read(ibuf)) == -1) 206b49634deSclaudio errx(1, "imsg_read error"); 207b49634deSclaudio if (n == 0) 208b49634deSclaudio errx(1, "pipe closed"); 209b49634deSclaudio 210b49634deSclaudio while (!done) { 211b49634deSclaudio if ((n = imsg_get(ibuf, &imsg)) == -1) 212b49634deSclaudio errx(1, "imsg_get error"); 213b49634deSclaudio if (n == 0) 214b49634deSclaudio break; 215b49634deSclaudio switch (res->action) { 216b49634deSclaudio case SHOW: 21759df52c7Snorby case SHOW_SUM: 21859df52c7Snorby done = show_summary_msg(&imsg); 219b49634deSclaudio break; 220b49634deSclaudio case SHOW_IFACE: 221b49634deSclaudio done = show_interface_msg(&imsg); 222b49634deSclaudio break; 223b49634deSclaudio case SHOW_NBR: 224b49634deSclaudio done = show_nbr_msg(&imsg); 225b49634deSclaudio break; 226b49634deSclaudio case SHOW_NBR_DTAIL: 227b49634deSclaudio done = show_nbr_detail_msg(&imsg); 228b49634deSclaudio break; 229b49634deSclaudio case SHOW_DB: 230b49634deSclaudio case SHOW_DBBYAREA: 23132286112Snorby case SHOW_DBSELF: 232b49634deSclaudio done = show_database_msg(&imsg); 233b49634deSclaudio break; 23432286112Snorby case SHOW_DBEXT: 23532286112Snorby case SHOW_DBNET: 23632286112Snorby case SHOW_DBRTR: 23732286112Snorby case SHOW_DBSUM: 23832286112Snorby case SHOW_DBASBR: 23932286112Snorby done = show_db_msg_detail(&imsg); 24032286112Snorby break; 24137355230Snorby case SHOW_RIB: 24237355230Snorby done = show_rib_msg(&imsg); 24337355230Snorby break; 24437355230Snorby case SHOW_RIB_DTAIL: 24537355230Snorby done = show_rib_detail_msg(&imsg); 24637355230Snorby break; 247c47b7f65Sclaudio case SHOW_FIB: 248c47b7f65Sclaudio done = show_fib_msg(&imsg); 249c47b7f65Sclaudio break; 250c47b7f65Sclaudio case SHOW_FIB_IFACE: 251c47b7f65Sclaudio done = show_fib_interface_msg(&imsg); 252c47b7f65Sclaudio break; 253b49634deSclaudio case NONE: 254b49634deSclaudio case RELOAD: 255b49634deSclaudio break; 256b49634deSclaudio } 257b49634deSclaudio imsg_free(&imsg); 258b49634deSclaudio } 259b49634deSclaudio } 260b49634deSclaudio close(ctl_sock); 261b49634deSclaudio free(ibuf); 262b49634deSclaudio 263b49634deSclaudio return (0); 264b49634deSclaudio } 265b49634deSclaudio 266b49634deSclaudio int 26759df52c7Snorby show_summary_msg(struct imsg *imsg) 268b49634deSclaudio { 26959df52c7Snorby struct ctl_sum *sum; 27059df52c7Snorby struct ctl_sum_area *sumarea; 27159df52c7Snorby 27259df52c7Snorby switch (imsg->hdr.type) { 27359df52c7Snorby case IMSG_CTL_SHOW_SUM: 27459df52c7Snorby sum = imsg->data; 27559df52c7Snorby printf("Router ID: %s\n", inet_ntoa(sum->rtr_id)); 27659df52c7Snorby printf("RFC1583 compatibility flag is "); 27759df52c7Snorby if (sum->rfc1583compat) 27859df52c7Snorby printf("enabled\n"); 27959df52c7Snorby else 28059df52c7Snorby printf("disabled\n"); 28159df52c7Snorby 28259df52c7Snorby printf("SPF delay is %d sec(s), hold time between two SPFs " 28359df52c7Snorby "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time); 28459df52c7Snorby printf("Number of external LSA(s) %d\n", sum->num_ext_lsa); 28559df52c7Snorby printf("Number of areas attached to this router: %d\n", 28659df52c7Snorby sum->num_area); 28759df52c7Snorby break; 28859df52c7Snorby case IMSG_CTL_SHOW_SUM_AREA: 28959df52c7Snorby sumarea = imsg->data; 29059df52c7Snorby printf("\nArea ID: %s\n", inet_ntoa(sumarea->area)); 29159df52c7Snorby printf(" Number of interfaces in this area: %d\n", 29259df52c7Snorby sumarea->num_iface); 29359df52c7Snorby printf(" Number of fully adjacent neighbors in this " 29459df52c7Snorby "area: %d\n", sumarea->num_adj_nbr); 29559df52c7Snorby printf(" SPF algorithm executed %d time(s)\n", 29659df52c7Snorby sumarea->num_spf_calc); 29759df52c7Snorby printf(" Number LSA(s) %d\n", sumarea->num_lsa); 29859df52c7Snorby break; 29959df52c7Snorby case IMSG_CTL_END: 30059df52c7Snorby printf("\n"); 30159df52c7Snorby return (1); 30259df52c7Snorby default: 30359df52c7Snorby break; 30459df52c7Snorby } 305b49634deSclaudio 306b49634deSclaudio return (0); 307b49634deSclaudio } 308b49634deSclaudio 309b49634deSclaudio int 310b49634deSclaudio show_interface_msg(struct imsg *imsg) 311b49634deSclaudio { 312b49634deSclaudio struct ctl_iface *iface; 313b49634deSclaudio 314b49634deSclaudio switch (imsg->hdr.type) { 315b49634deSclaudio case IMSG_CTL_SHOW_INTERFACE: 316b49634deSclaudio iface = imsg->data; 317b49634deSclaudio printf("\n"); 318b49634deSclaudio printf("Interface %s is %d, line protocol is %s\n", 319b49634deSclaudio iface->name, iface->linkstate, print_link(iface->flags)); 320b49634deSclaudio printf(" Internet address %s/%d, ", 321b49634deSclaudio inet_ntoa(iface->addr), 3223ec0d80eSclaudio mask2prefixlen(iface->mask.s_addr)); 323b49634deSclaudio printf("Area %s\n", inet_ntoa(iface->area)); 324b49634deSclaudio printf(" Router ID %s, network type %s, cost: %d\n", 325b49634deSclaudio inet_ntoa(iface->rtr_id), 326b49634deSclaudio print_if_type(iface->type), iface->metric); 32759df52c7Snorby printf(" Transmit delay is %d sec(s), state %s, priority %d\n", 3281d3a1c7dSnorby iface->transmit_delay, print_if_state(iface->state), 329b49634deSclaudio iface->priority); 330b49634deSclaudio printf(" Designated Router (ID) %s, ", 331b49634deSclaudio inet_ntoa(iface->dr_id)); 332b49634deSclaudio printf("interface address %s\n", inet_ntoa(iface->dr_addr)); 333b49634deSclaudio printf(" Backup Designated Router (ID) %s, ", 334b49634deSclaudio inet_ntoa(iface->bdr_id)); 335b49634deSclaudio printf("interface address %s\n", inet_ntoa(iface->bdr_addr)); 336b49634deSclaudio printf(" Timer intervals configured, " 337b49634deSclaudio "hello %d, dead %d, wait %d, retransmit %d\n", 338b49634deSclaudio iface->hello_interval, iface->dead_interval, 339b49634deSclaudio iface->dead_interval, iface->rxmt_interval); 340b49634deSclaudio if (iface->hello_timer < 0) 341b49634deSclaudio printf(" Hello timer not running\n"); 342b49634deSclaudio else 343b49634deSclaudio printf(" Hello timer due in %s\n", 344b49634deSclaudio fmt_timeframe_core(iface->hello_timer)); 345b49634deSclaudio printf(" Neighbor count is %d, adjacent neighbor count is " 346b49634deSclaudio "%d\n", iface->nbr_cnt, iface->adj_cnt); 347b49634deSclaudio break; 348b49634deSclaudio case IMSG_CTL_END: 349b49634deSclaudio printf("\n"); 350b49634deSclaudio return (1); 351b49634deSclaudio default: 352b49634deSclaudio break; 353b49634deSclaudio } 354b49634deSclaudio 355b49634deSclaudio return (0); 356b49634deSclaudio } 357b49634deSclaudio 358b49634deSclaudio const char * 359b49634deSclaudio print_if_type(enum iface_type type) 360b49634deSclaudio { 361b49634deSclaudio switch (type) { 362b49634deSclaudio case IF_TYPE_POINTOPOINT: 363b49634deSclaudio return ("POINTOPOINT"); 364b49634deSclaudio case IF_TYPE_BROADCAST: 365b49634deSclaudio return ("BROADCAST"); 366b49634deSclaudio case IF_TYPE_NBMA: 367b49634deSclaudio return ("NBMA"); 368b49634deSclaudio case IF_TYPE_POINTOMULTIPOINT: 369b49634deSclaudio return ("POINTOMULTIPOINT"); 370b49634deSclaudio case IF_TYPE_VIRTUALLINK: 371b49634deSclaudio return ("VIRTUALLINK"); 372b49634deSclaudio default: 373b49634deSclaudio return ("UNKNOWN"); 374b49634deSclaudio } 375b49634deSclaudio } 376b49634deSclaudio 377b49634deSclaudio const char * 378b49634deSclaudio print_if_state(int state) 379b49634deSclaudio { 380b49634deSclaudio switch (state) { 381b49634deSclaudio case IF_STA_DOWN: 382b49634deSclaudio return ("DOWN"); 383b49634deSclaudio case IF_STA_LOOPBACK: 384b49634deSclaudio return ("LOOPBACK"); 385b49634deSclaudio case IF_STA_WAITING: 386b49634deSclaudio return ("WAITING"); 387b49634deSclaudio case IF_STA_POINTTOPOINT: 388b49634deSclaudio return ("P2P"); 389b49634deSclaudio case IF_STA_DROTHER: 390b49634deSclaudio return ("DROTHER"); 391b49634deSclaudio case IF_STA_BACKUP: 392b49634deSclaudio return ("BACKUP"); 393b49634deSclaudio case IF_STA_DR: 394b49634deSclaudio return ("DR"); 395b49634deSclaudio default: 396b49634deSclaudio return ("UNKNOWN"); 397b49634deSclaudio } 398b49634deSclaudio } 399b49634deSclaudio 400b49634deSclaudio const char * 401b49634deSclaudio print_nbr_state(int state) 402b49634deSclaudio { 403b49634deSclaudio switch (state) { 404b49634deSclaudio case NBR_STA_DOWN: 405b49634deSclaudio return ("DOWN"); 406b49634deSclaudio case NBR_STA_ATTEMPT: 407b49634deSclaudio return ("ATTEMPT"); 408b49634deSclaudio case NBR_STA_INIT: 409b49634deSclaudio return ("INIT"); 410b49634deSclaudio case NBR_STA_2_WAY: 411b49634deSclaudio return ("2-WAY"); 412b49634deSclaudio case NBR_STA_XSTRT: 413b49634deSclaudio return ("EXSTART"); 414b49634deSclaudio case NBR_STA_SNAP: 415b49634deSclaudio return ("SNAPSHOT"); 416b49634deSclaudio case NBR_STA_XCHNG: 417b49634deSclaudio return ("EXCHANGE"); 418b49634deSclaudio case NBR_STA_LOAD: 419b49634deSclaudio return ("LOADING"); 420b49634deSclaudio case NBR_STA_FULL: 421b49634deSclaudio return ("FULL"); 422b49634deSclaudio default: 423b49634deSclaudio return ("UNKNOWN"); 424b49634deSclaudio } 425b49634deSclaudio } 426b49634deSclaudio 427b49634deSclaudio const char * 428b49634deSclaudio print_link(int state) 429b49634deSclaudio { 430b49634deSclaudio if (state & IFF_UP) 431b49634deSclaudio return ("UP"); 432b49634deSclaudio else 433b49634deSclaudio return ("DOWN"); 434b49634deSclaudio } 435b49634deSclaudio 436b49634deSclaudio #define TF_BUFS 8 437b49634deSclaudio #define TF_LEN 9 438b49634deSclaudio 439b49634deSclaudio const char * 440b49634deSclaudio fmt_timeframe(time_t t) 441b49634deSclaudio { 442b49634deSclaudio if (t == 0) 443b49634deSclaudio return ("Never"); 444b49634deSclaudio else 445b49634deSclaudio return (fmt_timeframe_core(time(NULL) - t)); 446b49634deSclaudio } 447b49634deSclaudio 448b49634deSclaudio const char * 449b49634deSclaudio fmt_timeframe_core(time_t t) 450b49634deSclaudio { 451b49634deSclaudio char *buf; 452b49634deSclaudio static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 453b49634deSclaudio static int idx = 0; 454b49634deSclaudio unsigned sec, min, hrs, day, week; 455b49634deSclaudio 456b49634deSclaudio if (t == 0) 457b49634deSclaudio return ("Stopped"); 458b49634deSclaudio 459b49634deSclaudio buf = tfbuf[idx++]; 460b49634deSclaudio if (idx == TF_BUFS) 461b49634deSclaudio idx = 0; 462b49634deSclaudio 463b49634deSclaudio week = t; 464b49634deSclaudio 465b49634deSclaudio sec = week % 60; 466b49634deSclaudio week /= 60; 467b49634deSclaudio min = week % 60; 468b49634deSclaudio week /= 60; 469b49634deSclaudio hrs = week % 24; 470b49634deSclaudio week /= 24; 471b49634deSclaudio day = week % 7; 472b49634deSclaudio week /= 7; 473b49634deSclaudio 474b49634deSclaudio if (week > 0) 475b49634deSclaudio snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 476b49634deSclaudio else if (day > 0) 477b49634deSclaudio snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 478b49634deSclaudio else 479b49634deSclaudio snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 480b49634deSclaudio 481b49634deSclaudio return (buf); 482b49634deSclaudio } 483b49634deSclaudio 484b49634deSclaudio const char * 485b49634deSclaudio log_id(u_int32_t id) 486b49634deSclaudio { 487b49634deSclaudio static char buf[48]; 488b49634deSclaudio struct in_addr addr; 489b49634deSclaudio 490b49634deSclaudio addr.s_addr = id; 491b49634deSclaudio 492b49634deSclaudio if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 493b49634deSclaudio return ("?"); 494b49634deSclaudio else 495b49634deSclaudio return (buf); 496b49634deSclaudio } 497b49634deSclaudio 498b49634deSclaudio const char * 499b49634deSclaudio log_adv_rtr(u_int32_t adv_rtr) 500b49634deSclaudio { 501b49634deSclaudio static char buf[48]; 502b49634deSclaudio struct in_addr addr; 503b49634deSclaudio 504b49634deSclaudio addr.s_addr = adv_rtr; 505b49634deSclaudio 506b49634deSclaudio if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL) 507b49634deSclaudio return ("?"); 508b49634deSclaudio else 509b49634deSclaudio return (buf); 510b49634deSclaudio } 511b49634deSclaudio 5123ec0d80eSclaudio /* prototype defined in ospfd.h and shared with the kroute.c version */ 513b49634deSclaudio u_int8_t 5143ec0d80eSclaudio mask2prefixlen(in_addr_t ina) 515b49634deSclaudio { 5163ec0d80eSclaudio if (ina == 0) 517b49634deSclaudio return (0); 518b49634deSclaudio else 5193ec0d80eSclaudio return (33 - ffs(ntohl(ina))); 520b49634deSclaudio } 521b49634deSclaudio 522b49634deSclaudio void 523b49634deSclaudio show_database_head(struct in_addr aid, u_int8_t type) 524b49634deSclaudio { 525b49634deSclaudio char *header, *format; 526b49634deSclaudio 527b49634deSclaudio switch (type) { 528b49634deSclaudio case LSA_TYPE_ROUTER: 529b49634deSclaudio format = "Router Link States"; 530b49634deSclaudio break; 531b49634deSclaudio case LSA_TYPE_NETWORK: 532b49634deSclaudio format = "Net Link States"; 533b49634deSclaudio break; 534b49634deSclaudio case LSA_TYPE_SUM_NETWORK: 535b49634deSclaudio format = "Summary Net Link States"; 536b49634deSclaudio break; 537b49634deSclaudio case LSA_TYPE_SUM_ROUTER: 538b49634deSclaudio format = "Summary Router Link States"; 539b49634deSclaudio break; 540b49634deSclaudio case LSA_TYPE_EXTERNAL: 541b49634deSclaudio format = NULL; 542b49634deSclaudio if ((header = strdup("Type-5 AS External Link States")) == NULL) 543b49634deSclaudio err(1, NULL); 544b49634deSclaudio break; 545b49634deSclaudio default: 546b49634deSclaudio errx(1, "unknown LSA type"); 547b49634deSclaudio } 548b49634deSclaudio if (type != LSA_TYPE_EXTERNAL) 549b49634deSclaudio if (asprintf(&header, "%s (Area %s)", format, 550b49634deSclaudio inet_ntoa(aid)) == -1) 551b49634deSclaudio err(1, NULL); 552b49634deSclaudio 55332286112Snorby printf("\n%-15s %s\n\n", "", header); 554b49634deSclaudio free(header); 555b49634deSclaudio } 556b49634deSclaudio 557b49634deSclaudio int 558b49634deSclaudio show_database_msg(struct imsg *imsg) 559b49634deSclaudio { 560b49634deSclaudio static struct in_addr area_id; 561b49634deSclaudio static u_int8_t lasttype; 562b49634deSclaudio struct area *area; 563b49634deSclaudio struct lsa_hdr *lsa; 564b49634deSclaudio 565b49634deSclaudio switch (imsg->hdr.type) { 566b49634deSclaudio case IMSG_CTL_SHOW_DATABASE: 56732286112Snorby case IMSG_CTL_SHOW_DB_SELF: 568b49634deSclaudio lsa = imsg->data; 56932286112Snorby if (lsa->type != lasttype) { 570b49634deSclaudio show_database_head(area_id, lsa->type); 57132286112Snorby printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID", 57232286112Snorby "Adv Router", "Age", "Seq#", "Checksum"); 57332286112Snorby } 574b49634deSclaudio printf("%-15s %-15s %-4d 0x%08x 0x%04x\n", 575b49634deSclaudio log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr), 576b49634deSclaudio ntohs(lsa->age), ntohl(lsa->seq_num), 577b49634deSclaudio ntohs(lsa->ls_chksum)); 578b49634deSclaudio lasttype = lsa->type; 579b49634deSclaudio break; 580b49634deSclaudio case IMSG_CTL_AREA: 581b49634deSclaudio area = imsg->data; 582b49634deSclaudio area_id = area->id; 58343dbf367Snorby lasttype = 0; 584b49634deSclaudio break; 585b49634deSclaudio case IMSG_CTL_END: 58632286112Snorby printf("\n"); 58732286112Snorby return (1); 58832286112Snorby default: 58932286112Snorby break; 59032286112Snorby } 59132286112Snorby 59232286112Snorby return (0); 59332286112Snorby } 59432286112Snorby 59532286112Snorby char * 59632286112Snorby print_ls_type(u_int8_t type) 59732286112Snorby { 59832286112Snorby switch (type) { 59932286112Snorby case LSA_TYPE_ROUTER: 60032286112Snorby return ("Router"); 60132286112Snorby case LSA_TYPE_NETWORK: 60232286112Snorby return ("Network"); 60332286112Snorby case LSA_TYPE_SUM_NETWORK: 60432286112Snorby return ("Summary (Network)"); 60532286112Snorby case LSA_TYPE_SUM_ROUTER: 60632286112Snorby return ("Summary (Router)"); 60732286112Snorby case LSA_TYPE_EXTERNAL: 60832286112Snorby return ("AS External"); 60932286112Snorby default: 61032286112Snorby return ("Unknown"); 61132286112Snorby } 61232286112Snorby } 61332286112Snorby 61432286112Snorby void 61532286112Snorby show_db_hdr_msg_detail(struct lsa_hdr *lsa) 61632286112Snorby { 61732286112Snorby printf("LS age: %d\n", ntohs(lsa->age)); 61832286112Snorby printf("Options: %s\n", print_ospf_options(lsa->opts)); 61932286112Snorby printf("LS Type: %s\n", print_ls_type(lsa->type)); 62032286112Snorby 62132286112Snorby switch (lsa->type) { 62232286112Snorby case LSA_TYPE_ROUTER: 62332286112Snorby printf("Link State ID: %s\n", log_id(lsa->ls_id)); 62432286112Snorby break; 62532286112Snorby case LSA_TYPE_NETWORK: 62632286112Snorby printf("Link State ID: %s (address of Designated Router)\n", 62732286112Snorby log_id(lsa->ls_id)); 62832286112Snorby break; 62932286112Snorby case LSA_TYPE_SUM_NETWORK: 63032286112Snorby printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id)); 63132286112Snorby break; 63232286112Snorby case LSA_TYPE_SUM_ROUTER: 63332286112Snorby printf("Link State ID: %s (ASBR Router ID)\n", 63432286112Snorby log_id(lsa->ls_id)); 63532286112Snorby break; 63632286112Snorby case LSA_TYPE_EXTERNAL: 63732286112Snorby printf("Link State ID: %s (External Network Number)\n", 63832286112Snorby log_id(lsa->ls_id)); 63932286112Snorby break; 64032286112Snorby } 64132286112Snorby 64232286112Snorby printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr)); 64332286112Snorby printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num)); 64432286112Snorby printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum)); 64532286112Snorby printf("Length: %d\n", ntohs(lsa->len)); 64632286112Snorby } 64732286112Snorby 64832286112Snorby char * 64932286112Snorby print_rtr_link_type(u_int8_t type) 65032286112Snorby { 65132286112Snorby switch (type) { 65232286112Snorby case LINK_TYPE_POINTTOPOINT: 65332286112Snorby return ("Point-to-Point"); 65432286112Snorby case LINK_TYPE_TRANSIT_NET: 65532286112Snorby return ("Transit Network"); 65632286112Snorby case LINK_TYPE_STUB_NET: 65732286112Snorby return ("Stub Network"); 65832286112Snorby case LINK_TYPE_VIRTUAL: 65932286112Snorby return ("Virtual Link"); 66032286112Snorby default: 66132286112Snorby return ("Unknown"); 66232286112Snorby } 66332286112Snorby } 66432286112Snorby 66532286112Snorby const char * 66632286112Snorby print_ospf_flags(u_int8_t opts) 66732286112Snorby { 66832286112Snorby static char optbuf[32]; 66932286112Snorby 67032286112Snorby snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s", 67132286112Snorby opts & OSPF_RTR_V ? "V" : "-", 67232286112Snorby opts & OSPF_RTR_E ? "E" : "-", 67332286112Snorby opts & OSPF_RTR_B ? "B" : "-"); 67432286112Snorby return (optbuf); 67532286112Snorby } 67632286112Snorby 67732286112Snorby int 67832286112Snorby show_db_msg_detail(struct imsg *imsg) 67932286112Snorby { 68032286112Snorby static struct in_addr area_id; 68132286112Snorby static u_int8_t lasttype; 68232286112Snorby struct in_addr addr, data; 68332286112Snorby struct area *area; 68432286112Snorby struct lsa *lsa; 68532286112Snorby struct lsa_rtr_link *rtr_link; 68632286112Snorby struct lsa_asext *asext; 68732286112Snorby u_int16_t i, nlinks, off; 68832286112Snorby 68932286112Snorby /* XXX sanity checks! */ 69032286112Snorby 69132286112Snorby switch (imsg->hdr.type) { 69232286112Snorby case IMSG_CTL_SHOW_DB_EXT: 69332286112Snorby lsa = imsg->data; 69432286112Snorby if (lsa->hdr.type != lasttype) 69532286112Snorby show_database_head(area_id, lsa->hdr.type); 69632286112Snorby show_db_hdr_msg_detail(&lsa->hdr); 69732286112Snorby addr.s_addr = lsa->data.asext.mask; 69832286112Snorby printf("Network Mask: %s\n", inet_ntoa(addr)); 69932286112Snorby 70032286112Snorby asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr)); 70132286112Snorby 70232286112Snorby printf(" Metric type: "); 70332286112Snorby if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG) 70432286112Snorby printf("2\n"); 70532286112Snorby else 70632286112Snorby printf("1\n"); 70732286112Snorby printf(" Metric: %d\n", ntohl(asext->metric) 70832286112Snorby & LSA_METRIC_MASK); 70932286112Snorby addr.s_addr = asext->fw_addr; 71032286112Snorby printf(" Forwarding Address: %s\n", inet_ntoa(addr)); 71132286112Snorby printf(" External Route Tag: %d\n\n", ntohl(asext->ext_tag)); 71232286112Snorby 71332286112Snorby lasttype = lsa->hdr.type; 71432286112Snorby break; 71532286112Snorby case IMSG_CTL_SHOW_DB_NET: 71632286112Snorby lsa = imsg->data; 71732286112Snorby if (lsa->hdr.type != lasttype) 71832286112Snorby show_database_head(area_id, lsa->hdr.type); 71932286112Snorby show_db_hdr_msg_detail(&lsa->hdr); 72032286112Snorby addr.s_addr = lsa->data.net.mask; 72132286112Snorby printf("Network Mask: %s\n", inet_ntoa(addr)); 72232286112Snorby 72332286112Snorby nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr) 72432286112Snorby - sizeof(u_int32_t)) / sizeof(struct lsa_net_link); 72532286112Snorby off = sizeof(lsa->hdr) + sizeof(u_int32_t); 72632286112Snorby 72732286112Snorby for (i = 0; i < nlinks; i++) { 72832286112Snorby addr.s_addr = lsa->data.net.att_rtr[i]; 72932286112Snorby printf(" Attached Router: %s\n", inet_ntoa(addr)); 73032286112Snorby } 73132286112Snorby 73232286112Snorby printf("\n"); 73332286112Snorby lasttype = lsa->hdr.type; 73432286112Snorby break; 73532286112Snorby case IMSG_CTL_SHOW_DB_RTR: 73632286112Snorby lsa = imsg->data; 73732286112Snorby if (lsa->hdr.type != lasttype) 73832286112Snorby show_database_head(area_id, lsa->hdr.type); 73932286112Snorby show_db_hdr_msg_detail(&lsa->hdr); 74032286112Snorby printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags)); 74132286112Snorby nlinks = ntohs(lsa->data.rtr.nlinks); 74232286112Snorby printf("Number of Links: %d\n\n", nlinks); 74332286112Snorby 74432286112Snorby off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 74532286112Snorby 74632286112Snorby for (i = 0; i < nlinks; i++) { 74732286112Snorby rtr_link = (struct lsa_rtr_link *)((char *)lsa + off); 74832286112Snorby 74932286112Snorby printf(" Link connected to: %s\n", 75032286112Snorby print_rtr_link_type(rtr_link->type)); 75132286112Snorby 75232286112Snorby addr.s_addr = rtr_link->id; 75332286112Snorby data.s_addr = rtr_link->data; 75432286112Snorby 75532286112Snorby switch (rtr_link->type) { 75632286112Snorby case LINK_TYPE_POINTTOPOINT: 75732286112Snorby case LINK_TYPE_VIRTUAL: 75832286112Snorby printf(" Link ID (Neighbors Router ID):" 75932286112Snorby " %s\n", inet_ntoa(addr)); 76032286112Snorby printf(" Link Data (Router Interface " 76132286112Snorby "address): %s\n", inet_ntoa(data)); 76232286112Snorby break; 76332286112Snorby case LINK_TYPE_TRANSIT_NET: 76432286112Snorby printf(" Link ID (Designated Router " 76532286112Snorby "address): %s\n", inet_ntoa(addr)); 76632286112Snorby printf(" Link Data (Router Interface " 76732286112Snorby "address): %s\n", inet_ntoa(data)); 76832286112Snorby break; 76932286112Snorby case LINK_TYPE_STUB_NET: 77032286112Snorby printf(" Link ID (Network ID): %s\n", 77132286112Snorby inet_ntoa(addr)); 77232286112Snorby printf(" Link Data (Network Mask): %s\n", 77332286112Snorby inet_ntoa(data)); 77432286112Snorby break; 77532286112Snorby default: 77632286112Snorby printf(" Link ID (Unknown): %s\n", 77732286112Snorby inet_ntoa(addr)); 77832286112Snorby printf(" Link Data (Unknown): %s\n", 77932286112Snorby inet_ntoa(data)); 78032286112Snorby break; 78132286112Snorby } 78232286112Snorby 78332286112Snorby printf(" Metric: %d\n\n", ntohs(rtr_link->metric)); 78432286112Snorby 78532286112Snorby off += sizeof(struct lsa_rtr_link) + 78632286112Snorby rtr_link->num_tos * sizeof(u_int32_t); 78732286112Snorby } 78832286112Snorby 78932286112Snorby lasttype = lsa->hdr.type; 79032286112Snorby break; 79132286112Snorby case IMSG_CTL_SHOW_DB_SUM: 79232286112Snorby case IMSG_CTL_SHOW_DB_ASBR: 79332286112Snorby lsa = imsg->data; 79432286112Snorby if (lsa->hdr.type != lasttype) 79532286112Snorby show_database_head(area_id, lsa->hdr.type); 79632286112Snorby show_db_hdr_msg_detail(&lsa->hdr); 79732286112Snorby addr.s_addr = lsa->data.sum.mask; 79832286112Snorby printf("Network Mask: %s\n", inet_ntoa(addr)); 79932286112Snorby printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) & 80032286112Snorby LSA_METRIC_MASK); 80132286112Snorby lasttype = lsa->hdr.type; 80232286112Snorby break; 80332286112Snorby case IMSG_CTL_AREA: 80432286112Snorby area = imsg->data; 80532286112Snorby area_id = area->id; 80632286112Snorby break; 80732286112Snorby case IMSG_CTL_END: 808b49634deSclaudio return (1); 809b49634deSclaudio default: 810b49634deSclaudio break; 811b49634deSclaudio } 812b49634deSclaudio 813b49634deSclaudio return (0); 814b49634deSclaudio } 815b49634deSclaudio 816b49634deSclaudio int 817b49634deSclaudio show_nbr_msg(struct imsg *imsg) 818b49634deSclaudio { 819b49634deSclaudio struct ctl_nbr *nbr; 820b49634deSclaudio char *state; 821b49634deSclaudio 822b49634deSclaudio switch (imsg->hdr.type) { 823b49634deSclaudio case IMSG_CTL_SHOW_NBR: 824b49634deSclaudio nbr = imsg->data; 825b49634deSclaudio if (asprintf(&state, "%s/%s", print_nbr_state(nbr->nbr_state), 826b49634deSclaudio print_if_state(nbr->iface_state)) == -1) 827b49634deSclaudio err(1, NULL); 828b49634deSclaudio printf("%-15s %-3d %-17s %-9s ", inet_ntoa(nbr->id), 829b49634deSclaudio nbr->priority, state, fmt_timeframe_core(nbr->dead_timer)); 830b49634deSclaudio printf("%-15s %s\n", inet_ntoa(nbr->addr), nbr->name); 831b49634deSclaudio free(state); 832b49634deSclaudio break; 833b49634deSclaudio case IMSG_CTL_END: 834b49634deSclaudio printf("\n"); 835b49634deSclaudio return (1); 836b49634deSclaudio default: 837b49634deSclaudio break; 838b49634deSclaudio } 839b49634deSclaudio 840b49634deSclaudio return (0); 841b49634deSclaudio } 842b49634deSclaudio 843b49634deSclaudio const char * 844b49634deSclaudio print_ospf_options(u_int8_t opts) 845b49634deSclaudio { 846b49634deSclaudio static char optbuf[32]; 847b49634deSclaudio 848b49634deSclaudio snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|*", 849b49634deSclaudio opts & OSPF_OPTION_DC ? "DC" : "-", 850b49634deSclaudio opts & OSPF_OPTION_EA ? "EA" : "-", 851b49634deSclaudio opts & OSPF_OPTION_NP ? "N/P" : "-", 852b49634deSclaudio opts & OSPF_OPTION_MC ? "MC" : "-", 853b49634deSclaudio opts & OSPF_OPTION_E ? "E" : "-"); 854b49634deSclaudio return (optbuf); 855b49634deSclaudio } 856b49634deSclaudio 857b49634deSclaudio int 858b49634deSclaudio show_nbr_detail_msg(struct imsg *imsg) 859b49634deSclaudio { 860b49634deSclaudio struct ctl_nbr *nbr; 861b49634deSclaudio 862b49634deSclaudio switch (imsg->hdr.type) { 863b49634deSclaudio case IMSG_CTL_SHOW_NBR: 864b49634deSclaudio nbr = imsg->data; 865b49634deSclaudio printf("\nNeighbor %s, ", inet_ntoa(nbr->id)); 866b49634deSclaudio printf("interface address %s\n", inet_ntoa(nbr->addr)); 867b49634deSclaudio printf(" In the area %s via interface %s\n", 868b49634deSclaudio inet_ntoa(nbr->area), nbr->name); 869b49634deSclaudio printf(" Neighbor priority is %d, " 870b49634deSclaudio "State is %s, %d state changes\n", 871b49634deSclaudio nbr->priority, print_nbr_state(nbr->nbr_state), 872b49634deSclaudio nbr->state_chng_cnt); 873b49634deSclaudio printf(" DR is %s, ", inet_ntoa(nbr->dr)); 874b49634deSclaudio printf("BDR is %s\n", inet_ntoa(nbr->bdr)); 875b49634deSclaudio printf(" Options is 0x%x %s\n", nbr->options, 876b49634deSclaudio print_ospf_options(nbr->options)); 877b49634deSclaudio printf(" Dead timer due in %s\n", 878b49634deSclaudio fmt_timeframe_core(nbr->dead_timer)); 879b49634deSclaudio printf(" Database Summary List %d\n", nbr->db_sum_lst_cnt); 880b49634deSclaudio printf(" Link State Request List %d\n", nbr->ls_req_lst_cnt); 881b49634deSclaudio printf(" Link State Retransmission List %d\n", 882b49634deSclaudio nbr->ls_retrans_lst_cnt); 883b49634deSclaudio break; 884b49634deSclaudio case IMSG_CTL_END: 885b49634deSclaudio printf("\n"); 886b49634deSclaudio return (1); 887b49634deSclaudio default: 888b49634deSclaudio break; 889b49634deSclaudio } 890b49634deSclaudio 891b49634deSclaudio return (0); 892b49634deSclaudio } 89337355230Snorby 89437355230Snorby int 89537355230Snorby show_rib_msg(struct imsg *imsg) 89637355230Snorby { 89737355230Snorby struct ctl_rt *rt; 89837355230Snorby char *dstnet; 89937355230Snorby 90037355230Snorby switch (imsg->hdr.type) { 90137355230Snorby case IMSG_CTL_SHOW_RIB: 90237355230Snorby rt = imsg->data; 90337355230Snorby switch (rt->d_type) { 90437355230Snorby case DT_NET: 90537355230Snorby if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 90637355230Snorby rt->prefixlen) == -1) 90737355230Snorby err(1, NULL); 90837355230Snorby break; 90937355230Snorby case DT_RTR: 91037355230Snorby if (asprintf(&dstnet, "%s", 91137355230Snorby inet_ntoa(rt->prefix)) == -1) 91237355230Snorby err(1, NULL); 91337355230Snorby break; 91437355230Snorby default: 91537355230Snorby errx(1, "Invalid route type"); 91637355230Snorby } 91737355230Snorby 91837355230Snorby printf("%-20s %-17s %-12s %-9s %-7d\n", dstnet, 91937355230Snorby inet_ntoa(rt->nexthop), path_type_names[rt->p_type], 92037355230Snorby dst_type_names[rt->d_type], rt->cost); 92137355230Snorby free(dstnet); 92237355230Snorby break; 92337355230Snorby case IMSG_CTL_END: 92437355230Snorby printf("\n"); 92537355230Snorby return (1); 92637355230Snorby default: 92737355230Snorby break; 92837355230Snorby } 92937355230Snorby 93037355230Snorby return (0); 93137355230Snorby } 93237355230Snorby 93337355230Snorby void 93437355230Snorby show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type) 93537355230Snorby { 936*91e3b0aeSnorby char *header, *format, *format2; 93737355230Snorby 93837355230Snorby switch (p_type) { 93937355230Snorby case PT_INTRA_AREA: 94037355230Snorby case PT_INTER_AREA: 94137355230Snorby switch (d_type) { 94237355230Snorby case DT_NET: 94337355230Snorby format = "Network Routing Table"; 944*91e3b0aeSnorby format2 = ""; 94537355230Snorby break; 94637355230Snorby case DT_RTR: 94737355230Snorby format = "Router Routing Table"; 948*91e3b0aeSnorby format2 = "Type"; 94937355230Snorby break; 95037355230Snorby default: 95137355230Snorby errx(1, "unknown route type"); 95237355230Snorby } 95337355230Snorby break; 95437355230Snorby case PT_TYPE1_EXT: 95537355230Snorby case PT_TYPE2_EXT: 95637355230Snorby format = NULL; 957*91e3b0aeSnorby format2 = "Cost 2"; 95837355230Snorby if ((header = strdup("External Routing Table")) == NULL) 95937355230Snorby err(1, NULL); 96037355230Snorby break; 96137355230Snorby default: 96237355230Snorby errx(1, "unknown route type"); 96337355230Snorby } 96437355230Snorby 96537355230Snorby if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT) 96637355230Snorby if (asprintf(&header, "%s (Area %s)", format, 96737355230Snorby inet_ntoa(aid)) == -1) 96837355230Snorby err(1, NULL); 96937355230Snorby 970*91e3b0aeSnorby printf("\n%-18s %s\n", "", header); 97137355230Snorby free(header); 97237355230Snorby 973*91e3b0aeSnorby printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination", 974*91e3b0aeSnorby "Nexthop", "Adv Router", "Path type", "Cost", format2); 975*91e3b0aeSnorby } 97637355230Snorby 977*91e3b0aeSnorby const char * 978*91e3b0aeSnorby print_ospf_rtr_flags(u_int8_t opts) 979*91e3b0aeSnorby { 980*91e3b0aeSnorby static char optbuf[32]; 981*91e3b0aeSnorby 982*91e3b0aeSnorby snprintf(optbuf, sizeof(optbuf), "%s%s%s", 983*91e3b0aeSnorby opts & OSPF_RTR_E ? "AS" : "", 984*91e3b0aeSnorby opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "", 985*91e3b0aeSnorby opts & OSPF_RTR_B ? "ABR" : ""); 986*91e3b0aeSnorby return (optbuf); 98737355230Snorby } 98837355230Snorby 98937355230Snorby int 99037355230Snorby show_rib_detail_msg(struct imsg *imsg) 99137355230Snorby { 99237355230Snorby static struct in_addr area_id; 99337355230Snorby struct ctl_rt *rt; 99437355230Snorby struct area *area; 99537355230Snorby char *dstnet; 99637355230Snorby static u_int8_t lasttype; 99737355230Snorby 99837355230Snorby switch (imsg->hdr.type) { 99937355230Snorby case IMSG_CTL_SHOW_RIB: 100037355230Snorby rt = imsg->data; 100137355230Snorby 100237355230Snorby switch (rt->p_type) { 100337355230Snorby case PT_INTRA_AREA: 100437355230Snorby case PT_INTER_AREA: 100537355230Snorby switch (rt->d_type) { 100637355230Snorby case DT_NET: 100737355230Snorby if (lasttype != RIB_NET) 100837355230Snorby show_rib_head(rt->area, rt->d_type, 100937355230Snorby rt->p_type); 101037355230Snorby if (asprintf(&dstnet, "%s/%d", 101137355230Snorby inet_ntoa(rt->prefix), rt->prefixlen) == -1) 101237355230Snorby err(1, NULL); 101337355230Snorby lasttype = RIB_NET; 101437355230Snorby break; 101537355230Snorby case DT_RTR: 101637355230Snorby if (lasttype != RIB_RTR) 101737355230Snorby show_rib_head(rt->area, rt->d_type, 101837355230Snorby rt->p_type); 101937355230Snorby if (asprintf(&dstnet, "%s", 102037355230Snorby inet_ntoa(rt->prefix)) == -1) 102137355230Snorby err(1, NULL); 102237355230Snorby lasttype = RIB_RTR; 102337355230Snorby break; 102437355230Snorby default: 102537355230Snorby errx(1, "unknown route type"); 102637355230Snorby } 1027*91e3b0aeSnorby printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop)); 1028*91e3b0aeSnorby printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr), 102937355230Snorby path_type_names[rt->p_type], rt->cost); 103037355230Snorby free(dstnet); 1031*91e3b0aeSnorby 1032*91e3b0aeSnorby if (rt->d_type == DT_RTR) 1033*91e3b0aeSnorby printf(" %-7s", 1034*91e3b0aeSnorby print_ospf_rtr_flags(rt->flags)); 1035*91e3b0aeSnorby 1036*91e3b0aeSnorby printf("\n"); 103737355230Snorby break; 103837355230Snorby case PT_TYPE1_EXT: 103937355230Snorby case PT_TYPE2_EXT: 1040*91e3b0aeSnorby if (lasttype != RIB_EXT) 1041*91e3b0aeSnorby show_rib_head(rt->area, rt->d_type, rt->p_type); 1042*91e3b0aeSnorby 1043*91e3b0aeSnorby if (asprintf(&dstnet, "%s/%d", 1044*91e3b0aeSnorby inet_ntoa(rt->prefix), rt->prefixlen) == -1) 1045*91e3b0aeSnorby err(1, NULL); 1046*91e3b0aeSnorby 1047*91e3b0aeSnorby printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop)); 1048*91e3b0aeSnorby printf("%-15s %-12s %-7d %-7d\n", 1049*91e3b0aeSnorby inet_ntoa(rt->adv_rtr), path_type_names[rt->p_type], 1050*91e3b0aeSnorby rt->cost, rt->cost2); 1051*91e3b0aeSnorby 1052*91e3b0aeSnorby lasttype = RIB_EXT; 105337355230Snorby break; 105437355230Snorby default: 105537355230Snorby errx(1, "unknown route type"); 105637355230Snorby } 105737355230Snorby break; 105837355230Snorby case IMSG_CTL_AREA: 105937355230Snorby area = imsg->data; 106037355230Snorby area_id = area->id; 106137355230Snorby break; 106237355230Snorby case IMSG_CTL_END: 106337355230Snorby printf("\n"); 106437355230Snorby return (1); 106537355230Snorby default: 106637355230Snorby break; 106737355230Snorby } 106837355230Snorby 106937355230Snorby return (0); 107037355230Snorby } 1071c47b7f65Sclaudio 1072c47b7f65Sclaudio void 1073c47b7f65Sclaudio show_fib_head(void) 1074c47b7f65Sclaudio { 1075c47b7f65Sclaudio printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); 1076c47b7f65Sclaudio printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); 1077c47b7f65Sclaudio } 1078c47b7f65Sclaudio 1079c47b7f65Sclaudio int 1080c47b7f65Sclaudio show_fib_msg(struct imsg *imsg) 1081c47b7f65Sclaudio { 1082c47b7f65Sclaudio struct kroute *k; 1083c47b7f65Sclaudio char *p; 1084c47b7f65Sclaudio 1085c47b7f65Sclaudio switch (imsg->hdr.type) { 1086c47b7f65Sclaudio case IMSG_CTL_KROUTE: 1087c47b7f65Sclaudio if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 1088c47b7f65Sclaudio errx(1, "wrong imsg len"); 1089c47b7f65Sclaudio k = imsg->data; 1090c47b7f65Sclaudio 1091c47b7f65Sclaudio if (k->flags & F_DOWN) 1092c47b7f65Sclaudio printf(" "); 1093c47b7f65Sclaudio else 1094c47b7f65Sclaudio printf("*"); 1095c47b7f65Sclaudio 1096c47b7f65Sclaudio if (k->flags & F_OSPFD_INSERTED) 1097c47b7f65Sclaudio printf("O"); 1098c47b7f65Sclaudio else if (k->flags & F_CONNECTED) 1099c47b7f65Sclaudio printf("C"); 1100fc1549e1Sclaudio else if (k->flags & F_STATIC) 1101c47b7f65Sclaudio printf("S"); 1102c47b7f65Sclaudio else 1103c47b7f65Sclaudio printf(" "); 1104c47b7f65Sclaudio 1105c47b7f65Sclaudio printf(" "); 1106c47b7f65Sclaudio if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) == 1107c47b7f65Sclaudio -1) 1108c47b7f65Sclaudio err(1, NULL); 1109c47b7f65Sclaudio printf("%-20s ", p); 1110c47b7f65Sclaudio free(p); 1111c47b7f65Sclaudio 1112c47b7f65Sclaudio if (k->nexthop.s_addr) 1113c47b7f65Sclaudio printf("%s", inet_ntoa(k->nexthop)); 1114c47b7f65Sclaudio else if (k->flags & F_CONNECTED) 1115c47b7f65Sclaudio printf("link#%u", k->ifindex); 1116c47b7f65Sclaudio printf("\n"); 1117c47b7f65Sclaudio 1118c47b7f65Sclaudio break; 1119c47b7f65Sclaudio case IMSG_CTL_END: 1120c47b7f65Sclaudio printf("\n"); 1121c47b7f65Sclaudio return (1); 1122c47b7f65Sclaudio default: 1123c47b7f65Sclaudio break; 1124c47b7f65Sclaudio } 1125c47b7f65Sclaudio 1126c47b7f65Sclaudio return (0); 1127c47b7f65Sclaudio } 1128c47b7f65Sclaudio 1129c47b7f65Sclaudio void 1130c47b7f65Sclaudio show_interface_head(void) 1131c47b7f65Sclaudio { 11324c561fb6Sclaudio printf("%-15s%-15s%s\n", "Interface", "Flags", 1133c47b7f65Sclaudio "Link state"); 1134c47b7f65Sclaudio } 1135c47b7f65Sclaudio 1136c47b7f65Sclaudio const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1137c47b7f65Sclaudio const struct ifmedia_status_description 1138c47b7f65Sclaudio ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS; 1139c47b7f65Sclaudio const struct ifmedia_description 1140c47b7f65Sclaudio ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 1141c47b7f65Sclaudio 1142c47b7f65Sclaudio const char * 1143c47b7f65Sclaudio get_media_descr(int media_type) 1144c47b7f65Sclaudio { 1145c47b7f65Sclaudio const struct ifmedia_description *p; 1146c47b7f65Sclaudio 1147c47b7f65Sclaudio for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 1148c47b7f65Sclaudio if (media_type == p->ifmt_word) 1149c47b7f65Sclaudio return (p->ifmt_string); 1150c47b7f65Sclaudio 1151c47b7f65Sclaudio return ("unknown media"); 1152c47b7f65Sclaudio } 1153c47b7f65Sclaudio 1154c47b7f65Sclaudio const char * 1155c47b7f65Sclaudio get_linkstate(int media_type, int link_state) 1156c47b7f65Sclaudio { 1157c47b7f65Sclaudio const struct ifmedia_status_description *p; 1158c47b7f65Sclaudio int i; 1159c47b7f65Sclaudio 1160c47b7f65Sclaudio if (link_state == LINK_STATE_UNKNOWN) 1161c47b7f65Sclaudio return ("unknown"); 1162c47b7f65Sclaudio 1163c47b7f65Sclaudio for (i = 0; ifm_status_valid_list[i] != 0; i++) 1164c47b7f65Sclaudio for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) { 1165c47b7f65Sclaudio if (p->ifms_type != media_type || 1166c47b7f65Sclaudio p->ifms_valid != ifm_status_valid_list[i]) 1167c47b7f65Sclaudio continue; 1168c47b7f65Sclaudio return (p->ifms_string[link_state == LINK_STATE_UP]); 1169c47b7f65Sclaudio } 1170c47b7f65Sclaudio 1171c47b7f65Sclaudio return ("unknown link state"); 1172c47b7f65Sclaudio } 1173c47b7f65Sclaudio 1174c47b7f65Sclaudio void 1175c47b7f65Sclaudio print_baudrate(u_long baudrate) 1176c47b7f65Sclaudio { 1177c47b7f65Sclaudio if (baudrate > IF_Gbps(1)) 1178c47b7f65Sclaudio printf("%lu GBit/s", baudrate / IF_Gbps(1)); 1179c47b7f65Sclaudio else if (baudrate > IF_Mbps(1)) 1180c47b7f65Sclaudio printf("%lu MBit/s", baudrate / IF_Mbps(1)); 1181c47b7f65Sclaudio else if (baudrate > IF_Kbps(1)) 1182c47b7f65Sclaudio printf("%lu KBit/s", baudrate / IF_Kbps(1)); 1183c47b7f65Sclaudio else 1184c47b7f65Sclaudio printf("%lu Bit/s", baudrate); 1185c47b7f65Sclaudio } 1186c47b7f65Sclaudio 1187c47b7f65Sclaudio int 1188c47b7f65Sclaudio show_fib_interface_msg(struct imsg *imsg) 1189c47b7f65Sclaudio { 1190c47b7f65Sclaudio struct kif *k; 1191c47b7f65Sclaudio int ifms_type; 1192c47b7f65Sclaudio 1193c47b7f65Sclaudio switch (imsg->hdr.type) { 11944c561fb6Sclaudio case IMSG_CTL_IFINFO: 1195c47b7f65Sclaudio k = imsg->data; 1196c47b7f65Sclaudio printf("%-15s", k->ifname); 1197c47b7f65Sclaudio printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 1198c47b7f65Sclaudio switch (k->media_type) { 1199c47b7f65Sclaudio case IFT_ETHER: 1200c47b7f65Sclaudio ifms_type = IFM_ETHER; 1201c47b7f65Sclaudio break; 1202c47b7f65Sclaudio case IFT_FDDI: 1203c47b7f65Sclaudio ifms_type = IFM_FDDI; 1204c47b7f65Sclaudio break; 1205c47b7f65Sclaudio case IFT_ISO88025: 1206c47b7f65Sclaudio ifms_type = IFM_TOKEN; 1207c47b7f65Sclaudio break; 1208c47b7f65Sclaudio case IFT_CARP: 1209c47b7f65Sclaudio ifms_type = IFM_CARP; 1210c47b7f65Sclaudio break; 1211c47b7f65Sclaudio default: 1212c47b7f65Sclaudio ifms_type = 0; 1213c47b7f65Sclaudio break; 1214c47b7f65Sclaudio } 1215c47b7f65Sclaudio 1216c47b7f65Sclaudio if (ifms_type) 1217c47b7f65Sclaudio printf("%s, %s", get_media_descr(ifms_type), 1218c47b7f65Sclaudio get_linkstate(ifms_type, k->link_state)); 1219c47b7f65Sclaudio else if (k->link_state == LINK_STATE_UNKNOWN) 1220c47b7f65Sclaudio printf("unknown"); 1221c47b7f65Sclaudio else 1222c47b7f65Sclaudio printf("link state %u", k->link_state); 1223c47b7f65Sclaudio 1224c47b7f65Sclaudio if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 1225c47b7f65Sclaudio printf(", "); 1226c47b7f65Sclaudio print_baudrate(k->baudrate); 1227c47b7f65Sclaudio } 1228c47b7f65Sclaudio printf("\n"); 1229c47b7f65Sclaudio break; 1230c47b7f65Sclaudio case IMSG_CTL_END: 1231c47b7f65Sclaudio printf("\n"); 1232c47b7f65Sclaudio return (1); 1233c47b7f65Sclaudio default: 1234c47b7f65Sclaudio break; 1235c47b7f65Sclaudio } 1236c47b7f65Sclaudio 1237c47b7f65Sclaudio return (0); 1238c47b7f65Sclaudio } 1239