1*f1b790a5Sclaudio /* $OpenBSD: ripctl.c,v 1.22 2024/11/21 13:38:15 claudio Exp $ 28eeeb81eSnorby * 38eeeb81eSnorby * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> 48eeeb81eSnorby * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 58eeeb81eSnorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 68eeeb81eSnorby * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 78eeeb81eSnorby * 88eeeb81eSnorby * Permission to use, copy, modify, and distribute this software for any 98eeeb81eSnorby * purpose with or without fee is hereby granted, provided that the above 108eeeb81eSnorby * copyright notice and this permission notice appear in all copies. 118eeeb81eSnorby * 128eeeb81eSnorby * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 138eeeb81eSnorby * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 148eeeb81eSnorby * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 158eeeb81eSnorby * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 168eeeb81eSnorby * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 178eeeb81eSnorby * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 188eeeb81eSnorby * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 198eeeb81eSnorby */ 208eeeb81eSnorby 218eeeb81eSnorby #include <sys/types.h> 228eeeb81eSnorby #include <sys/socket.h> 238eeeb81eSnorby #include <sys/un.h> 248eeeb81eSnorby #include <netinet/in.h> 258eeeb81eSnorby #include <arpa/inet.h> 268eeeb81eSnorby #include <net/if_media.h> 278eeeb81eSnorby #include <net/if_types.h> 288eeeb81eSnorby 298eeeb81eSnorby #include <err.h> 30397afdbcSderaadt #include <errno.h> 318eeeb81eSnorby #include <stdio.h> 328eeeb81eSnorby #include <stdlib.h> 338eeeb81eSnorby #include <string.h> 348eeeb81eSnorby #include <unistd.h> 358eeeb81eSnorby 368eeeb81eSnorby #include "rip.h" 378eeeb81eSnorby #include "ripd.h" 388eeeb81eSnorby #include "ripe.h" 398eeeb81eSnorby #include "parser.h" 408eeeb81eSnorby 418eeeb81eSnorby __dead void usage(void); 428eeeb81eSnorby const char *fmt_timeframe_core(time_t); 4316530d00Sstsp const char *get_linkstate(uint8_t, int); 448eeeb81eSnorby int show_interface_msg(struct imsg *); 4516530d00Sstsp uint64_t get_ifms_type(uint8_t); 468eeeb81eSnorby int show_rib_msg(struct imsg *); 478eeeb81eSnorby int show_nbr_msg(struct imsg *); 488eeeb81eSnorby void show_fib_head(void); 498eeeb81eSnorby int show_fib_msg(struct imsg *); 508eeeb81eSnorby void show_interface_head(void); 518eeeb81eSnorby int show_fib_interface_msg(struct imsg *); 52e5605ae3Sderaadt const char *get_media_descr(uint64_t); 5316530d00Sstsp void print_baudrate(uint64_t); 548eeeb81eSnorby 558eeeb81eSnorby struct imsgbuf *ibuf; 568eeeb81eSnorby 578eeeb81eSnorby __dead void 588eeeb81eSnorby usage(void) 598eeeb81eSnorby { 608eeeb81eSnorby extern char *__progname; 618eeeb81eSnorby 623dabc796Sjca fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n", 633dabc796Sjca __progname); 648eeeb81eSnorby exit(1); 658eeeb81eSnorby } 668eeeb81eSnorby 678eeeb81eSnorby int 688eeeb81eSnorby main(int argc, char *argv[]) 698eeeb81eSnorby { 708eeeb81eSnorby struct sockaddr_un sun; 718eeeb81eSnorby struct parse_result *res; 728eeeb81eSnorby struct imsg imsg; 738eeeb81eSnorby unsigned int ifidx = 0; 748eeeb81eSnorby int ctl_sock; 75c3319070Sclaudio int done = 0, verbose = 0; 768eeeb81eSnorby int n; 773dabc796Sjca int ch; 783dabc796Sjca char *sockname = RIPD_SOCKET; 793dabc796Sjca 803dabc796Sjca while ((ch = getopt(argc, argv, "s:")) != -1) { 813dabc796Sjca switch (ch) { 823dabc796Sjca case 's': 833dabc796Sjca sockname = optarg; 843dabc796Sjca break; 853dabc796Sjca default: 863dabc796Sjca usage(); 873dabc796Sjca /* NOTREACHED */ 883dabc796Sjca } 893dabc796Sjca } 903dabc796Sjca 913dabc796Sjca argc -= optind; 923dabc796Sjca argv += optind; 938eeeb81eSnorby 948eeeb81eSnorby /* parse options */ 953dabc796Sjca if ((res = parse(argc, argv)) == NULL) 968eeeb81eSnorby exit(1); 978eeeb81eSnorby 988eeeb81eSnorby /* connect to ripd control socket */ 998eeeb81eSnorby if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 1008eeeb81eSnorby err(1, "socket"); 1018eeeb81eSnorby 1028eeeb81eSnorby bzero(&sun, sizeof(sun)); 1038eeeb81eSnorby sun.sun_family = AF_UNIX; 1043dabc796Sjca strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)); 1058eeeb81eSnorby if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 1063dabc796Sjca err(1, "connect: %s", sockname); 1078eeeb81eSnorby 1084ca91f07Sderaadt if (pledge("stdio", NULL) == -1) 1094ca91f07Sderaadt err(1, "pledge"); 1104ca91f07Sderaadt 1118eeeb81eSnorby if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 1128eeeb81eSnorby err(1, NULL); 113*f1b790a5Sclaudio if (imsgbuf_init(ibuf, ctl_sock) == -1) 114*f1b790a5Sclaudio err(1, NULL); 1158eeeb81eSnorby done = 0; 1168eeeb81eSnorby 1178eeeb81eSnorby /* process user request */ 1188eeeb81eSnorby switch (res->action) { 1198eeeb81eSnorby case NONE: 1208eeeb81eSnorby usage(); 1218eeeb81eSnorby /* not reached */ 1228eeeb81eSnorby case SHOW: 1238eeeb81eSnorby case SHOW_IFACE: 1248eeeb81eSnorby printf("%-11s %-18s %-10s %-10s %-8s\n", 1258eeeb81eSnorby "Interface", "Address", "State", "Linkstate", 1268eeeb81eSnorby "Uptime"); 1278eeeb81eSnorby if (*res->ifname) { 1288eeeb81eSnorby ifidx = if_nametoindex(res->ifname); 1298eeeb81eSnorby if (ifidx == 0) 1308eeeb81eSnorby errx(1, "no such interface %s", res->ifname); 1318eeeb81eSnorby } 132f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 1338eeeb81eSnorby &ifidx, sizeof(ifidx)); 1348eeeb81eSnorby break; 1358eeeb81eSnorby case SHOW_NBR: 1368eeeb81eSnorby printf("%-15s %-15s %-15s %-9s %-10s\n", "ID", 1378eeeb81eSnorby "State", "Address", "Iface", "Uptime"); 138f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 1398eeeb81eSnorby break; 1408eeeb81eSnorby case SHOW_RIB: 1418eeeb81eSnorby printf("%-20s %-17s %-7s\n", "Destination", 1428eeeb81eSnorby "Nexthop", "Cost"); 143f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0); 1448eeeb81eSnorby break; 1458eeeb81eSnorby case SHOW_FIB: 1468eeeb81eSnorby if (!res->addr.s_addr) 147f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 1488eeeb81eSnorby &res->flags, sizeof(res->flags)); 1498eeeb81eSnorby else 150f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, 1518eeeb81eSnorby &res->addr, sizeof(res->addr)); 1528eeeb81eSnorby show_fib_head(); 1538eeeb81eSnorby break; 1548eeeb81eSnorby case SHOW_FIB_IFACE: 1558eeeb81eSnorby if (*res->ifname) 156f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, 1578eeeb81eSnorby res->ifname, sizeof(res->ifname)); 1588eeeb81eSnorby else 159f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 1608eeeb81eSnorby show_interface_head(); 1618eeeb81eSnorby break; 1628eeeb81eSnorby case FIB: 1638eeeb81eSnorby errx(1, "fib couple|decouple"); 1648eeeb81eSnorby break; 1658eeeb81eSnorby case FIB_COUPLE: 166f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); 1678eeeb81eSnorby printf("couple request sent.\n"); 1688eeeb81eSnorby done = 1; 1698eeeb81eSnorby break; 1708eeeb81eSnorby case FIB_DECOUPLE: 171f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); 1728eeeb81eSnorby printf("decouple request sent.\n"); 1738eeeb81eSnorby done = 1; 1748eeeb81eSnorby break; 175c3319070Sclaudio case LOG_VERBOSE: 176c3319070Sclaudio verbose = 1; 177c3319070Sclaudio /* FALLTHROUGH */ 178c3319070Sclaudio case LOG_BRIEF: 179c3319070Sclaudio imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, 180c3319070Sclaudio &verbose, sizeof(verbose)); 181c3319070Sclaudio printf("logging request sent.\n"); 182c3319070Sclaudio done = 1; 183c3319070Sclaudio break; 1848eeeb81eSnorby case RELOAD: 185f7ce36daSeric imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 1868eeeb81eSnorby printf("reload request sent.\n"); 1878eeeb81eSnorby done = 1; 1888eeeb81eSnorby break; 1898eeeb81eSnorby } 1908eeeb81eSnorby 191dd7efffeSclaudio if (imsgbuf_flush(ibuf) == -1) 1928eeeb81eSnorby err(1, "write error"); 1938eeeb81eSnorby 1948eeeb81eSnorby while (!done) { 195668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 196ef2e27a1Sclaudio err(1, "read error"); 1978eeeb81eSnorby if (n == 0) 1988eeeb81eSnorby errx(1, "pipe closed"); 1998eeeb81eSnorby 2008eeeb81eSnorby while (!done) { 2018eeeb81eSnorby if ((n = imsg_get(ibuf, &imsg)) == -1) 2028eeeb81eSnorby errx(1, "imsg_get error"); 2038eeeb81eSnorby if (n == 0) 2048eeeb81eSnorby break; 2058eeeb81eSnorby switch (res->action) { 2068eeeb81eSnorby case SHOW: 2078eeeb81eSnorby case SHOW_IFACE: 2088eeeb81eSnorby done = show_interface_msg(&imsg); 2098eeeb81eSnorby break; 2108eeeb81eSnorby case SHOW_NBR: 2118eeeb81eSnorby done = show_nbr_msg(&imsg); 2128eeeb81eSnorby break; 2138eeeb81eSnorby case SHOW_RIB: 2148eeeb81eSnorby done = show_rib_msg(&imsg); 2158eeeb81eSnorby break; 2168eeeb81eSnorby case SHOW_FIB: 2178eeeb81eSnorby done = show_fib_msg(&imsg); 2188eeeb81eSnorby break; 2198eeeb81eSnorby case SHOW_FIB_IFACE: 2208eeeb81eSnorby done = show_fib_interface_msg(&imsg); 2218eeeb81eSnorby break; 2228eeeb81eSnorby case NONE: 2238eeeb81eSnorby case FIB: 2248eeeb81eSnorby case FIB_COUPLE: 2258eeeb81eSnorby case FIB_DECOUPLE: 226c3319070Sclaudio case LOG_VERBOSE: 227c3319070Sclaudio case LOG_BRIEF: 2288eeeb81eSnorby case RELOAD: 2298eeeb81eSnorby break; 2308eeeb81eSnorby } 2318eeeb81eSnorby imsg_free(&imsg); 2328eeeb81eSnorby } 2338eeeb81eSnorby } 2348eeeb81eSnorby close(ctl_sock); 2358eeeb81eSnorby free(ibuf); 2368eeeb81eSnorby 2378eeeb81eSnorby return (0); 2388eeeb81eSnorby } 2398eeeb81eSnorby 24016530d00Sstsp uint64_t 24116530d00Sstsp get_ifms_type(uint8_t if_type) 2428eeeb81eSnorby { 24316530d00Sstsp switch (if_type) { 2448eeeb81eSnorby case IFT_ETHER: 2458eeeb81eSnorby return (IFM_ETHER); 2468eeeb81eSnorby break; 2478eeeb81eSnorby case IFT_FDDI: 2488eeeb81eSnorby return (IFM_FDDI); 2498eeeb81eSnorby break; 2508eeeb81eSnorby case IFT_CARP: 2518eeeb81eSnorby return (IFM_CARP); 2528eeeb81eSnorby break; 2538eeeb81eSnorby default: 2548eeeb81eSnorby return (0); 2558eeeb81eSnorby break; 2568eeeb81eSnorby } 2578eeeb81eSnorby } 2588eeeb81eSnorby 2598eeeb81eSnorby #define TF_BUFS 8 2608eeeb81eSnorby #define TF_LEN 9 2618eeeb81eSnorby 2628eeeb81eSnorby const char * 2638eeeb81eSnorby fmt_timeframe_core(time_t t) 2648eeeb81eSnorby { 2658eeeb81eSnorby char *buf; 2668eeeb81eSnorby static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 2678eeeb81eSnorby static int idx = 0; 268035b0708Sgilles unsigned int sec, min, hrs, day; 269035b0708Sgilles unsigned long long week; 2708eeeb81eSnorby 2718eeeb81eSnorby if (t == 0) 2728eeeb81eSnorby return ("Stopped"); 2738eeeb81eSnorby 2748eeeb81eSnorby buf = tfbuf[idx++]; 2758eeeb81eSnorby if (idx == TF_BUFS) 2768eeeb81eSnorby idx = 0; 2778eeeb81eSnorby 2788eeeb81eSnorby week = t; 2798eeeb81eSnorby 2808eeeb81eSnorby sec = week % 60; 2818eeeb81eSnorby week /= 60; 2828eeeb81eSnorby min = week % 60; 2838eeeb81eSnorby week /= 60; 2848eeeb81eSnorby hrs = week % 24; 2858eeeb81eSnorby week /= 24; 2868eeeb81eSnorby day = week % 7; 2878eeeb81eSnorby week /= 7; 2888eeeb81eSnorby 2898eeeb81eSnorby if (week > 0) 290035b0708Sgilles snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); 2918eeeb81eSnorby else if (day > 0) 2928eeeb81eSnorby snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 2938eeeb81eSnorby else 2948eeeb81eSnorby snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 2958eeeb81eSnorby 2968eeeb81eSnorby return (buf); 2978eeeb81eSnorby } 2988eeeb81eSnorby 2998eeeb81eSnorby /* prototype defined in ripd.h and shared with the kroute.c version */ 3008eeeb81eSnorby u_int8_t 3018eeeb81eSnorby mask2prefixlen(in_addr_t ina) 3028eeeb81eSnorby { 3038eeeb81eSnorby if (ina == 0) 3048eeeb81eSnorby return (0); 3058eeeb81eSnorby else 3068eeeb81eSnorby return (33 - ffs(ntohl(ina))); 3078eeeb81eSnorby } 3088eeeb81eSnorby 3098eeeb81eSnorby int 3108eeeb81eSnorby show_interface_msg(struct imsg *imsg) 3118eeeb81eSnorby { 3128eeeb81eSnorby struct ctl_iface *iface; 3138eeeb81eSnorby char *netid; 3148eeeb81eSnorby 3158eeeb81eSnorby switch (imsg->hdr.type) { 3168eeeb81eSnorby case IMSG_CTL_SHOW_IFACE: 3178eeeb81eSnorby iface = imsg->data; 3188eeeb81eSnorby 3198eeeb81eSnorby if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr), 3208eeeb81eSnorby mask2prefixlen(iface->mask.s_addr)) == -1) 3218eeeb81eSnorby err(1, NULL); 3228eeeb81eSnorby printf("%-11s %-18s %-10s %-10s %-8s\n", 3238eeeb81eSnorby iface->name, netid, if_state_name(iface->state), 32416530d00Sstsp get_linkstate(iface->if_type, iface->linkstate), 3250f617141Sclaudio iface->uptime == 0 ? "00:00:00" : 3268eeeb81eSnorby fmt_timeframe_core(iface->uptime)); 3278eeeb81eSnorby free(netid); 3288eeeb81eSnorby break; 3298eeeb81eSnorby case IMSG_CTL_END: 3308eeeb81eSnorby printf("\n"); 3318eeeb81eSnorby return (1); 3328eeeb81eSnorby default: 3338eeeb81eSnorby break; 3348eeeb81eSnorby } 3358eeeb81eSnorby 3368eeeb81eSnorby return (0); 3378eeeb81eSnorby } 3388eeeb81eSnorby 3398eeeb81eSnorby int 3408eeeb81eSnorby show_rib_msg(struct imsg *imsg) 3418eeeb81eSnorby { 3428eeeb81eSnorby struct ctl_rt *rt; 3438eeeb81eSnorby char *dstnet; 3448eeeb81eSnorby 3458eeeb81eSnorby switch (imsg->hdr.type) { 3468eeeb81eSnorby case IMSG_CTL_SHOW_RIB: 3478eeeb81eSnorby rt = imsg->data; 3488eeeb81eSnorby if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 3498eeeb81eSnorby mask2prefixlen(rt->netmask.s_addr)) == -1) 3508eeeb81eSnorby err(1, NULL); 3518eeeb81eSnorby 3528eeeb81eSnorby printf("%-20s %-17s %-7d\n", dstnet, 3538eeeb81eSnorby inet_ntoa(rt->nexthop), 3548eeeb81eSnorby rt->metric); 3558eeeb81eSnorby free(dstnet); 3568eeeb81eSnorby 3578eeeb81eSnorby break; 3588eeeb81eSnorby case IMSG_CTL_END: 3598eeeb81eSnorby printf("\n"); 3608eeeb81eSnorby return (1); 3618eeeb81eSnorby default: 3628eeeb81eSnorby break; 3638eeeb81eSnorby } 3648eeeb81eSnorby 3658eeeb81eSnorby return (0); 3668eeeb81eSnorby } 3678eeeb81eSnorby 3688eeeb81eSnorby int 3698eeeb81eSnorby show_nbr_msg(struct imsg *imsg) 3708eeeb81eSnorby { 3718eeeb81eSnorby struct ctl_nbr *nbr; 3728eeeb81eSnorby char *state; 3738eeeb81eSnorby 3748eeeb81eSnorby switch (imsg->hdr.type) { 3758eeeb81eSnorby case IMSG_CTL_SHOW_NBR: 3768eeeb81eSnorby nbr = imsg->data; 3778eeeb81eSnorby if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 3788eeeb81eSnorby if_state_name(nbr->iface_state)) == -1) 3798eeeb81eSnorby err(1, NULL); 3808eeeb81eSnorby printf("%-15s %-16s", inet_ntoa(nbr->id), 3818eeeb81eSnorby state); 3828eeeb81eSnorby printf("%-15s %-10s", inet_ntoa(nbr->addr), nbr->name); 3838eeeb81eSnorby printf("%-15s\n", nbr->uptime == 0 ? "-" : 3848eeeb81eSnorby fmt_timeframe_core(nbr->uptime)); 3858eeeb81eSnorby free(state); 3868eeeb81eSnorby break; 3878eeeb81eSnorby case IMSG_CTL_END: 3888eeeb81eSnorby printf("\n"); 3898eeeb81eSnorby return (1); 3908eeeb81eSnorby default: 3918eeeb81eSnorby break; 3928eeeb81eSnorby } 3938eeeb81eSnorby 3948eeeb81eSnorby return (0); 3958eeeb81eSnorby } 3968eeeb81eSnorby 3978eeeb81eSnorby void 3988eeeb81eSnorby show_fib_head(void) 3998eeeb81eSnorby { 4008eeeb81eSnorby printf("flags: * = valid, R = RIP, C = Connected, S = Static\n"); 4018eeeb81eSnorby printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); 4028eeeb81eSnorby } 4038eeeb81eSnorby 4048eeeb81eSnorby int 4058eeeb81eSnorby show_fib_msg(struct imsg *imsg) 4068eeeb81eSnorby { 4078eeeb81eSnorby struct kroute *k; 4088eeeb81eSnorby char *p; 4098eeeb81eSnorby 4108eeeb81eSnorby switch (imsg->hdr.type) { 4118eeeb81eSnorby case IMSG_CTL_KROUTE: 4128eeeb81eSnorby if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 4138eeeb81eSnorby errx(1, "wrong imsg len"); 4148eeeb81eSnorby k = imsg->data; 4158eeeb81eSnorby 4168eeeb81eSnorby if (k->flags & F_DOWN) 4178eeeb81eSnorby printf(" "); 4188eeeb81eSnorby else 4198eeeb81eSnorby printf("*"); 4208eeeb81eSnorby 42174ae440cSmichele if (k->flags & F_RIPD_INSERTED) 4228eeeb81eSnorby printf("R"); 4238eeeb81eSnorby else if (k->flags & F_CONNECTED) 4248eeeb81eSnorby printf("C"); 4258eeeb81eSnorby else if (k->flags & F_STATIC) 4268eeeb81eSnorby printf("S"); 4278eeeb81eSnorby else 4288eeeb81eSnorby printf(" "); 4298eeeb81eSnorby 4308eeeb81eSnorby printf(" "); 4318eeeb81eSnorby if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), 4328eeeb81eSnorby mask2prefixlen(k->netmask.s_addr)) == -1) 4338eeeb81eSnorby err(1, NULL); 4348eeeb81eSnorby printf("%-20s ", p); 4358eeeb81eSnorby free(p); 4368eeeb81eSnorby 4378eeeb81eSnorby if (k->nexthop.s_addr) 4388eeeb81eSnorby printf("%s", inet_ntoa(k->nexthop)); 4398eeeb81eSnorby else if (k->flags & F_CONNECTED) 4408eeeb81eSnorby printf("link#%u", k->ifindex); 4418eeeb81eSnorby printf("\n"); 4428eeeb81eSnorby 4438eeeb81eSnorby break; 4448eeeb81eSnorby case IMSG_CTL_END: 4458eeeb81eSnorby printf("\n"); 4468eeeb81eSnorby return (1); 4478eeeb81eSnorby default: 4488eeeb81eSnorby break; 4498eeeb81eSnorby } 4508eeeb81eSnorby 4518eeeb81eSnorby return (0); 4528eeeb81eSnorby } 4538eeeb81eSnorby 4548eeeb81eSnorby void 4558eeeb81eSnorby show_interface_head(void) 4568eeeb81eSnorby { 4578eeeb81eSnorby printf("%-15s%-15s%s\n", "Interface", "Flags", 4588eeeb81eSnorby "Link state"); 4598eeeb81eSnorby } 4608eeeb81eSnorby 4618eeeb81eSnorby int 4628eeeb81eSnorby show_fib_interface_msg(struct imsg *imsg) 4638eeeb81eSnorby { 4648eeeb81eSnorby struct kif *k; 46516530d00Sstsp uint64_t ifms_type; 4668eeeb81eSnorby 4678eeeb81eSnorby switch (imsg->hdr.type) { 4688eeeb81eSnorby case IMSG_CTL_IFINFO: 4698eeeb81eSnorby k = imsg->data; 4708eeeb81eSnorby printf("%-15s", k->ifname); 4718eeeb81eSnorby printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 47216530d00Sstsp ifms_type = get_ifms_type(k->if_type); 4738eeeb81eSnorby if (ifms_type) 4740f617141Sclaudio printf("%s, ", get_media_descr(ifms_type)); 4750f617141Sclaudio 47616530d00Sstsp printf("%s", get_linkstate(k->if_type, k->link_state)); 4778eeeb81eSnorby 4788eeeb81eSnorby if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 4798eeeb81eSnorby printf(", "); 4808eeeb81eSnorby print_baudrate(k->baudrate); 4818eeeb81eSnorby } 4828eeeb81eSnorby printf("\n"); 4838eeeb81eSnorby break; 4848eeeb81eSnorby case IMSG_CTL_END: 4858eeeb81eSnorby printf("\n"); 4868eeeb81eSnorby return (1); 4878eeeb81eSnorby default: 4888eeeb81eSnorby break; 4898eeeb81eSnorby } 4908eeeb81eSnorby 4918eeeb81eSnorby return (0); 4928eeeb81eSnorby } 4938eeeb81eSnorby 4940f617141Sclaudio const struct if_status_description 4950f617141Sclaudio if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 4968eeeb81eSnorby const struct ifmedia_description 4978eeeb81eSnorby ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 4988eeeb81eSnorby 4998eeeb81eSnorby const char * 500e5605ae3Sderaadt get_media_descr(uint64_t media_type) 5018eeeb81eSnorby { 5028eeeb81eSnorby const struct ifmedia_description *p; 5038eeeb81eSnorby 5048eeeb81eSnorby for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 5058eeeb81eSnorby if (media_type == p->ifmt_word) 5068eeeb81eSnorby return (p->ifmt_string); 5078eeeb81eSnorby 5088eeeb81eSnorby return ("unknown"); 5098eeeb81eSnorby } 5108eeeb81eSnorby 5118eeeb81eSnorby const char * 51216530d00Sstsp get_linkstate(uint8_t if_type, int link_state) 5138eeeb81eSnorby { 5140f617141Sclaudio const struct if_status_description *p; 5150f617141Sclaudio static char buf[8]; 5168eeeb81eSnorby 5170f617141Sclaudio for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 51816530d00Sstsp if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) 5190f617141Sclaudio return (p->ifs_string); 5208eeeb81eSnorby } 5210f617141Sclaudio snprintf(buf, sizeof(buf), "[#%d]", link_state); 5220f617141Sclaudio return (buf); 5238eeeb81eSnorby } 5248eeeb81eSnorby 5258eeeb81eSnorby void 52616530d00Sstsp print_baudrate(uint64_t baudrate) 5278eeeb81eSnorby { 5288eeeb81eSnorby if (baudrate > IF_Gbps(1)) 52929e85e71Shenning printf("%llu GBit/s", baudrate / IF_Gbps(1)); 5308eeeb81eSnorby else if (baudrate > IF_Mbps(1)) 53129e85e71Shenning printf("%llu MBit/s", baudrate / IF_Mbps(1)); 5328eeeb81eSnorby else if (baudrate > IF_Kbps(1)) 53329e85e71Shenning printf("%llu KBit/s", baudrate / IF_Kbps(1)); 5348eeeb81eSnorby else 53529e85e71Shenning printf("%llu Bit/s", baudrate); 5368eeeb81eSnorby } 537