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
initifstat(void)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
rt_getaddrinfo(struct sockaddr * sa,int addrs,struct sockaddr ** info)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
select_if(void)19473baed14Scanacar select_if(void)
19573baed14Scanacar {
19673baed14Scanacar num_disp = num_ifs + 1;
19773baed14Scanacar return (0);
19873baed14Scanacar }
19973baed14Scanacar
20073baed14Scanacar int
read_if(void)20173baed14Scanacar read_if(void)
20273baed14Scanacar {
20373baed14Scanacar fetchifstat();
20473baed14Scanacar num_disp = num_ifs + 1;
20573baed14Scanacar
20673baed14Scanacar return 0;
20773baed14Scanacar }
20873baed14Scanacar
2091612fc5aSmarkus void
print_if(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
fetchifstat(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
showifstat(struct ifstat * ifs)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
showtotal(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
if_err_ifails(const struct ifcount * ifc)401c5f96cb8Sdlg if_err_ifails(const struct ifcount *ifc)
402c5f96cb8Sdlg {
403c5f96cb8Sdlg return (ifc->ifc_ie + ifc->ifc_iq);
404c5f96cb8Sdlg }
405c5f96cb8Sdlg
406c5f96cb8Sdlg static uint64_t
if_err_ofails(const struct ifcount * ifc)407c5f96cb8Sdlg if_err_ofails(const struct ifcount *ifc)
408c5f96cb8Sdlg {
409c5f96cb8Sdlg return (ifc->ifc_oe + ifc->ifc_oq);
410c5f96cb8Sdlg }
411c5f96cb8Sdlg
412c5f96cb8Sdlg static uint64_t
if_err_ierrors(const struct ifcount * ifc)413c5f96cb8Sdlg if_err_ierrors(const struct ifcount *ifc)
414c5f96cb8Sdlg {
415c5f96cb8Sdlg return (ifc->ifc_ie);
416c5f96cb8Sdlg }
417c5f96cb8Sdlg
418c5f96cb8Sdlg static uint64_t
if_err_oerrors(const struct ifcount * ifc)419c5f96cb8Sdlg if_err_oerrors(const struct ifcount *ifc)
420c5f96cb8Sdlg {
421c5f96cb8Sdlg return (ifc->ifc_oe);
422c5f96cb8Sdlg }
423c5f96cb8Sdlg
424c5f96cb8Sdlg static uint64_t
if_err_iqdrops(const struct ifcount * ifc)425c5f96cb8Sdlg if_err_iqdrops(const struct ifcount *ifc)
426c5f96cb8Sdlg {
427c5f96cb8Sdlg return (ifc->ifc_iq);
428c5f96cb8Sdlg }
429c5f96cb8Sdlg
430c5f96cb8Sdlg static uint64_t
if_err_oqdrops(const struct ifcount * ifc)431c5f96cb8Sdlg if_err_oqdrops(const struct ifcount *ifc)
432c5f96cb8Sdlg {
433c5f96cb8Sdlg return (ifc->ifc_oq);
434c5f96cb8Sdlg }
435c5f96cb8Sdlg
436c5f96cb8Sdlg static void
if_set_errs(unsigned int v)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
if_keyboard_callback(int ch)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