Annotation of src/usr.bin/netstat/if.c, Revision 1.5
1.4 deraadt 1: /* $NetBSD: if.c,v 1.16.4.1 1996/06/04 20:27:06 cgd Exp $ */
1.1 deraadt 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
1.4 deraadt 40: static char *rcsid = "$NetBSD: if.c,v 1.16.4.1 1996/06/04 20:27:06 cgd Exp $";
1.1 deraadt 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>
1.5 ! deraadt 50: #include <net/if_types.h>
1.1 deraadt 51: #include <netinet/in.h>
52: #include <netinet/in_var.h>
53: #include <netns/ns.h>
54: #include <netns/ns_if.h>
55: #include <netiso/iso.h>
56: #include <netiso/iso_var.h>
57: #include <arpa/inet.h>
58:
59: #include <signal.h>
60: #include <stdio.h>
61: #include <string.h>
62: #include <unistd.h>
63:
64: #include "netstat.h"
65:
66: #define YES 1
67: #define NO 0
68:
69: static void sidewaysintpr __P((u_int, u_long));
70: static void catchalarm __P((int));
71:
72: /*
73: * Print a description of the network interfaces.
1.3 deraadt 74: * NOTE: ifnetaddr is the location of the kernel global "ifnet",
75: * which is a TAILQ_HEAD.
1.1 deraadt 76: */
77: void
78: intpr(interval, ifnetaddr)
79: int interval;
80: u_long ifnetaddr;
81: {
82: struct ifnet ifnet;
83: union {
84: struct ifaddr ifa;
85: struct in_ifaddr in;
86: struct ns_ifaddr ns;
87: struct iso_ifaddr iso;
88: } ifaddr;
89: u_long ifaddraddr;
90: struct sockaddr *sa;
1.3 deraadt 91: struct ifnet_head ifhead; /* TAILQ_HEAD */
92: char name[IFNAMSIZ];
1.1 deraadt 93:
94: if (ifnetaddr == 0) {
95: printf("ifnet: symbol not defined\n");
96: return;
97: }
98: if (interval) {
99: sidewaysintpr((unsigned)interval, ifnetaddr);
100: return;
101: }
1.3 deraadt 102:
103: /*
104: * Find the pointer to the first ifnet structure. Replace
105: * the pointer to the TAILQ_HEAD with the actual pointer
106: * to the first list element.
107: */
108: if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
1.1 deraadt 109: return;
1.3 deraadt 110: ifnetaddr = (u_long)ifhead.tqh_first;
111:
1.2 deraadt 112: printf("%-5.5s %-5.5s %-11.11s %-17.17s %8.8s %5.5s %8.8s %5.5s",
1.1 deraadt 113: "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
114: "Opkts", "Oerrs");
115: printf(" %5s", "Coll");
116: if (tflag)
117: printf(" %s", "Time");
118: if (dflag)
119: printf(" %s", "Drop");
120: putchar('\n');
121: ifaddraddr = 0;
122: while (ifnetaddr || ifaddraddr) {
123: struct sockaddr_in *sin;
124: register char *cp;
125: int n, m;
126:
127: if (ifaddraddr == 0) {
1.3 deraadt 128: if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
1.1 deraadt 129: return;
1.3 deraadt 130: bcopy(ifnet.if_xname, name, IFNAMSIZ);
131: name[IFNAMSIZ - 1] = '\0'; /* sanity */
1.1 deraadt 132: ifnetaddr = (u_long)ifnet.if_list.tqe_next;
1.3 deraadt 133: if (interface != 0 && strcmp(name, interface) != 0)
1.1 deraadt 134: continue;
135: cp = index(name, '\0');
136: if ((ifnet.if_flags & IFF_UP) == 0)
137: *cp++ = '*';
138: *cp = '\0';
139: ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
140: }
141: printf("%-5.5s %-5d ", name, ifnet.if_mtu);
142: if (ifaddraddr == 0) {
143: printf("%-11.11s ", "none");
144: printf("%-15.15s ", "none");
145: } else {
146: if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
147: ifaddraddr = 0;
148: continue;
149: }
150: #define CP(x) ((char *)(x))
151: cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
152: CP(&ifaddr); sa = (struct sockaddr *)cp;
153: switch (sa->sa_family) {
154: case AF_UNSPEC:
155: printf("%-11.11s ", "none");
156: printf("%-17.17s ", "none");
157: break;
158: case AF_INET:
159: sin = (struct sockaddr_in *)sa;
160: #ifdef notdef
161: /* can't use inet_makeaddr because kernel
162: * keeps nets unshifted.
163: */
164: in = inet_makeaddr(ifaddr.in.ia_subnet,
165: INADDR_ANY);
166: printf("%-11.11s ", netname(in.s_addr,
167: ifaddr.in.ia_subnetmask));
168: #else
169: printf("%-11.11s ",
170: netname(ifaddr.in.ia_subnet,
171: ifaddr.in.ia_subnetmask));
172: #endif
173: printf("%-17.17s ",
174: routename(sin->sin_addr.s_addr));
175:
176: if (aflag) {
177: u_long multiaddr;
178: struct in_multi inm;
179:
180: multiaddr = (u_long)ifaddr.in.ia_multiaddrs.lh_first;
181: while (multiaddr != 0) {
182: kread(multiaddr, (char *)&inm,
183: sizeof inm);
184: printf("\n%23s %-15.15s ", "",
185: routename(inm.inm_addr.s_addr));
186: multiaddr = (u_long)inm.inm_list.le_next;
187: }
188: }
189: break;
190: case AF_NS:
191: {
192: struct sockaddr_ns *sns =
193: (struct sockaddr_ns *)sa;
194: u_long net;
195: char netnum[8];
196:
197: *(union ns_net *) &net = sns->sns_addr.x_net;
1.5 ! deraadt 198: sprintf(netnum, "%lxH", ntohl(net));
1.1 deraadt 199: upHex(netnum);
200: printf("ns:%-8s ", netnum);
201: printf("%-17s ",
202: ns_phost((struct sockaddr *)sns));
203: }
204: break;
205: case AF_LINK:
206: {
207: struct sockaddr_dl *sdl =
208: (struct sockaddr_dl *)sa;
1.5 ! deraadt 209: m = printf("%-11.11s ", "<Link>");
! 210: if (sdl->sdl_type == IFT_ETHER ||
! 211: sdl->sdl_type == IFT_FDDI)
! 212: printf("%-17.17s ",
! 213: ether_ntoa(LLADDR(sdl)));
! 214: else {
! 215: cp = (char *)LLADDR(sdl);
! 216: n = sdl->sdl_alen;
! 217: goto hexprint;
! 218: }
1.1 deraadt 219: }
1.5 ! deraadt 220: break;
1.1 deraadt 221: default:
222: m = printf("(%d)", sa->sa_family);
223: for (cp = sa->sa_len + (char *)sa;
224: --cp > sa->sa_data && (*cp == 0);) {}
225: n = cp - sa->sa_data + 1;
226: cp = sa->sa_data;
227: hexprint:
228: while (--n >= 0)
229: m += printf("%x%c", *cp++ & 0xff,
230: n > 0 ? '.' : ' ');
231: m = 30 - m;
232: while (m-- > 0)
233: putchar(' ');
234: break;
235: }
236: ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
237: }
238: printf("%8d %5d %8d %5d %5d",
239: ifnet.if_ipackets, ifnet.if_ierrors,
240: ifnet.if_opackets, ifnet.if_oerrors,
241: ifnet.if_collisions);
242: if (tflag)
243: printf(" %3d", ifnet.if_timer);
244: if (dflag)
245: printf(" %3d", ifnet.if_snd.ifq_drops);
246: putchar('\n');
247: }
248: }
249:
1.4 deraadt 250: #define MAXIF 100
1.1 deraadt 251: struct iftot {
1.3 deraadt 252: char ift_name[IFNAMSIZ]; /* interface name */
1.1 deraadt 253: int ift_ip; /* input packets */
254: int ift_ie; /* input errors */
255: int ift_op; /* output packets */
256: int ift_oe; /* output errors */
257: int ift_co; /* collisions */
258: int ift_dr; /* drops */
259: } iftot[MAXIF];
260:
261: u_char signalled; /* set if alarm goes off "early" */
262:
263: /*
264: * Print a running summary of interface statistics.
265: * Repeat display every interval seconds, showing statistics
266: * collected over that interval. Assumes that interval is non-zero.
267: * First line printed at top of screen is always cumulative.
268: */
269: static void
270: sidewaysintpr(interval, off)
271: unsigned interval;
272: u_long off;
273: {
274: struct ifnet ifnet;
275: u_long firstifnet;
276: register struct iftot *ip, *total;
277: register int line;
278: struct iftot *lastif, *sum, *interesting;
1.3 deraadt 279: struct ifnet_head ifhead; /* TAILQ_HEAD */
1.1 deraadt 280: int oldmask;
281:
1.3 deraadt 282: /*
283: * Find the pointer to the first ifnet structure. Replace
284: * the pointer to the TAILQ_HEAD with the actual pointer
285: * to the first list element.
286: */
287: if (kread(off, (char *)&ifhead, sizeof ifhead))
1.1 deraadt 288: return;
1.3 deraadt 289: firstifnet = (u_long)ifhead.tqh_first;
290:
1.1 deraadt 291: lastif = iftot;
292: sum = iftot + MAXIF - 1;
293: total = sum - 1;
1.4 deraadt 294: interesting = (interface == NULL) ? iftot : NULL;
1.1 deraadt 295: for (off = firstifnet, ip = iftot; off;) {
296: if (kread(off, (char *)&ifnet, sizeof ifnet))
297: break;
298: ip->ift_name[0] = '(';
1.3 deraadt 299: bcopy(ifnet.if_xname, ip->ift_name + 1, IFNAMSIZ - 1);
300: if (interface &&
301: strcmp(ip->ift_name + 1, interface) == 0)
1.1 deraadt 302: interesting = ip;
1.3 deraadt 303: ip->ift_name[IFNAMSIZ - 1] = '\0';
1.1 deraadt 304: ip++;
305: if (ip >= iftot + MAXIF - 2)
306: break;
307: off = (u_long)ifnet.if_list.tqe_next;
1.4 deraadt 308: }
309: if (interesting == NULL) {
310: fprintf(stderr, "%s: %s: unknown interface\n",
311: __progname, interface);
312: exit(1);
1.1 deraadt 313: }
314: lastif = ip;
315:
316: (void)signal(SIGALRM, catchalarm);
317: signalled = NO;
318: (void)alarm(interval);
319: banner:
320: printf(" input %-6.6s output ", interesting->ift_name);
321: if (lastif - iftot > 0) {
322: if (dflag)
323: printf(" ");
324: printf(" input (Total) output");
325: }
326: for (ip = iftot; ip < iftot + MAXIF; ip++) {
327: ip->ift_ip = 0;
328: ip->ift_ie = 0;
329: ip->ift_op = 0;
330: ip->ift_oe = 0;
331: ip->ift_co = 0;
332: ip->ift_dr = 0;
333: }
334: putchar('\n');
335: printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
336: "packets", "errs", "packets", "errs", "colls");
337: if (dflag)
338: printf("%5.5s ", "drops");
339: if (lastif - iftot > 0)
340: printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
341: "packets", "errs", "packets", "errs", "colls");
342: if (dflag)
343: printf(" %5.5s", "drops");
344: putchar('\n');
345: fflush(stdout);
346: line = 0;
347: loop:
348: sum->ift_ip = 0;
349: sum->ift_ie = 0;
350: sum->ift_op = 0;
351: sum->ift_oe = 0;
352: sum->ift_co = 0;
353: sum->ift_dr = 0;
354: for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
355: if (kread(off, (char *)&ifnet, sizeof ifnet)) {
356: off = 0;
357: continue;
358: }
359: if (ip == interesting) {
360: printf("%8d %5d %8d %5d %5d",
361: ifnet.if_ipackets - ip->ift_ip,
362: ifnet.if_ierrors - ip->ift_ie,
363: ifnet.if_opackets - ip->ift_op,
364: ifnet.if_oerrors - ip->ift_oe,
365: ifnet.if_collisions - ip->ift_co);
366: if (dflag)
367: printf(" %5d",
368: ifnet.if_snd.ifq_drops - ip->ift_dr);
369: }
370: ip->ift_ip = ifnet.if_ipackets;
371: ip->ift_ie = ifnet.if_ierrors;
372: ip->ift_op = ifnet.if_opackets;
373: ip->ift_oe = ifnet.if_oerrors;
374: ip->ift_co = ifnet.if_collisions;
375: ip->ift_dr = ifnet.if_snd.ifq_drops;
376: sum->ift_ip += ip->ift_ip;
377: sum->ift_ie += ip->ift_ie;
378: sum->ift_op += ip->ift_op;
379: sum->ift_oe += ip->ift_oe;
380: sum->ift_co += ip->ift_co;
381: sum->ift_dr += ip->ift_dr;
382: off = (u_long)ifnet.if_list.tqe_next;
383: }
384: if (lastif - iftot > 0) {
385: printf(" %8d %5d %8d %5d %5d",
386: sum->ift_ip - total->ift_ip,
387: sum->ift_ie - total->ift_ie,
388: sum->ift_op - total->ift_op,
389: sum->ift_oe - total->ift_oe,
390: sum->ift_co - total->ift_co);
391: if (dflag)
392: printf(" %5d", sum->ift_dr - total->ift_dr);
393: }
394: *total = *sum;
395: putchar('\n');
396: fflush(stdout);
397: line++;
398: oldmask = sigblock(sigmask(SIGALRM));
399: if (! signalled) {
400: sigpause(0);
401: }
402: sigsetmask(oldmask);
403: signalled = NO;
404: (void)alarm(interval);
405: if (line == 21)
406: goto banner;
407: goto loop;
408: /*NOTREACHED*/
409: }
410:
411: /*
412: * Called if an interval expires before sidewaysintpr has completed a loop.
413: * Sets a flag to not wait for the alarm.
414: */
415: static void
416: catchalarm(signo)
417: int signo;
418: {
419: signalled = YES;
420: }