Annotation of src/usr.bin/systat/if.c, Revision 1.7
1.7 ! claudio 1: /* $OpenBSD: if.c,v 1.6 2006/03/31 18:19:44 deraadt Exp $ */
1.1 markus 2: /*
3: * Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <sys/param.h>
18: #include <sys/types.h>
19: #include <sys/socket.h>
20: #include <sys/sysctl.h>
21: #include <net/if.h>
22: #include <net/if_dl.h>
23: #include <net/route.h>
24:
25: #include <stdlib.h>
1.5 deraadt 26: #include <string.h>
1.1 markus 27:
28: #include "systat.h"
29: #include "extern.h"
30:
31: static enum state { BOOT, TIME, RUN } state = TIME;
32:
33: struct ifcount {
34: u_long ifc_ib; /* input bytes */
35: u_long ifc_ip; /* input packets */
36: u_long ifc_ie; /* input errors */
37: u_long ifc_ob; /* output bytes */
38: u_long ifc_op; /* output packets */
39: u_long ifc_oe; /* output errors */
40: u_long ifc_co; /* collisions */
1.7 ! claudio 41: int ifc_flags; /* up / down */
! 42: int ifc_state; /* link state */
1.1 markus 43: } sum;
44:
45: struct ifstat {
46: char ifs_name[IFNAMSIZ]; /* interface name */
47: struct ifcount ifs_cur;
48: struct ifcount ifs_old;
49: struct ifcount ifs_now;
50: } *ifstats;
51:
52: static int nifs = 0;
1.5 deraadt 53: extern u_int naptime;
1.1 markus 54:
1.7 ! claudio 55: const char *showlinkstate(int);
! 56:
1.1 markus 57: WINDOW *
58: openifstat(void)
59: {
60:
61: return (subwin(stdscr, LINES-5-1, 0, 5, 0));
62: }
63:
64: void
65: closeifstat(WINDOW *w)
66: {
67:
68: if (w == NULL)
69: return;
70: wclear(w);
71: wrefresh(w);
72: delwin(w);
73: }
74:
75: int
76: initifstat(void)
77: {
78:
79: fetchifstat();
80: return(1);
81: }
82:
83: #define UPDATE(x, y) do { \
1.2 deraadt 84: ifs->ifs_now.x = ifm.y; \
1.1 markus 85: ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \
1.4 dlg 86: if (state == TIME) {\
87: ifs->ifs_old.x = ifs->ifs_now.x; \
88: ifs->ifs_cur.x /= naptime; \
89: } \
1.1 markus 90: sum.x += ifs->ifs_cur.x; \
91: } while(0)
92:
93:
94: void
95: rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
96: {
97: int i;
98:
99: for (i = 0; i < RTAX_MAX; i++) {
100: if (addrs & (1 << i)) {
101: info[i] = sa;
102: sa = (struct sockaddr *) ((char *)(sa) +
103: roundup(sa->sa_len, sizeof(long)));
104: } else
105: info[i] = NULL;
106: }
107: }
108:
109: void
110: fetchifstat(void)
111: {
112: struct ifstat *newstats, *ifs;
1.2 deraadt 113: struct if_msghdr ifm;
1.1 markus 114: struct sockaddr *info[RTAX_MAX];
115: struct sockaddr_dl *sdl;
116: char *buf, *next, *lim;
1.5 deraadt 117: int mib[6];
1.1 markus 118: size_t need;
119:
120: mib[0] = CTL_NET;
121: mib[1] = AF_ROUTE;
122: mib[2] = 0;
123: mib[3] = 0;
124: mib[4] = NET_RT_IFLIST;
125: mib[5] = 0;
126:
127: if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1)
128: return;
129: if ((buf = malloc(need)) == NULL)
130: return;
131: if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) {
132: free(buf);
133: return;
134: }
135:
136: bzero(&sum, sizeof(sum));
137:
138: lim = buf + need;
1.2 deraadt 139: for (next = buf; next < lim; next += ifm.ifm_msglen) {
140: bcopy(next, &ifm, sizeof ifm);
141: if (ifm.ifm_type != RTM_IFINFO ||
142: !(ifm.ifm_addrs & RTA_IFP))
1.1 markus 143: continue;
1.2 deraadt 144: if (ifm.ifm_index >= nifs) {
145: if ((newstats = realloc(ifstats, (ifm.ifm_index + 4) *
1.1 markus 146: sizeof(struct ifstat))) == NULL)
147: continue;
148: ifstats = newstats;
1.2 deraadt 149: for (; nifs < ifm.ifm_index + 4; nifs++)
1.1 markus 150: ifstats[nifs].ifs_name[0] = '\0';
151: }
1.2 deraadt 152: ifs = &ifstats[ifm.ifm_index];
1.1 markus 153: if (ifs->ifs_name[0] == '\0') {
154: bzero(&info, sizeof(info));
1.2 deraadt 155: rt_getaddrinfo(
156: (struct sockaddr *)((struct if_msghdr *)next + 1),
157: ifm.ifm_addrs, info);
1.1 markus 158: if ((sdl = (struct sockaddr_dl *)info[RTAX_IFP])) {
159: if (sdl->sdl_family == AF_LINK &&
1.3 dlg 160: sdl->sdl_nlen > 0) {
161: bcopy(sdl->sdl_data, ifs->ifs_name,
162: sdl->sdl_nlen);
163: ifs->ifs_name[sdl->sdl_nlen] = '\0';
164: }
1.1 markus 165: }
166: if (ifs->ifs_name[0] == '\0')
167: continue;
168: }
169: UPDATE(ifc_ip, ifm_data.ifi_ipackets);
170: UPDATE(ifc_ib, ifm_data.ifi_ibytes);
171: UPDATE(ifc_ie, ifm_data.ifi_ierrors);
172: UPDATE(ifc_op, ifm_data.ifi_opackets);
173: UPDATE(ifc_ob, ifm_data.ifi_obytes);
174: UPDATE(ifc_oe, ifm_data.ifi_oerrors);
175: UPDATE(ifc_co, ifm_data.ifi_collisions);
1.7 ! claudio 176: ifs->ifs_cur.ifc_flags = ifm.ifm_flags;
! 177: ifs->ifs_cur.ifc_state = ifm.ifm_data.ifi_link_state;
1.1 markus 178: }
179: free(buf);
180: }
181:
182: #define INSET 0
183:
184: void
185: labelifstat(void)
186: {
187:
1.5 deraadt 188: wmove(wnd, 0, 0);
189: wclrtobot(wnd);
1.1 markus 190:
1.7 ! claudio 191: mvwaddstr(wnd, 1, INSET, "Iface");
! 192: mvwaddstr(wnd, 1, INSET+9, "State");
! 193: mvwaddstr(wnd, 1, INSET+19, "Ibytes");
! 194: mvwaddstr(wnd, 1, INSET+29, "Ipkts");
! 195: mvwaddstr(wnd, 1, INSET+36, "Ierrs");
! 196: mvwaddstr(wnd, 1, INSET+48, "Obytes");
1.1 markus 197: mvwaddstr(wnd, 1, INSET+58, "Opkts");
198: mvwaddstr(wnd, 1, INSET+65, "Oerrs");
199: mvwaddstr(wnd, 1, INSET+74, "Colls");
200: }
201:
1.7 ! claudio 202: #define FMT "%-8.8s %2s%2s %10lu %8lu %6lu %10lu %8lu %6lu %6lu "
! 203:
! 204: const char *
! 205: showlinkstate(int state)
! 206: {
! 207: switch (state) {
! 208: case LINK_STATE_UP:
! 209: return (":U");
! 210: case LINK_STATE_DOWN:
! 211: return (":D");
! 212: case LINK_STATE_UNKNOWN:
! 213: return ("");
! 214: }
! 215: }
1.6 deraadt 216:
1.1 markus 217: void
218: showifstat(void)
219: {
220: int row;
221: struct ifstat *ifs;
222:
223: row = 2;
1.5 deraadt 224: wmove(wnd, 0, 0);
225: wclrtoeol(wnd);
1.1 markus 226: for (ifs = ifstats; ifs < ifstats + nifs; ifs++) {
227: if (ifs->ifs_name[0] == '\0')
228: continue;
229: mvwprintw(wnd, row++, INSET, FMT,
230: ifs->ifs_name,
1.7 ! claudio 231: ifs->ifs_cur.ifc_flags & IFF_UP ? "up" : "dn",
! 232: showlinkstate(ifs->ifs_cur.ifc_state),
1.1 markus 233: ifs->ifs_cur.ifc_ib,
234: ifs->ifs_cur.ifc_ip,
235: ifs->ifs_cur.ifc_ie,
236: ifs->ifs_cur.ifc_ob,
237: ifs->ifs_cur.ifc_op,
238: ifs->ifs_cur.ifc_oe,
239: ifs->ifs_cur.ifc_co);
240: }
241: mvwprintw(wnd, row++, INSET, FMT,
242: "Totals",
1.7 ! claudio 243: "", "",
1.1 markus 244: sum.ifc_ib,
245: sum.ifc_ip,
246: sum.ifc_ie,
247: sum.ifc_ob,
248: sum.ifc_op,
249: sum.ifc_oe,
250: sum.ifc_co);
251: }
252:
253: int
254: cmdifstat(char *cmd, char *args)
255: {
256: struct ifstat *ifs;
257:
258: if (prefix(cmd, "run")) {
259: if (state != RUN)
260: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
261: ifs->ifs_old = ifs->ifs_now;
262: state = RUN;
263: return (1);
264: }
265: if (prefix(cmd, "boot")) {
266: state = BOOT;
267: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
268: bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
269: return (1);
270: }
271: if (prefix(cmd, "time")) {
272: state = TIME;
273: return (1);
274: }
275: if (prefix(cmd, "zero")) {
276: if (state == RUN)
277: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
278: ifs->ifs_old = ifs->ifs_now;
279: return (1);
280: }
281: return (1);
282: }