Annotation of src/usr.bin/netstat/if.c, Revision 1.3
1.3 ! deraadt 1: /* $NetBSD: if.c,v 1.16 1996/05/07 05:30:45 thorpej 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.3 ! deraadt 40: static char *rcsid = "$NetBSD: if.c,v 1.16 1996/05/07 05:30:45 thorpej 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:
242: #define MAXIF 10
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;
286: interesting = iftot;
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;
300: }
301: lastif = ip;
302:
303: (void)signal(SIGALRM, catchalarm);
304: signalled = NO;
305: (void)alarm(interval);
306: banner:
307: printf(" input %-6.6s output ", interesting->ift_name);
308: if (lastif - iftot > 0) {
309: if (dflag)
310: printf(" ");
311: printf(" input (Total) output");
312: }
313: for (ip = iftot; ip < iftot + MAXIF; ip++) {
314: ip->ift_ip = 0;
315: ip->ift_ie = 0;
316: ip->ift_op = 0;
317: ip->ift_oe = 0;
318: ip->ift_co = 0;
319: ip->ift_dr = 0;
320: }
321: putchar('\n');
322: printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
323: "packets", "errs", "packets", "errs", "colls");
324: if (dflag)
325: printf("%5.5s ", "drops");
326: if (lastif - iftot > 0)
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: putchar('\n');
332: fflush(stdout);
333: line = 0;
334: loop:
335: sum->ift_ip = 0;
336: sum->ift_ie = 0;
337: sum->ift_op = 0;
338: sum->ift_oe = 0;
339: sum->ift_co = 0;
340: sum->ift_dr = 0;
341: for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
342: if (kread(off, (char *)&ifnet, sizeof ifnet)) {
343: off = 0;
344: continue;
345: }
346: if (ip == interesting) {
347: printf("%8d %5d %8d %5d %5d",
348: ifnet.if_ipackets - ip->ift_ip,
349: ifnet.if_ierrors - ip->ift_ie,
350: ifnet.if_opackets - ip->ift_op,
351: ifnet.if_oerrors - ip->ift_oe,
352: ifnet.if_collisions - ip->ift_co);
353: if (dflag)
354: printf(" %5d",
355: ifnet.if_snd.ifq_drops - ip->ift_dr);
356: }
357: ip->ift_ip = ifnet.if_ipackets;
358: ip->ift_ie = ifnet.if_ierrors;
359: ip->ift_op = ifnet.if_opackets;
360: ip->ift_oe = ifnet.if_oerrors;
361: ip->ift_co = ifnet.if_collisions;
362: ip->ift_dr = ifnet.if_snd.ifq_drops;
363: sum->ift_ip += ip->ift_ip;
364: sum->ift_ie += ip->ift_ie;
365: sum->ift_op += ip->ift_op;
366: sum->ift_oe += ip->ift_oe;
367: sum->ift_co += ip->ift_co;
368: sum->ift_dr += ip->ift_dr;
369: off = (u_long)ifnet.if_list.tqe_next;
370: }
371: if (lastif - iftot > 0) {
372: printf(" %8d %5d %8d %5d %5d",
373: sum->ift_ip - total->ift_ip,
374: sum->ift_ie - total->ift_ie,
375: sum->ift_op - total->ift_op,
376: sum->ift_oe - total->ift_oe,
377: sum->ift_co - total->ift_co);
378: if (dflag)
379: printf(" %5d", sum->ift_dr - total->ift_dr);
380: }
381: *total = *sum;
382: putchar('\n');
383: fflush(stdout);
384: line++;
385: oldmask = sigblock(sigmask(SIGALRM));
386: if (! signalled) {
387: sigpause(0);
388: }
389: sigsetmask(oldmask);
390: signalled = NO;
391: (void)alarm(interval);
392: if (line == 21)
393: goto banner;
394: goto loop;
395: /*NOTREACHED*/
396: }
397:
398: /*
399: * Called if an interval expires before sidewaysintpr has completed a loop.
400: * Sets a flag to not wait for the alarm.
401: */
402: static void
403: catchalarm(signo)
404: int signo;
405: {
406: signalled = YES;
407: }