Annotation of src/usr.bin/netstat/if.c, Revision 1.1.1.1
1.1 deraadt 1: /* $NetBSD: if.c,v 1.13 1995/10/03 21:42:36 thorpej Exp $ */
2:
3: /*
4: * Copyright (c) 1983, 1988, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: #if 0
38: static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
39: #else
40: static char *rcsid = "$NetBSD: if.c,v 1.13 1995/10/03 21:42:36 thorpej Exp $";
41: #endif
42: #endif /* not lint */
43:
44: #include <sys/types.h>
45: #include <sys/protosw.h>
46: #include <sys/socket.h>
47:
48: #include <net/if.h>
49: #include <net/if_dl.h>
50: #include <netinet/in.h>
51: #include <netinet/in_var.h>
52: #include <netns/ns.h>
53: #include <netns/ns_if.h>
54: #include <netiso/iso.h>
55: #include <netiso/iso_var.h>
56: #include <arpa/inet.h>
57:
58: #include <signal.h>
59: #include <stdio.h>
60: #include <string.h>
61: #include <unistd.h>
62:
63: #include "netstat.h"
64:
65: #define YES 1
66: #define NO 0
67:
68: static void sidewaysintpr __P((u_int, u_long));
69: static void catchalarm __P((int));
70:
71: /*
72: * Print a description of the network interfaces.
73: */
74: void
75: intpr(interval, ifnetaddr)
76: int interval;
77: u_long ifnetaddr;
78: {
79: struct ifnet ifnet;
80: union {
81: struct ifaddr ifa;
82: struct in_ifaddr in;
83: struct ns_ifaddr ns;
84: struct iso_ifaddr iso;
85: } ifaddr;
86: u_long ifaddraddr;
87: struct sockaddr *sa;
88: char name[16];
89:
90: if (ifnetaddr == 0) {
91: printf("ifnet: symbol not defined\n");
92: return;
93: }
94: if (interval) {
95: sidewaysintpr((unsigned)interval, ifnetaddr);
96: return;
97: }
98: if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
99: return;
100: printf("%-5.5s %-5.5s %-11.11s %-15.15s %10.10s %5.5s %8.8s %5.5s",
101: "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
102: "Opkts", "Oerrs");
103: printf(" %5s", "Coll");
104: if (tflag)
105: printf(" %s", "Time");
106: if (dflag)
107: printf(" %s", "Drop");
108: putchar('\n');
109: ifaddraddr = 0;
110: while (ifnetaddr || ifaddraddr) {
111: struct sockaddr_in *sin;
112: register char *cp;
113: int n, m;
114:
115: if (ifaddraddr == 0) {
116: if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
117: kread((u_long)ifnet.if_name, name, 16))
118: return;
119: name[15] = '\0';
120: ifnetaddr = (u_long)ifnet.if_list.tqe_next;
121: if (interface != 0 && (strcmp(name, interface) != 0 ||
122: unit != ifnet.if_unit))
123: continue;
124: cp = index(name, '\0');
125: cp += sprintf(cp, "%d", ifnet.if_unit);
126: if ((ifnet.if_flags & IFF_UP) == 0)
127: *cp++ = '*';
128: *cp = '\0';
129: ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
130: }
131: printf("%-5.5s %-5d ", name, ifnet.if_mtu);
132: if (ifaddraddr == 0) {
133: printf("%-11.11s ", "none");
134: printf("%-15.15s ", "none");
135: } else {
136: if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
137: ifaddraddr = 0;
138: continue;
139: }
140: #define CP(x) ((char *)(x))
141: cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
142: CP(&ifaddr); sa = (struct sockaddr *)cp;
143: switch (sa->sa_family) {
144: case AF_UNSPEC:
145: printf("%-11.11s ", "none");
146: printf("%-17.17s ", "none");
147: break;
148: case AF_INET:
149: sin = (struct sockaddr_in *)sa;
150: #ifdef notdef
151: /* can't use inet_makeaddr because kernel
152: * keeps nets unshifted.
153: */
154: in = inet_makeaddr(ifaddr.in.ia_subnet,
155: INADDR_ANY);
156: printf("%-11.11s ", netname(in.s_addr,
157: ifaddr.in.ia_subnetmask));
158: #else
159: printf("%-11.11s ",
160: netname(ifaddr.in.ia_subnet,
161: ifaddr.in.ia_subnetmask));
162: #endif
163: printf("%-17.17s ",
164: routename(sin->sin_addr.s_addr));
165:
166: if (aflag) {
167: u_long multiaddr;
168: struct in_multi inm;
169:
170: multiaddr = (u_long)ifaddr.in.ia_multiaddrs.lh_first;
171: while (multiaddr != 0) {
172: kread(multiaddr, (char *)&inm,
173: sizeof inm);
174: printf("\n%23s %-15.15s ", "",
175: routename(inm.inm_addr.s_addr));
176: multiaddr = (u_long)inm.inm_list.le_next;
177: }
178: }
179: break;
180: case AF_NS:
181: {
182: struct sockaddr_ns *sns =
183: (struct sockaddr_ns *)sa;
184: u_long net;
185: char netnum[8];
186:
187: *(union ns_net *) &net = sns->sns_addr.x_net;
188: sprintf(netnum, "%lxH", ntohl(net));
189: upHex(netnum);
190: printf("ns:%-8s ", netnum);
191: printf("%-17s ",
192: ns_phost((struct sockaddr *)sns));
193: }
194: break;
195: case AF_LINK:
196: {
197: struct sockaddr_dl *sdl =
198: (struct sockaddr_dl *)sa;
199: cp = (char *)LLADDR(sdl);
200: n = sdl->sdl_alen;
201: }
202: m = printf("%-11.11s ", "<Link>");
203: goto hexprint;
204: default:
205: m = printf("(%d)", sa->sa_family);
206: for (cp = sa->sa_len + (char *)sa;
207: --cp > sa->sa_data && (*cp == 0);) {}
208: n = cp - sa->sa_data + 1;
209: cp = sa->sa_data;
210: hexprint:
211: while (--n >= 0)
212: m += printf("%x%c", *cp++ & 0xff,
213: n > 0 ? '.' : ' ');
214: m = 30 - m;
215: while (m-- > 0)
216: putchar(' ');
217: break;
218: }
219: ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
220: }
221: printf("%8d %5d %8d %5d %5d",
222: ifnet.if_ipackets, ifnet.if_ierrors,
223: ifnet.if_opackets, ifnet.if_oerrors,
224: ifnet.if_collisions);
225: if (tflag)
226: printf(" %3d", ifnet.if_timer);
227: if (dflag)
228: printf(" %3d", ifnet.if_snd.ifq_drops);
229: putchar('\n');
230: }
231: }
232:
233: #define MAXIF 10
234: struct iftot {
235: char ift_name[16]; /* interface name */
236: int ift_ip; /* input packets */
237: int ift_ie; /* input errors */
238: int ift_op; /* output packets */
239: int ift_oe; /* output errors */
240: int ift_co; /* collisions */
241: int ift_dr; /* drops */
242: } iftot[MAXIF];
243:
244: u_char signalled; /* set if alarm goes off "early" */
245:
246: /*
247: * Print a running summary of interface statistics.
248: * Repeat display every interval seconds, showing statistics
249: * collected over that interval. Assumes that interval is non-zero.
250: * First line printed at top of screen is always cumulative.
251: */
252: static void
253: sidewaysintpr(interval, off)
254: unsigned interval;
255: u_long off;
256: {
257: struct ifnet ifnet;
258: u_long firstifnet;
259: register struct iftot *ip, *total;
260: register int line;
261: struct iftot *lastif, *sum, *interesting;
262: int oldmask;
263:
264: if (kread(off, (char *)&firstifnet, sizeof (u_long)))
265: return;
266: lastif = iftot;
267: sum = iftot + MAXIF - 1;
268: total = sum - 1;
269: interesting = iftot;
270: for (off = firstifnet, ip = iftot; off;) {
271: char *cp;
272:
273: if (kread(off, (char *)&ifnet, sizeof ifnet))
274: break;
275: ip->ift_name[0] = '(';
276: if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
277: break;
278: if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
279: unit == ifnet.if_unit)
280: interesting = ip;
281: ip->ift_name[15] = '\0';
282: cp = index(ip->ift_name, '\0');
283: sprintf(cp, "%d)", ifnet.if_unit);
284: ip++;
285: if (ip >= iftot + MAXIF - 2)
286: break;
287: off = (u_long)ifnet.if_list.tqe_next;
288: }
289: lastif = ip;
290:
291: (void)signal(SIGALRM, catchalarm);
292: signalled = NO;
293: (void)alarm(interval);
294: banner:
295: printf(" input %-6.6s output ", interesting->ift_name);
296: if (lastif - iftot > 0) {
297: if (dflag)
298: printf(" ");
299: printf(" input (Total) output");
300: }
301: for (ip = iftot; ip < iftot + MAXIF; ip++) {
302: ip->ift_ip = 0;
303: ip->ift_ie = 0;
304: ip->ift_op = 0;
305: ip->ift_oe = 0;
306: ip->ift_co = 0;
307: ip->ift_dr = 0;
308: }
309: putchar('\n');
310: printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
311: "packets", "errs", "packets", "errs", "colls");
312: if (dflag)
313: printf("%5.5s ", "drops");
314: if (lastif - iftot > 0)
315: printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
316: "packets", "errs", "packets", "errs", "colls");
317: if (dflag)
318: printf(" %5.5s", "drops");
319: putchar('\n');
320: fflush(stdout);
321: line = 0;
322: loop:
323: sum->ift_ip = 0;
324: sum->ift_ie = 0;
325: sum->ift_op = 0;
326: sum->ift_oe = 0;
327: sum->ift_co = 0;
328: sum->ift_dr = 0;
329: for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
330: if (kread(off, (char *)&ifnet, sizeof ifnet)) {
331: off = 0;
332: continue;
333: }
334: if (ip == interesting) {
335: printf("%8d %5d %8d %5d %5d",
336: ifnet.if_ipackets - ip->ift_ip,
337: ifnet.if_ierrors - ip->ift_ie,
338: ifnet.if_opackets - ip->ift_op,
339: ifnet.if_oerrors - ip->ift_oe,
340: ifnet.if_collisions - ip->ift_co);
341: if (dflag)
342: printf(" %5d",
343: ifnet.if_snd.ifq_drops - ip->ift_dr);
344: }
345: ip->ift_ip = ifnet.if_ipackets;
346: ip->ift_ie = ifnet.if_ierrors;
347: ip->ift_op = ifnet.if_opackets;
348: ip->ift_oe = ifnet.if_oerrors;
349: ip->ift_co = ifnet.if_collisions;
350: ip->ift_dr = ifnet.if_snd.ifq_drops;
351: sum->ift_ip += ip->ift_ip;
352: sum->ift_ie += ip->ift_ie;
353: sum->ift_op += ip->ift_op;
354: sum->ift_oe += ip->ift_oe;
355: sum->ift_co += ip->ift_co;
356: sum->ift_dr += ip->ift_dr;
357: off = (u_long)ifnet.if_list.tqe_next;
358: }
359: if (lastif - iftot > 0) {
360: printf(" %8d %5d %8d %5d %5d",
361: sum->ift_ip - total->ift_ip,
362: sum->ift_ie - total->ift_ie,
363: sum->ift_op - total->ift_op,
364: sum->ift_oe - total->ift_oe,
365: sum->ift_co - total->ift_co);
366: if (dflag)
367: printf(" %5d", sum->ift_dr - total->ift_dr);
368: }
369: *total = *sum;
370: putchar('\n');
371: fflush(stdout);
372: line++;
373: oldmask = sigblock(sigmask(SIGALRM));
374: if (! signalled) {
375: sigpause(0);
376: }
377: sigsetmask(oldmask);
378: signalled = NO;
379: (void)alarm(interval);
380: if (line == 21)
381: goto banner;
382: goto loop;
383: /*NOTREACHED*/
384: }
385:
386: /*
387: * Called if an interval expires before sidewaysintpr has completed a loop.
388: * Sets a flag to not wait for the alarm.
389: */
390: static void
391: catchalarm(signo)
392: int signo;
393: {
394: signalled = YES;
395: }