1*479c151dSjsg /* $OpenBSD: if.c,v 1.28 2024/09/20 02:00:46 jsg Exp $ */ 21612fc5aSmarkus /* 31612fc5aSmarkus * Copyright (c) 2004 Markus Friedl <markus@openbsd.org> 41612fc5aSmarkus * 51612fc5aSmarkus * Permission to use, copy, modify, and distribute this software for any 61612fc5aSmarkus * purpose with or without fee is hereby granted, provided that the above 71612fc5aSmarkus * copyright notice and this permission notice appear in all copies. 81612fc5aSmarkus * 91612fc5aSmarkus * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101612fc5aSmarkus * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111612fc5aSmarkus * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121612fc5aSmarkus * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131612fc5aSmarkus * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141612fc5aSmarkus * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151612fc5aSmarkus * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161612fc5aSmarkus */ 17bc595886Sjasper 18b3fb853aSderaadt #include <sys/types.h> 198f6b3bafSderaadt #include <sys/signal.h> 201612fc5aSmarkus #include <sys/socket.h> 211612fc5aSmarkus #include <sys/sysctl.h> 221612fc5aSmarkus #include <net/if.h> 231612fc5aSmarkus #include <net/if_dl.h> 241612fc5aSmarkus #include <net/route.h> 257d0bcf9cSderaadt #include <sys/sockio.h> 26bc595886Sjasper #include <sys/ioctl.h> 271612fc5aSmarkus 281612fc5aSmarkus #include <stdlib.h> 296cf6eca7Sderaadt #include <string.h> 30bc595886Sjasper #include <unistd.h> 311612fc5aSmarkus 32b3fb853aSderaadt #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 33b3fb853aSderaadt 341612fc5aSmarkus #include "systat.h" 351612fc5aSmarkus 361612fc5aSmarkus static enum state { BOOT, TIME, RUN } state = TIME; 371612fc5aSmarkus 381612fc5aSmarkus struct ifstat { 391612fc5aSmarkus char ifs_name[IFNAMSIZ]; /* interface name */ 407d0bcf9cSderaadt char ifs_description[IFDESCRSIZE]; 411612fc5aSmarkus struct ifcount ifs_cur; 421612fc5aSmarkus struct ifcount ifs_old; 431612fc5aSmarkus struct ifcount ifs_now; 44d7c69161Scanacar char ifs_flag; 451612fc5aSmarkus } *ifstats; 461612fc5aSmarkus 4708e35e0cSmortimer struct ifcount sum; 4808e35e0cSmortimer 491612fc5aSmarkus static int nifs = 0; 5073baed14Scanacar static int num_ifs = 0; 515c280c62Smpf static int show_bits = 0; 521612fc5aSmarkus 5373baed14Scanacar void print_if(void); 5473baed14Scanacar int read_if(void); 5573baed14Scanacar int select_if(void); 5673baed14Scanacar int if_keyboard_callback(int); 5750de0d1bSclaudio 58f429edc3Sderaadt void fetchifstat(void); 5973baed14Scanacar static void showifstat(struct ifstat *); 6073baed14Scanacar static void showtotal(void); 614a1020e8Slum static void rt_getaddrinfo(struct sockaddr *, int, struct sockaddr **); 621612fc5aSmarkus 63c5f96cb8Sdlg const char ifails[] = "IFAILS"; 64c5f96cb8Sdlg const char ofails[] = "OFAILS"; 65c5f96cb8Sdlg 66c5f96cb8Sdlg #define IF_ERR_SUM 0 67c5f96cb8Sdlg #define IF_ERR_ERRORS 1 68c5f96cb8Sdlg #define IF_ERR_QDROPS 2 69c5f96cb8Sdlg 70c5f96cb8Sdlg struct if_err_view { 71c5f96cb8Sdlg const char *iname; 72c5f96cb8Sdlg const char *oname; 73c5f96cb8Sdlg uint64_t (*icount)(const struct ifcount *); 74c5f96cb8Sdlg uint64_t (*ocount)(const struct ifcount *); 75c5f96cb8Sdlg }; 76c5f96cb8Sdlg 77c5f96cb8Sdlg static uint64_t if_err_ifails(const struct ifcount *); 78c5f96cb8Sdlg static uint64_t if_err_ofails(const struct ifcount *); 79c5f96cb8Sdlg static uint64_t if_err_ierrors(const struct ifcount *); 80c5f96cb8Sdlg static uint64_t if_err_oerrors(const struct ifcount *); 81c5f96cb8Sdlg static uint64_t if_err_iqdrops(const struct ifcount *); 82c5f96cb8Sdlg static uint64_t if_err_oqdrops(const struct ifcount *); 83c5f96cb8Sdlg 84c5f96cb8Sdlg static const struct if_err_view if_err_views[] = { 85c5f96cb8Sdlg [IF_ERR_SUM] = { 86c5f96cb8Sdlg .iname = ifails, 87c5f96cb8Sdlg .oname = ofails, 88c5f96cb8Sdlg .icount = if_err_ifails, 89c5f96cb8Sdlg .ocount = if_err_ofails, 90c5f96cb8Sdlg }, 91c5f96cb8Sdlg [IF_ERR_ERRORS] = { 92c5f96cb8Sdlg .iname = "IERRS", 93c5f96cb8Sdlg .oname = "OERRS", 94c5f96cb8Sdlg .icount = if_err_ierrors, 95c5f96cb8Sdlg .ocount = if_err_oerrors, 96c5f96cb8Sdlg }, 97c5f96cb8Sdlg [IF_ERR_QDROPS] = { 98c5f96cb8Sdlg .iname = "IQDROPS", 99c5f96cb8Sdlg .oname = "OQDROPS", 100c5f96cb8Sdlg .icount = if_err_iqdrops, 101c5f96cb8Sdlg .ocount = if_err_oqdrops, 102c5f96cb8Sdlg }, 103c5f96cb8Sdlg }; 104c5f96cb8Sdlg 105c5f96cb8Sdlg static const struct if_err_view *if_err_view = &if_err_views[IF_ERR_SUM]; 1061612fc5aSmarkus 10773baed14Scanacar /* Define fields */ 10873baed14Scanacar field_def fields_if[] = { 10973baed14Scanacar {"IFACE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 1107d0bcf9cSderaadt {"STATE", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 11173baed14Scanacar {"IPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 11273baed14Scanacar {"IBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 113c5f96cb8Sdlg {ifails, 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 11473baed14Scanacar {"OPKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 11573baed14Scanacar {"OBYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 116c5f96cb8Sdlg {ofails, 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 11773baed14Scanacar {"COLLS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 1187d0bcf9cSderaadt {"DESC", 14, 64, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 11973baed14Scanacar }; 1201612fc5aSmarkus 12173baed14Scanacar 122596a8091Sjasper #define FLD_IF_IFACE FIELD_ADDR(fields_if,0) 123596a8091Sjasper #define FLD_IF_STATE FIELD_ADDR(fields_if,1) 124596a8091Sjasper #define FLD_IF_IPKTS FIELD_ADDR(fields_if,2) 125596a8091Sjasper #define FLD_IF_IBYTES FIELD_ADDR(fields_if,3) 126596a8091Sjasper #define FLD_IF_IERRS FIELD_ADDR(fields_if,4) 127596a8091Sjasper #define FLD_IF_OPKTS FIELD_ADDR(fields_if,5) 128596a8091Sjasper #define FLD_IF_OBYTES FIELD_ADDR(fields_if,6) 129596a8091Sjasper #define FLD_IF_OERRS FIELD_ADDR(fields_if,7) 130596a8091Sjasper #define FLD_IF_COLLS FIELD_ADDR(fields_if,8) 131596a8091Sjasper #define FLD_IF_DESC FIELD_ADDR(fields_if,9) 13273baed14Scanacar 13373baed14Scanacar 13473baed14Scanacar /* Define views */ 13573baed14Scanacar field_def *view_if_0[] = { 1367d0bcf9cSderaadt FLD_IF_IFACE, FLD_IF_STATE, FLD_IF_DESC, FLD_IF_IPKTS, 1377d0bcf9cSderaadt FLD_IF_IBYTES, FLD_IF_IERRS, FLD_IF_OPKTS, FLD_IF_OBYTES, 1387d0bcf9cSderaadt FLD_IF_OERRS, FLD_IF_COLLS, NULL 13973baed14Scanacar }; 14073baed14Scanacar 14173baed14Scanacar /* Define view managers */ 14273baed14Scanacar 14373baed14Scanacar struct view_manager ifstat_mgr = { 14473baed14Scanacar "Ifstat", select_if, read_if, NULL, print_header, 14573baed14Scanacar print_if, if_keyboard_callback, NULL, NULL 14673baed14Scanacar }; 14773baed14Scanacar 14873baed14Scanacar field_view views_if[] = { 14973baed14Scanacar {view_if_0, "ifstat", '1', &ifstat_mgr}, 15073baed14Scanacar {NULL, NULL, 0, NULL} 15173baed14Scanacar }; 15273baed14Scanacar 1531612fc5aSmarkus 1541612fc5aSmarkus int 1551612fc5aSmarkus initifstat(void) 1561612fc5aSmarkus { 15773baed14Scanacar field_view *v; 15873baed14Scanacar read_if(); 15973baed14Scanacar for (v = views_if; v->name != NULL; v++) 16073baed14Scanacar add_view(v); 1611612fc5aSmarkus 1621612fc5aSmarkus return(1); 1631612fc5aSmarkus } 1641612fc5aSmarkus 1651612fc5aSmarkus #define UPDATE(x, y) do { \ 1663e4efdf5Sderaadt ifs->ifs_now.x = ifm.y; \ 1671612fc5aSmarkus ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \ 168e24b9d6eSdlg if (state == TIME) {\ 1691612fc5aSmarkus ifs->ifs_old.x = ifs->ifs_now.x; \ 170e24b9d6eSdlg ifs->ifs_cur.x /= naptime; \ 171e24b9d6eSdlg } \ 172e24b9d6eSdlg sum.x += ifs->ifs_cur.x; \ 1731612fc5aSmarkus } while(0) 1741612fc5aSmarkus 1751612fc5aSmarkus 1761612fc5aSmarkus void 1771612fc5aSmarkus rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info) 1781612fc5aSmarkus { 1791612fc5aSmarkus int i; 1801612fc5aSmarkus 1811612fc5aSmarkus for (i = 0; i < RTAX_MAX; i++) { 1821612fc5aSmarkus if (addrs & (1 << i)) { 1831612fc5aSmarkus info[i] = sa; 1841612fc5aSmarkus sa = (struct sockaddr *) ((char *)(sa) + 1851612fc5aSmarkus roundup(sa->sa_len, sizeof(long))); 1861612fc5aSmarkus } else 1871612fc5aSmarkus info[i] = NULL; 1881612fc5aSmarkus } 1891612fc5aSmarkus } 1901612fc5aSmarkus 19173baed14Scanacar 19273baed14Scanacar 19373baed14Scanacar int 19473baed14Scanacar select_if(void) 19573baed14Scanacar { 19673baed14Scanacar num_disp = num_ifs + 1; 19773baed14Scanacar return (0); 19873baed14Scanacar } 19973baed14Scanacar 20073baed14Scanacar int 20173baed14Scanacar read_if(void) 20273baed14Scanacar { 20373baed14Scanacar fetchifstat(); 20473baed14Scanacar num_disp = num_ifs + 1; 20573baed14Scanacar 20673baed14Scanacar return 0; 20773baed14Scanacar } 20873baed14Scanacar 2091612fc5aSmarkus void 21073baed14Scanacar print_if(void) 21173baed14Scanacar { 21273baed14Scanacar int n, i, count = 0; 21373baed14Scanacar 21473baed14Scanacar for (n = 0, i = 0; n < nifs; n++) { 21573baed14Scanacar if (ifstats[n].ifs_name[0] == '\0') 21673baed14Scanacar continue; 21773baed14Scanacar if (i++ < dispstart) 21873baed14Scanacar continue; 21973baed14Scanacar if (i == num_disp) 22073baed14Scanacar break; 22173baed14Scanacar showifstat(ifstats + n); 22273baed14Scanacar if (maxprint > 0 && ++count >= maxprint) 22373baed14Scanacar return; 22473baed14Scanacar } 22573baed14Scanacar showtotal(); 22673baed14Scanacar } 22773baed14Scanacar 22873baed14Scanacar 229f429edc3Sderaadt void 2301612fc5aSmarkus fetchifstat(void) 2311612fc5aSmarkus { 2321612fc5aSmarkus struct ifstat *newstats, *ifs; 2333e4efdf5Sderaadt struct if_msghdr ifm; 2341612fc5aSmarkus struct sockaddr *info[RTAX_MAX]; 2351612fc5aSmarkus struct sockaddr_dl *sdl; 2361612fc5aSmarkus char *buf, *next, *lim; 237d7c69161Scanacar int mib[6], i; 2381612fc5aSmarkus size_t need; 2391612fc5aSmarkus 2401612fc5aSmarkus mib[0] = CTL_NET; 241149dc9fcSguenther mib[1] = PF_ROUTE; 2421612fc5aSmarkus mib[2] = 0; 2431612fc5aSmarkus mib[3] = 0; 2441612fc5aSmarkus mib[4] = NET_RT_IFLIST; 2451612fc5aSmarkus mib[5] = 0; 2461612fc5aSmarkus 2471612fc5aSmarkus if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1) 2481612fc5aSmarkus return; 2491612fc5aSmarkus if ((buf = malloc(need)) == NULL) 2501612fc5aSmarkus return; 2511612fc5aSmarkus if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) { 2521612fc5aSmarkus free(buf); 2531612fc5aSmarkus return; 2541612fc5aSmarkus } 2551612fc5aSmarkus 2561612fc5aSmarkus bzero(&sum, sizeof(sum)); 25773baed14Scanacar num_ifs = 0; 2581612fc5aSmarkus 2591612fc5aSmarkus lim = buf + need; 2603e4efdf5Sderaadt for (next = buf; next < lim; next += ifm.ifm_msglen) { 2613e4efdf5Sderaadt bcopy(next, &ifm, sizeof ifm); 26277e759e9Sclaudio if (ifm.ifm_version != RTM_VERSION || 26377e759e9Sclaudio ifm.ifm_type != RTM_IFINFO || 2643e4efdf5Sderaadt !(ifm.ifm_addrs & RTA_IFP)) 2651612fc5aSmarkus continue; 2663e4efdf5Sderaadt if (ifm.ifm_index >= nifs) { 2677e81aea1Sdoug if ((newstats = reallocarray(ifstats, ifm.ifm_index + 4, 2687e81aea1Sdoug sizeof(struct ifstat))) == NULL) 2691612fc5aSmarkus continue; 2701612fc5aSmarkus ifstats = newstats; 2713e4efdf5Sderaadt for (; nifs < ifm.ifm_index + 4; nifs++) 27273baed14Scanacar bzero(&ifstats[nifs], sizeof(*ifstats)); 2731612fc5aSmarkus } 2743e4efdf5Sderaadt ifs = &ifstats[ifm.ifm_index]; 2751612fc5aSmarkus if (ifs->ifs_name[0] == '\0') { 2761612fc5aSmarkus bzero(&info, sizeof(info)); 2773e4efdf5Sderaadt rt_getaddrinfo( 2783e4efdf5Sderaadt (struct sockaddr *)((struct if_msghdr *)next + 1), 2793e4efdf5Sderaadt ifm.ifm_addrs, info); 2807d0bcf9cSderaadt sdl = (struct sockaddr_dl *)info[RTAX_IFP]; 2817d0bcf9cSderaadt 2827d0bcf9cSderaadt if (sdl && sdl->sdl_family == AF_LINK && 2834d152fbaSdlg sdl->sdl_nlen > 0) { 2847d0bcf9cSderaadt struct ifreq ifrdesc; 2857d0bcf9cSderaadt char ifdescr[IFDESCRSIZE]; 2867d0bcf9cSderaadt int s; 2877d0bcf9cSderaadt 2884d152fbaSdlg bcopy(sdl->sdl_data, ifs->ifs_name, 2894d152fbaSdlg sdl->sdl_nlen); 2904d152fbaSdlg ifs->ifs_name[sdl->sdl_nlen] = '\0'; 2917d0bcf9cSderaadt 2927d0bcf9cSderaadt /* Get the interface description */ 2937d0bcf9cSderaadt memset(&ifrdesc, 0, sizeof(ifrdesc)); 2947d0bcf9cSderaadt strlcpy(ifrdesc.ifr_name, ifs->ifs_name, 2957d0bcf9cSderaadt sizeof(ifrdesc.ifr_name)); 2967d0bcf9cSderaadt ifrdesc.ifr_data = (caddr_t)&ifdescr; 2977d0bcf9cSderaadt 2987d0bcf9cSderaadt s = socket(AF_INET, SOCK_DGRAM, 0); 2997d0bcf9cSderaadt if (s != -1) { 3007d0bcf9cSderaadt if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) 3017d0bcf9cSderaadt strlcpy(ifs->ifs_description, 3027d0bcf9cSderaadt ifrdesc.ifr_data, 3037d0bcf9cSderaadt sizeof(ifs->ifs_description)); 3047d0bcf9cSderaadt close(s); 3054d152fbaSdlg } 3061612fc5aSmarkus } 3071612fc5aSmarkus if (ifs->ifs_name[0] == '\0') 3081612fc5aSmarkus continue; 3091612fc5aSmarkus } 31073baed14Scanacar num_ifs++; 3111612fc5aSmarkus UPDATE(ifc_ip, ifm_data.ifi_ipackets); 3121612fc5aSmarkus UPDATE(ifc_ib, ifm_data.ifi_ibytes); 3131612fc5aSmarkus UPDATE(ifc_ie, ifm_data.ifi_ierrors); 314c5f96cb8Sdlg UPDATE(ifc_iq, ifm_data.ifi_iqdrops); 3151612fc5aSmarkus UPDATE(ifc_op, ifm_data.ifi_opackets); 3161612fc5aSmarkus UPDATE(ifc_ob, ifm_data.ifi_obytes); 3171612fc5aSmarkus UPDATE(ifc_oe, ifm_data.ifi_oerrors); 318c5f96cb8Sdlg UPDATE(ifc_oq, ifm_data.ifi_oqdrops); 3191612fc5aSmarkus UPDATE(ifc_co, ifm_data.ifi_collisions); 32050de0d1bSclaudio ifs->ifs_cur.ifc_flags = ifm.ifm_flags; 32150de0d1bSclaudio ifs->ifs_cur.ifc_state = ifm.ifm_data.ifi_link_state; 322d7c69161Scanacar ifs->ifs_flag++; 3231612fc5aSmarkus } 324d7c69161Scanacar 325d7c69161Scanacar /* remove unreferenced interfaces */ 326d7c69161Scanacar for (i = 0; i < nifs; i++) { 327d7c69161Scanacar ifs = &ifstats[i]; 328d7c69161Scanacar if (ifs->ifs_flag) 329d7c69161Scanacar ifs->ifs_flag = 0; 330d7c69161Scanacar else 331d7c69161Scanacar ifs->ifs_name[0] = '\0'; 332d7c69161Scanacar } 333d7c69161Scanacar 3341612fc5aSmarkus free(buf); 3351612fc5aSmarkus } 3361612fc5aSmarkus 3371612fc5aSmarkus 33873baed14Scanacar static void 33973baed14Scanacar showifstat(struct ifstat *ifs) 3401612fc5aSmarkus { 3415c280c62Smpf int conv = show_bits ? 8 : 1; 3425c280c62Smpf int div = show_bits ? 1000 : 1024; 3435c280c62Smpf 34473baed14Scanacar print_fld_str(FLD_IF_IFACE, ifs->ifs_name); 3451612fc5aSmarkus 34673baed14Scanacar tb_start(); 34773baed14Scanacar tbprintf("%s", ifs->ifs_cur.ifc_flags & IFF_UP ? 34873baed14Scanacar "up" : "dn"); 3491612fc5aSmarkus 35073baed14Scanacar switch (ifs->ifs_cur.ifc_state) { 35150de0d1bSclaudio case LINK_STATE_UP: 35230762738Sreyk case LINK_STATE_HALF_DUPLEX: 35330762738Sreyk case LINK_STATE_FULL_DUPLEX: 35473baed14Scanacar tbprintf(":U"); 35573baed14Scanacar break; 35650de0d1bSclaudio case LINK_STATE_DOWN: 35773baed14Scanacar tbprintf (":D"); 35873baed14Scanacar break; 35950de0d1bSclaudio } 3601612fc5aSmarkus 36173baed14Scanacar print_fld_tb(FLD_IF_STATE); 36273baed14Scanacar 3637d0bcf9cSderaadt print_fld_str(FLD_IF_DESC, ifs->ifs_description); 3647d0bcf9cSderaadt 3655c280c62Smpf print_fld_sdiv(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib * conv, div); 36673baed14Scanacar print_fld_size(FLD_IF_IPKTS, ifs->ifs_cur.ifc_ip); 367c5f96cb8Sdlg print_fld_size(FLD_IF_IERRS, if_err_view->icount(&ifs->ifs_cur)); 36873baed14Scanacar 3695c280c62Smpf print_fld_sdiv(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob * conv, div); 37073baed14Scanacar print_fld_size(FLD_IF_OPKTS, ifs->ifs_cur.ifc_op); 371c5f96cb8Sdlg print_fld_size(FLD_IF_OERRS, if_err_view->ocount(&ifs->ifs_cur)); 37273baed14Scanacar 37373baed14Scanacar print_fld_size(FLD_IF_COLLS, ifs->ifs_cur.ifc_co); 37473baed14Scanacar 37573baed14Scanacar end_line(); 37673baed14Scanacar } 37773baed14Scanacar 37873baed14Scanacar static void 37973baed14Scanacar showtotal(void) 3801612fc5aSmarkus { 3815c280c62Smpf int conv = show_bits ? 8 : 1; 3825c280c62Smpf int div = show_bits ? 1000 : 1024; 3835c280c62Smpf 38473baed14Scanacar print_fld_str(FLD_IF_IFACE, "Totals"); 3851612fc5aSmarkus 3865c280c62Smpf print_fld_sdiv(FLD_IF_IBYTES, sum.ifc_ib * conv, div); 38773baed14Scanacar print_fld_size(FLD_IF_IPKTS, sum.ifc_ip); 388c5f96cb8Sdlg print_fld_size(FLD_IF_IERRS, if_err_view->icount(&sum)); 38973baed14Scanacar 3905c280c62Smpf print_fld_sdiv(FLD_IF_OBYTES, sum.ifc_ob * conv, div); 39173baed14Scanacar print_fld_size(FLD_IF_OPKTS, sum.ifc_op); 392c5f96cb8Sdlg print_fld_size(FLD_IF_OERRS, if_err_view->ocount(&sum)); 39373baed14Scanacar 39473baed14Scanacar print_fld_size(FLD_IF_COLLS, sum.ifc_co); 39573baed14Scanacar 39673baed14Scanacar end_line(); 39773baed14Scanacar 3981612fc5aSmarkus } 3991612fc5aSmarkus 400c5f96cb8Sdlg static uint64_t 401c5f96cb8Sdlg if_err_ifails(const struct ifcount *ifc) 402c5f96cb8Sdlg { 403c5f96cb8Sdlg return (ifc->ifc_ie + ifc->ifc_iq); 404c5f96cb8Sdlg } 405c5f96cb8Sdlg 406c5f96cb8Sdlg static uint64_t 407c5f96cb8Sdlg if_err_ofails(const struct ifcount *ifc) 408c5f96cb8Sdlg { 409c5f96cb8Sdlg return (ifc->ifc_oe + ifc->ifc_oq); 410c5f96cb8Sdlg } 411c5f96cb8Sdlg 412c5f96cb8Sdlg static uint64_t 413c5f96cb8Sdlg if_err_ierrors(const struct ifcount *ifc) 414c5f96cb8Sdlg { 415c5f96cb8Sdlg return (ifc->ifc_ie); 416c5f96cb8Sdlg } 417c5f96cb8Sdlg 418c5f96cb8Sdlg static uint64_t 419c5f96cb8Sdlg if_err_oerrors(const struct ifcount *ifc) 420c5f96cb8Sdlg { 421c5f96cb8Sdlg return (ifc->ifc_oe); 422c5f96cb8Sdlg } 423c5f96cb8Sdlg 424c5f96cb8Sdlg static uint64_t 425c5f96cb8Sdlg if_err_iqdrops(const struct ifcount *ifc) 426c5f96cb8Sdlg { 427c5f96cb8Sdlg return (ifc->ifc_iq); 428c5f96cb8Sdlg } 429c5f96cb8Sdlg 430c5f96cb8Sdlg static uint64_t 431c5f96cb8Sdlg if_err_oqdrops(const struct ifcount *ifc) 432c5f96cb8Sdlg { 433c5f96cb8Sdlg return (ifc->ifc_oq); 434c5f96cb8Sdlg } 435c5f96cb8Sdlg 436c5f96cb8Sdlg static void 437c5f96cb8Sdlg if_set_errs(unsigned int v) 438c5f96cb8Sdlg { 439c5f96cb8Sdlg if_err_view = &if_err_views[v]; 440c5f96cb8Sdlg FLD_IF_IERRS->title = if_err_view->iname; 441d7dbde78Sdlg FLD_IF_OERRS->title = if_err_view->oname; 442c5f96cb8Sdlg gotsig_alarm = 1; 443c5f96cb8Sdlg } 444c5f96cb8Sdlg 4451612fc5aSmarkus int 44673baed14Scanacar if_keyboard_callback(int ch) 4471612fc5aSmarkus { 4481612fc5aSmarkus struct ifstat *ifs; 4491612fc5aSmarkus 45073baed14Scanacar switch (ch) { 451c5f96cb8Sdlg case 'd': 452c5f96cb8Sdlg if_set_errs(IF_ERR_QDROPS); 453c5f96cb8Sdlg break; 454c5f96cb8Sdlg case 'e': 455c5f96cb8Sdlg if_set_errs(IF_ERR_ERRORS); 456c5f96cb8Sdlg break; 457c5f96cb8Sdlg case 'f': 458c5f96cb8Sdlg if_set_errs(IF_ERR_SUM); 459c5f96cb8Sdlg break; 460c5f96cb8Sdlg 46173baed14Scanacar case 'r': 4621612fc5aSmarkus for (ifs = ifstats; ifs < ifstats + nifs; ifs++) 4631612fc5aSmarkus ifs->ifs_old = ifs->ifs_now; 4641612fc5aSmarkus state = RUN; 46573baed14Scanacar gotsig_alarm = 1; 46673baed14Scanacar 46773baed14Scanacar break; 46873baed14Scanacar case 'b': 4691612fc5aSmarkus state = BOOT; 4701612fc5aSmarkus for (ifs = ifstats; ifs < ifstats + nifs; ifs++) 4711612fc5aSmarkus bzero(&ifs->ifs_old, sizeof(ifs->ifs_old)); 47273baed14Scanacar gotsig_alarm = 1; 47373baed14Scanacar break; 4745c280c62Smpf case 'B': 4755c280c62Smpf show_bits = !show_bits; 4765c280c62Smpf if (show_bits) { 4775c280c62Smpf FLD_IF_IBYTES->title = "IBITS"; 4785c280c62Smpf FLD_IF_OBYTES->title = "OBITS"; 4795c280c62Smpf } else { 4805c280c62Smpf FLD_IF_IBYTES->title = "IBYTES"; 4815c280c62Smpf FLD_IF_OBYTES->title = "OBYTES"; 4825c280c62Smpf } 4835c280c62Smpf gotsig_alarm = 1; 4845c280c62Smpf break; 48573baed14Scanacar case 't': 4861612fc5aSmarkus state = TIME; 48773baed14Scanacar gotsig_alarm = 1; 48873baed14Scanacar break; 48973baed14Scanacar default: 49073baed14Scanacar return keyboard_callback(ch); 491*479c151dSjsg } 49273baed14Scanacar 49373baed14Scanacar return 1; 4941612fc5aSmarkus } 49573baed14Scanacar 496