Annotation of src/usr.bin/systat/if.c, Revision 1.6
1.6 ! deraadt 1: /* $OpenBSD: if.c,v 1.5 2006/03/31 04:10:59 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 */
41: } sum;
42:
43: struct ifstat {
44: char ifs_name[IFNAMSIZ]; /* interface name */
45: struct ifcount ifs_cur;
46: struct ifcount ifs_old;
47: struct ifcount ifs_now;
48: } *ifstats;
49:
50: static int nifs = 0;
1.5 deraadt 51: extern u_int naptime;
1.1 markus 52:
53: WINDOW *
54: openifstat(void)
55: {
56:
57: return (subwin(stdscr, LINES-5-1, 0, 5, 0));
58: }
59:
60: void
61: closeifstat(WINDOW *w)
62: {
63:
64: if (w == NULL)
65: return;
66: wclear(w);
67: wrefresh(w);
68: delwin(w);
69: }
70:
71: int
72: initifstat(void)
73: {
74:
75: fetchifstat();
76: return(1);
77: }
78:
79: #define UPDATE(x, y) do { \
1.2 deraadt 80: ifs->ifs_now.x = ifm.y; \
1.1 markus 81: ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \
1.4 dlg 82: if (state == TIME) {\
83: ifs->ifs_old.x = ifs->ifs_now.x; \
84: ifs->ifs_cur.x /= naptime; \
85: } \
1.1 markus 86: sum.x += ifs->ifs_cur.x; \
87: } while(0)
88:
89:
90: void
91: rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
92: {
93: int i;
94:
95: for (i = 0; i < RTAX_MAX; i++) {
96: if (addrs & (1 << i)) {
97: info[i] = sa;
98: sa = (struct sockaddr *) ((char *)(sa) +
99: roundup(sa->sa_len, sizeof(long)));
100: } else
101: info[i] = NULL;
102: }
103: }
104:
105: void
106: fetchifstat(void)
107: {
108: struct ifstat *newstats, *ifs;
1.2 deraadt 109: struct if_msghdr ifm;
1.1 markus 110: struct sockaddr *info[RTAX_MAX];
111: struct sockaddr_dl *sdl;
112: char *buf, *next, *lim;
1.5 deraadt 113: int mib[6];
1.1 markus 114: size_t need;
115:
116: mib[0] = CTL_NET;
117: mib[1] = AF_ROUTE;
118: mib[2] = 0;
119: mib[3] = 0;
120: mib[4] = NET_RT_IFLIST;
121: mib[5] = 0;
122:
123: if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1)
124: return;
125: if ((buf = malloc(need)) == NULL)
126: return;
127: if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) {
128: free(buf);
129: return;
130: }
131:
132: bzero(&sum, sizeof(sum));
133:
134: lim = buf + need;
1.2 deraadt 135: for (next = buf; next < lim; next += ifm.ifm_msglen) {
136: bcopy(next, &ifm, sizeof ifm);
137: if (ifm.ifm_type != RTM_IFINFO ||
138: !(ifm.ifm_addrs & RTA_IFP))
1.1 markus 139: continue;
1.2 deraadt 140: if (ifm.ifm_index >= nifs) {
141: if ((newstats = realloc(ifstats, (ifm.ifm_index + 4) *
1.1 markus 142: sizeof(struct ifstat))) == NULL)
143: continue;
144: ifstats = newstats;
1.2 deraadt 145: for (; nifs < ifm.ifm_index + 4; nifs++)
1.1 markus 146: ifstats[nifs].ifs_name[0] = '\0';
147: }
1.2 deraadt 148: ifs = &ifstats[ifm.ifm_index];
1.1 markus 149: if (ifs->ifs_name[0] == '\0') {
150: bzero(&info, sizeof(info));
1.2 deraadt 151: rt_getaddrinfo(
152: (struct sockaddr *)((struct if_msghdr *)next + 1),
153: ifm.ifm_addrs, info);
1.1 markus 154: if ((sdl = (struct sockaddr_dl *)info[RTAX_IFP])) {
155: if (sdl->sdl_family == AF_LINK &&
1.3 dlg 156: sdl->sdl_nlen > 0) {
157: bcopy(sdl->sdl_data, ifs->ifs_name,
158: sdl->sdl_nlen);
159: ifs->ifs_name[sdl->sdl_nlen] = '\0';
160: }
1.1 markus 161: }
162: if (ifs->ifs_name[0] == '\0')
163: continue;
164: }
165: UPDATE(ifc_ip, ifm_data.ifi_ipackets);
166: UPDATE(ifc_ib, ifm_data.ifi_ibytes);
167: UPDATE(ifc_ie, ifm_data.ifi_ierrors);
168: UPDATE(ifc_op, ifm_data.ifi_opackets);
169: UPDATE(ifc_ob, ifm_data.ifi_obytes);
170: UPDATE(ifc_oe, ifm_data.ifi_oerrors);
171: UPDATE(ifc_co, ifm_data.ifi_collisions);
172: }
173: free(buf);
174: }
175:
176: #define INSET 0
177:
178: void
179: labelifstat(void)
180: {
181:
1.5 deraadt 182: wmove(wnd, 0, 0);
183: wclrtobot(wnd);
1.1 markus 184:
185: mvwaddstr(wnd, 1, INSET, "Interfaces");
186: mvwaddstr(wnd, 1, INSET+15, "Ibytes");
187: mvwaddstr(wnd, 1, INSET+27, "Ipkts");
188: mvwaddstr(wnd, 1, INSET+34, "Ierrs");
189: mvwaddstr(wnd, 1, INSET+46, "Obytes");
190: mvwaddstr(wnd, 1, INSET+58, "Opkts");
191: mvwaddstr(wnd, 1, INSET+65, "Oerrs");
192: mvwaddstr(wnd, 1, INSET+74, "Colls");
193: }
194:
195: #define FMT "%-10.10s %10lu %10lu %6lu %10lu %10lu %6lu %6lu "
1.6 ! deraadt 196:
1.1 markus 197: void
198: showifstat(void)
199: {
200: int row;
201: struct ifstat *ifs;
202:
203: row = 2;
1.5 deraadt 204: wmove(wnd, 0, 0);
205: wclrtoeol(wnd);
1.1 markus 206: for (ifs = ifstats; ifs < ifstats + nifs; ifs++) {
207: if (ifs->ifs_name[0] == '\0')
208: continue;
209: mvwprintw(wnd, row++, INSET, FMT,
210: ifs->ifs_name,
211: ifs->ifs_cur.ifc_ib,
212: ifs->ifs_cur.ifc_ip,
213: ifs->ifs_cur.ifc_ie,
214: ifs->ifs_cur.ifc_ob,
215: ifs->ifs_cur.ifc_op,
216: ifs->ifs_cur.ifc_oe,
217: ifs->ifs_cur.ifc_co);
218: }
219: mvwprintw(wnd, row++, INSET, FMT,
220: "Totals",
221: sum.ifc_ib,
222: sum.ifc_ip,
223: sum.ifc_ie,
224: sum.ifc_ob,
225: sum.ifc_op,
226: sum.ifc_oe,
227: sum.ifc_co);
228: }
229:
230: int
231: cmdifstat(char *cmd, char *args)
232: {
233: struct ifstat *ifs;
234:
235: if (prefix(cmd, "run")) {
236: if (state != RUN)
237: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
238: ifs->ifs_old = ifs->ifs_now;
239: state = RUN;
240: return (1);
241: }
242: if (prefix(cmd, "boot")) {
243: state = BOOT;
244: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
245: bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
246: return (1);
247: }
248: if (prefix(cmd, "time")) {
249: state = TIME;
250: return (1);
251: }
252: if (prefix(cmd, "zero")) {
253: if (state == RUN)
254: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
255: ifs->ifs_old = ifs->ifs_now;
256: return (1);
257: }
258: return (1);
259: }