Annotation of src/usr.bin/systat/if.c, Revision 1.9
1.9 ! deraadt 1: /* $OpenBSD: if.c,v 1.8 2006/11/28 19:21:15 reyk 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:
1.9 ! deraadt 61: return (subwin(stdscr, LINES-1-1, 0, 1, 0));
1.1 markus 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:
1.8 reyk 209: case LINK_STATE_HALF_DUPLEX:
210: case LINK_STATE_FULL_DUPLEX:
1.7 claudio 211: return (":U");
212: case LINK_STATE_DOWN:
213: return (":D");
214: case LINK_STATE_UNKNOWN:
1.9 ! deraadt 215: default:
1.7 claudio 216: return ("");
217: }
218: }
1.6 deraadt 219:
1.1 markus 220: void
221: showifstat(void)
222: {
223: int row;
224: struct ifstat *ifs;
225:
226: row = 2;
1.5 deraadt 227: wmove(wnd, 0, 0);
228: wclrtoeol(wnd);
1.1 markus 229: for (ifs = ifstats; ifs < ifstats + nifs; ifs++) {
230: if (ifs->ifs_name[0] == '\0')
231: continue;
232: mvwprintw(wnd, row++, INSET, FMT,
233: ifs->ifs_name,
1.7 claudio 234: ifs->ifs_cur.ifc_flags & IFF_UP ? "up" : "dn",
235: showlinkstate(ifs->ifs_cur.ifc_state),
1.1 markus 236: ifs->ifs_cur.ifc_ib,
237: ifs->ifs_cur.ifc_ip,
238: ifs->ifs_cur.ifc_ie,
239: ifs->ifs_cur.ifc_ob,
240: ifs->ifs_cur.ifc_op,
241: ifs->ifs_cur.ifc_oe,
242: ifs->ifs_cur.ifc_co);
243: }
244: mvwprintw(wnd, row++, INSET, FMT,
245: "Totals",
1.7 claudio 246: "", "",
1.1 markus 247: sum.ifc_ib,
248: sum.ifc_ip,
249: sum.ifc_ie,
250: sum.ifc_ob,
251: sum.ifc_op,
252: sum.ifc_oe,
253: sum.ifc_co);
254: }
255:
256: int
257: cmdifstat(char *cmd, char *args)
258: {
259: struct ifstat *ifs;
260:
261: if (prefix(cmd, "run")) {
262: if (state != RUN)
263: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
264: ifs->ifs_old = ifs->ifs_now;
265: state = RUN;
266: return (1);
267: }
268: if (prefix(cmd, "boot")) {
269: state = BOOT;
270: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
271: bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
272: return (1);
273: }
274: if (prefix(cmd, "time")) {
275: state = TIME;
276: return (1);
277: }
278: if (prefix(cmd, "zero")) {
279: if (state == RUN)
280: for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
281: ifs->ifs_old = ifs->ifs_now;
282: return (1);
283: }
284: return (1);
285: }