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