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