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