Annotation of src/usr.bin/netstat/if.c, Revision 1.74.2.1
1.74.2.1! tls 1: /* $NetBSD: if.c,v 1.75 2012/10/19 19:50:19 msaitoh Exp $ */
1.13 thorpej 2:
1.1 cgd 3: /*
1.8 mycroft 4: * Copyright (c) 1983, 1988, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.55 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.25 lukem 32: #include <sys/cdefs.h>
1.1 cgd 33: #ifndef lint
1.13 thorpej 34: #if 0
35: static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
36: #else
1.74.2.1! tls 37: __RCSID("$NetBSD: if.c,v 1.75 2012/10/19 19:50:19 msaitoh Exp $");
1.13 thorpej 38: #endif
1.1 cgd 39: #endif /* not lint */
40:
1.64 elad 41: #include <sys/param.h>
1.1 cgd 42: #include <sys/types.h>
1.8 mycroft 43: #include <sys/protosw.h>
1.1 cgd 44: #include <sys/socket.h>
1.57 ragge 45: #include <sys/time.h>
1.64 elad 46: #include <sys/sysctl.h>
1.1 cgd 47:
48: #include <net/if.h>
49: #include <net/if_dl.h>
1.20 thorpej 50: #include <net/if_types.h>
1.64 elad 51: #include <net/route.h>
1.1 cgd 52: #include <netinet/in.h>
53: #include <netinet/in_var.h>
54: #include <netiso/iso.h>
55: #include <netiso/iso_var.h>
1.8 mycroft 56: #include <arpa/inet.h>
1.1 cgd 57:
1.59 rpaulo 58: #include <kvm.h>
1.8 mycroft 59: #include <signal.h>
1.1 cgd 60: #include <stdio.h>
1.42 matt 61: #include <stdlib.h>
1.8 mycroft 62: #include <string.h>
63: #include <unistd.h>
1.34 itojun 64: #include <netdb.h>
1.64 elad 65: #include <err.h>
1.8 mycroft 66:
67: #include "netstat.h"
1.70 pooka 68: #include "prog_ops.h"
1.1 cgd 69:
1.64 elad 70: #define MAXIF 100
71:
1.68 pooka 72: #define HUMBUF_SIZE 7
73:
1.64 elad 74: struct iftot {
75: char ift_name[IFNAMSIZ]; /* interface name */
76: u_quad_t ift_ip; /* input packets */
77: u_quad_t ift_ib; /* input bytes */
78: u_quad_t ift_ie; /* input errors */
79: u_quad_t ift_op; /* output packets */
80: u_quad_t ift_ob; /* output bytes */
81: u_quad_t ift_oe; /* output errors */
82: u_quad_t ift_co; /* collisions */
83: int ift_dr; /* drops */
84: };
85:
1.73 christos 86: static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *,
87: struct ifnet *);
1.64 elad 88: static void sidewaysintpr(u_int, u_long);
89:
90: static void iftot_banner(struct iftot *);
91: static void iftot_print_sum(struct iftot *, struct iftot *);
92: static void iftot_print(struct iftot *, struct iftot *);
1.1 cgd 93:
1.8 mycroft 94: static void catchalarm __P((int));
1.64 elad 95: static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
96: static void fetchifs(void);
97:
98: static void intpr_sysctl(void);
99: static void intpr_kvm(u_long, void (*)(const char *));
100:
101: struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old;
102: bool signalled; /* set if alarm goes off "early" */
1.32 itojun 103:
1.1 cgd 104: /*
105: * Print a description of the network interfaces.
1.15 thorpej 106: * NOTE: ifnetaddr is the location of the kernel global "ifnet",
107: * which is a TAILQ_HEAD.
1.1 cgd 108: */
1.8 mycroft 109: void
1.74 matt 110: intpr(int interval, u_long ifnetaddr, void (*pfunc)(const char *))
1.1 cgd 111: {
1.64 elad 112:
113: if (interval) {
114: sidewaysintpr((unsigned)interval, ifnetaddr);
115: return;
116: }
117:
118: if (use_sysctl) {
119: intpr_sysctl();
120: } else {
121: intpr_kvm(ifnetaddr, pfunc);
122: }
123:
124: }
125:
126: static void
127: intpr_header(void)
128: {
129:
130: if (!sflag & !pflag) {
131: if (bflag) {
132: printf("%-5.5s %-5.5s %-13.13s %-17.17s "
133: "%10.10s %10.10s",
134: "Name", "Mtu", "Network", "Address",
135: "Ibytes", "Obytes");
136: } else {
137: printf("%-5.5s %-5.5s %-13.13s %-17.17s "
138: "%8.8s %5.5s %8.8s %5.5s %5.5s",
139: "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
140: "Opkts", "Oerrs", "Colls");
141: }
142: if (tflag)
143: printf(" %4.4s", "Time");
144: if (dflag)
145: printf(" %5.5s", "Drops");
146: putchar('\n');
147: }
148: }
149:
150: static void
151: intpr_sysctl(void)
152: {
153: struct if_msghdr *ifm;
154: int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
155: char *buf = NULL, *next, *lim, *cp;
156: struct rt_msghdr *rtm;
157: struct ifa_msghdr *ifam;
158: struct if_data *ifd = NULL;
159: struct sockaddr *sa, *rti_info[RTAX_MAX];
160: struct sockaddr_dl *sdl;
161: uint64_t total = 0;
162: size_t len;
163: char name[IFNAMSIZ + 1]; /* + 1 for `*' */
164:
1.70 pooka 165: if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
1.64 elad 166: err(1, "sysctl");
167: if ((buf = malloc(len)) == NULL)
168: err(1, NULL);
1.70 pooka 169: if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1)
1.64 elad 170: err(1, "sysctl");
171:
172: intpr_header();
173:
174: lim = buf + len;
175: for (next = buf; next < lim; next += rtm->rtm_msglen) {
176: rtm = (struct rt_msghdr *)next;
177: if (rtm->rtm_version != RTM_VERSION)
178: continue;
179: switch (rtm->rtm_type) {
180: case RTM_IFINFO:
181: total = 0;
182: ifm = (struct if_msghdr *)next;
183: ifd = &ifm->ifm_data;
184:
185: sa = (struct sockaddr *)(ifm + 1);
186: get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
187:
188: sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
189: if (sdl == NULL || sdl->sdl_family != AF_LINK) {
190: continue;
191: }
192: bzero(name, sizeof(name));
193: if (sdl->sdl_nlen >= IFNAMSIZ)
194: memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
195: else if (sdl->sdl_nlen > 0)
196: memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
197:
198: if (interface != 0 && strcmp(name, interface) != 0)
199: continue;
200:
201: /* mark inactive interfaces with a '*' */
202: cp = strchr(name, '\0');
203: if ((ifm->ifm_flags & IFF_UP) == 0)
204: *cp++ = '*';
205: *cp = '\0';
206:
207: if (qflag) {
208: total = ifd->ifi_ibytes + ifd->ifi_obytes +
209: ifd->ifi_ipackets + ifd->ifi_ierrors +
210: ifd->ifi_opackets + ifd->ifi_oerrors +
211: ifd->ifi_collisions;
212: if (tflag)
213: total += 0; // XXX-elad ifnet.if_timer;
214: if (dflag)
215: total += 0; // XXX-elad ifnet.if_snd.ifq_drops;
216: if (total == 0)
217: continue;
218: }
219:
1.66 pgoyette 220: printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
1.73 christos 221: print_addr(rti_info[RTAX_IFP], rti_info, ifd, NULL);
1.64 elad 222: break;
223:
224: case RTM_NEWADDR:
225: if (qflag && total == 0)
226: continue;
227: if (interface != 0 && strcmp(name, interface) != 0)
228: continue;
229: ifam = (struct ifa_msghdr *)next;
230: if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
231: RTA_BRD)) == 0)
232: break;
233:
234: sa = (struct sockaddr *)(ifam + 1);
235:
236: get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
237:
1.66 pgoyette 238: printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
1.73 christos 239: print_addr(rti_info[RTAX_IFA], rti_info, ifd, NULL);
1.64 elad 240: break;
241: }
242: }
243: }
244:
1.73 christos 245: union ifaddr_u {
246: struct ifaddr ifa;
247: struct in_ifaddr in;
248: #ifdef INET6
249: struct in6_ifaddr in6;
250: #endif /* INET6 */
251: struct iso_ifaddr iso;
252: };
253:
1.64 elad 254: static void
255: intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *))
256: {
1.1 cgd 257: struct ifnet ifnet;
1.73 christos 258: union ifaddr_u ifaddr;
1.7 cgd 259: u_long ifaddraddr;
1.15 thorpej 260: struct ifnet_head ifhead; /* TAILQ_HEAD */
1.43 enami 261: char name[IFNAMSIZ + 1]; /* + 1 for `*' */
1.1 cgd 262:
263: if (ifnetaddr == 0) {
264: printf("ifnet: symbol not defined\n");
265: return;
266: }
1.15 thorpej 267:
268: /*
269: * Find the pointer to the first ifnet structure. Replace
270: * the pointer to the TAILQ_HEAD with the actual pointer
271: * to the first list element.
272: */
273: if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
1.8 mycroft 274: return;
1.15 thorpej 275: ifnetaddr = (u_long)ifhead.tqh_first;
276:
1.64 elad 277: intpr_header();
278:
1.1 cgd 279: ifaddraddr = 0;
280: while (ifnetaddr || ifaddraddr) {
1.25 lukem 281: char *cp;
1.64 elad 282: int n;
1.1 cgd 283:
284: if (ifaddraddr == 0) {
1.15 thorpej 285: if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
1.8 mycroft 286: return;
1.25 lukem 287: memmove(name, ifnet.if_xname, IFNAMSIZ);
1.15 thorpej 288: name[IFNAMSIZ - 1] = '\0'; /* sanity */
1.10 mycroft 289: ifnetaddr = (u_long)ifnet.if_list.tqe_next;
1.16 thorpej 290: if (interface != 0 && strcmp(name, interface) != 0)
1.1 cgd 291: continue;
1.25 lukem 292: cp = strchr(name, '\0');
1.34 itojun 293:
294: if (pfunc) {
295: (*pfunc)(name);
296: continue;
297: }
298:
1.10 mycroft 299: if ((ifnet.if_flags & IFF_UP) == 0)
1.1 cgd 300: *cp++ = '*';
301: *cp = '\0';
1.10 mycroft 302: ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
1.1 cgd 303: }
1.41 itojun 304: if (vflag)
305: n = strlen(name) < 5 ? 5 : strlen(name);
306: else
307: n = 5;
308: printf("%-*.*s %-5llu ", n, n, name,
1.33 bouyer 309: (unsigned long long)ifnet.if_mtu);
1.1 cgd 310: if (ifaddraddr == 0) {
1.21 christos 311: printf("%-13.13s ", "none");
1.23 mikel 312: printf("%-17.17s ", "none");
1.1 cgd 313: } else {
1.64 elad 314: struct sockaddr *sa;
315:
1.8 mycroft 316: if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
317: ifaddraddr = 0;
318: continue;
319: }
1.1 cgd 320: #define CP(x) ((char *)(x))
1.8 mycroft 321: cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
1.56 itojun 322: CP(&ifaddr);
323: sa = (struct sockaddr *)cp;
1.73 christos 324: print_addr(sa, (void *)&ifaddr, &ifnet.if_data, &ifnet);
1.64 elad 325: }
326: ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
327: }
328:
329: }
330:
331: static void
1.73 christos 332: print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd,
333: struct ifnet *ifnet)
1.64 elad 334: {
335: char hexsep = '.'; /* for hexprint */
336: static const char hexfmt[] = "%02x%c"; /* for hexprint */
337: char hbuf[NI_MAXHOST]; /* for getnameinfo() */
338: #ifdef INET6
339: const int niflag = NI_NUMERICHOST;
1.67 plunky 340: struct sockaddr_in6 *sin6, *netmask6;
1.64 elad 341: #endif
342: in_addr_t netmask;
343: struct sockaddr_in *sin;
344: char *cp;
345: int n, m;
346:
347: switch (sa->sa_family) {
348: case AF_UNSPEC:
349: printf("%-13.13s ", "none");
350: printf("%-17.17s ", "none");
351: break;
352: case AF_INET:
353: sin = (struct sockaddr_in *)sa;
1.1 cgd 354: #ifdef notdef
1.64 elad 355: /*
356: * can't use inet_makeaddr because kernel
357: * keeps nets unshifted.
358: */
359: in = inet_makeaddr(ifaddr.in.ia_subnet,
360: INADDR_ANY);
361: cp = netname4(in.s_addr,
362: ifaddr.in.ia_subnetmask);
1.1 cgd 363: #else
1.64 elad 364: if (use_sysctl) {
365: netmask = ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr;
366: } else {
367: struct in_ifaddr *ifaddr_in = (void *)rtinfo;
368: netmask = ifaddr_in->ia_subnetmask;
369: }
370: cp = netname4(sin->sin_addr.s_addr, netmask);
1.37 itojun 371: #endif
1.64 elad 372: if (vflag)
373: n = strlen(cp) < 13 ? 13 : strlen(cp);
374: else
375: n = 13;
376: printf("%-*.*s ", n, n, cp);
377: cp = routename4(sin->sin_addr.s_addr);
378: if (vflag)
379: n = strlen(cp) < 17 ? 17 : strlen(cp);
380: else
381: n = 17;
382: printf("%-*.*s ", n, n, cp);
383:
1.73 christos 384: if (aflag && ifnet) {
1.64 elad 385: u_long multiaddr;
386: struct in_multi inm;
1.73 christos 387: union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo;
1.64 elad 388:
389: multiaddr = (u_long)
1.73 christos 390: ifaddr->in.ia_multiaddrs.lh_first;
1.64 elad 391: while (multiaddr != 0) {
392: kread(multiaddr, (char *)&inm,
393: sizeof inm);
394: printf("\n%25s %-17.17s ", "",
395: routename4(
396: inm.inm_addr.s_addr));
397: multiaddr =
398: (u_long)inm.inm_list.le_next;
399: }
400: }
401: break;
1.32 itojun 402: #ifdef INET6
1.64 elad 403: case AF_INET6:
404: sin6 = (struct sockaddr_in6 *)sa;
1.54 itojun 405: #ifdef __KAME__
1.64 elad 406: if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
407: sin6->sin6_scope_id =
408: ntohs(*(u_int16_t *)
409: &sin6->sin6_addr.s6_addr[2]);
410: /* too little width */
411: if (!vflag)
412: sin6->sin6_scope_id = 0;
413: sin6->sin6_addr.s6_addr[2] = 0;
414: sin6->sin6_addr.s6_addr[3] = 0;
415: }
1.34 itojun 416: #endif
1.64 elad 417:
418: if (use_sysctl) {
419: netmask6 = (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK];
420: } else {
421: struct in6_ifaddr *ifaddr_in6 = (void *)rtinfo;
422: netmask6 = &ifaddr_in6->ia_prefixmask;
423: }
424:
425: cp = netname6(sin6, netmask6);
426: if (vflag)
427: n = strlen(cp) < 13 ? 13 : strlen(cp);
428: else
429: n = 13;
430: printf("%-*.*s ", n, n, cp);
431: if (getnameinfo((struct sockaddr *)sin6,
432: sin6->sin6_len,
433: hbuf, sizeof(hbuf), NULL, 0,
434: niflag) != 0) {
435: strlcpy(hbuf, "?", sizeof(hbuf));
436: }
437: cp = hbuf;
438: if (vflag)
439: n = strlen(cp) < 17 ? 17 : strlen(cp);
440: else
441: n = 17;
442: printf("%-*.*s ", n, n, cp);
443:
1.73 christos 444: if (aflag && ifnet) {
1.64 elad 445: u_long multiaddr;
446: struct in6_multi inm;
447: struct sockaddr_in6 as6;
1.73 christos 448: union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo;
1.35 itojun 449:
1.64 elad 450: multiaddr = (u_long)
1.73 christos 451: ifaddr->in6.ia6_multiaddrs.lh_first;
1.64 elad 452: while (multiaddr != 0) {
453: kread(multiaddr, (char *)&inm,
454: sizeof inm);
455: memset(&as6, 0, sizeof(as6));
456: as6.sin6_len = sizeof(struct sockaddr_in6);
457: as6.sin6_family = AF_INET6;
458: as6.sin6_addr = inm.in6m_addr;
1.54 itojun 459: #ifdef __KAME__
1.64 elad 460: if (IN6_IS_ADDR_MC_LINKLOCAL(&as6.sin6_addr)) {
461: as6.sin6_scope_id =
462: ntohs(*(u_int16_t *)
463: &as6.sin6_addr.s6_addr[2]);
464: as6.sin6_addr.s6_addr[2] = 0;
465: as6.sin6_addr.s6_addr[3] = 0;
1.35 itojun 466: }
1.61 matt 467: #endif
1.64 elad 468: if (getnameinfo((struct sockaddr *)&as6,
469: as6.sin6_len, hbuf,
470: sizeof(hbuf), NULL, 0,
471: niflag) != 0) {
472: strlcpy(hbuf, "??",
473: sizeof(hbuf));
1.63 lukem 474: }
475: cp = hbuf;
1.49 bjh21 476: if (vflag)
1.64 elad 477: n = strlen(cp) < 17
478: ? 17 : strlen(cp);
1.49 bjh21 479: else
1.64 elad 480: n = 17;
481: printf("\n%25s %-*.*s ", "",
482: n, n, cp);
483: multiaddr =
484: (u_long)inm.in6m_entry.le_next;
1.1 cgd 485: }
486: }
1.64 elad 487: break;
488: #endif /*INET6*/
489: #ifndef SMALL
490: case AF_APPLETALK:
491: printf("atalk:%-7.7s ",
492: atalk_print(sa,0x10));
493: printf("%-17.17s ", atalk_print(sa,0x0b));
494: break;
495: #endif
496: case AF_LINK:
497: printf("%-13.13s ", "<Link>");
498: if (getnameinfo(sa, sa->sa_len,
499: hbuf, sizeof(hbuf), NULL, 0,
500: NI_NUMERICHOST) != 0) {
501: strlcpy(hbuf, "?", sizeof(hbuf));
1.26 kml 502: }
1.64 elad 503: cp = hbuf;
504: if (vflag)
505: n = strlen(cp) < 17 ? 17 : strlen(cp);
506: else
507: n = 17;
508: printf("%-*.*s ", n, n, cp);
509: break;
510:
511: default:
512: m = printf("(%d)", sa->sa_family);
513: for (cp = sa->sa_len + (char *)sa;
514: --cp > sa->sa_data && (*cp == 0);) {}
515: n = cp - sa->sa_data + 1;
516: cp = sa->sa_data;
517:
518: while (--n >= 0)
519: m += printf(hexfmt, *cp++ & 0xff,
520: n > 0 ? hexsep : ' ');
521: m = 32 - m;
522: while (m-- > 0)
523: putchar(' ');
524: break;
525: }
526:
527: if (bflag) {
1.68 pooka 528: char humbuf[HUMBUF_SIZE];
529:
530: if (hflag && humanize_number(humbuf, sizeof(humbuf),
531: ifd->ifi_ibytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
532: printf("%10s ", humbuf);
533: else
534: printf("%10llu ", (unsigned long long)ifd->ifi_ibytes);
535:
536: if (hflag && humanize_number(humbuf, sizeof(humbuf),
537: ifd->ifi_obytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
538: printf("%10s", humbuf);
539: else
540: printf("%10llu", (unsigned long long)ifd->ifi_obytes);
1.64 elad 541: } else {
542: printf("%8llu %5llu %8llu %5llu %5llu",
543: (unsigned long long)ifd->ifi_ipackets,
544: (unsigned long long)ifd->ifi_ierrors,
545: (unsigned long long)ifd->ifi_opackets,
546: (unsigned long long)ifd->ifi_oerrors,
547: (unsigned long long)ifd->ifi_collisions);
1.1 cgd 548: }
1.64 elad 549: if (tflag)
1.73 christos 550: printf(" %4d", ifnet ? ifnet->if_timer : 0);
1.64 elad 551: if (dflag)
1.73 christos 552: printf(" %5d", ifnet ? ifnet->if_snd.ifq_drops : 0);
1.64 elad 553: putchar('\n');
554: }
555:
556: static void
557: iftot_banner(struct iftot *ift)
558: {
559: if (bflag)
560: printf("%7.7s in %8.8s %6.6s out %5.5s",
561: ift->ift_name, " ",
562: ift->ift_name, " ");
563: else
564: printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
565: ift->ift_name, " ",
566: ift->ift_name, " ", " ");
567: if (dflag)
568: printf(" %5.5s", " ");
569:
570: if (bflag)
571: printf(" %7.7s in %8.8s %6.6s out %5.5s",
572: "total", " ", "total", " ");
573: else
574: printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
575: "total", " ", "total", " ", " ");
576: if (dflag)
577: printf(" %5.5s", " ");
578: putchar('\n');
579: if (bflag)
580: printf("%10.10s %8.8s %10.10s %5.5s",
581: "bytes", " ", "bytes", " ");
582: else
583: printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
584: "packets", "errs", "packets", "errs", "colls");
585: if (dflag)
586: printf(" %5.5s", "drops");
587:
588: if (bflag)
589: printf(" %10.10s %8.8s %10.10s %5.5s",
590: "bytes", " ", "bytes", " ");
591: else
592: printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
593: "packets", "errs", "packets", "errs", "colls");
594: if (dflag)
595: printf(" %5.5s", "drops");
596: putchar('\n');
597: fflush(stdout);
1.1 cgd 598: }
599:
1.64 elad 600: static void
601: iftot_print(struct iftot *cur, struct iftot *old)
602: {
603: if (bflag)
1.74.2.1! tls 604: printf("%10" PRIu64 " %8.8s %10" PRIu64 " %5.5s",
1.66 pgoyette 605: cur->ift_ib - old->ift_ib, " ",
606: cur->ift_ob - old->ift_ob, " ");
1.64 elad 607: else
1.74.2.1! tls 608: printf("%8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64,
1.66 pgoyette 609: cur->ift_ip - old->ift_ip,
610: cur->ift_ie - old->ift_ie,
611: cur->ift_op - old->ift_op,
612: cur->ift_oe - old->ift_oe,
613: cur->ift_co - old->ift_co);
1.64 elad 614: if (dflag)
615: printf(" %5llu",
616: /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */
617: 0LL);
618: }
619:
620: static void
621: iftot_print_sum(struct iftot *cur, struct iftot *old)
622: {
623: if (bflag)
1.74.2.1! tls 624: printf(" %10" PRIu64 " %8.8s %10" PRIu64 " %5.5s",
1.66 pgoyette 625: cur->ift_ib - old->ift_ib, " ",
626: cur->ift_ob - old->ift_ob, " ");
1.64 elad 627: else
1.74.2.1! tls 628: printf(" %8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64,
1.66 pgoyette 629: cur->ift_ip - old->ift_ip,
630: cur->ift_ie - old->ift_ie,
631: cur->ift_op - old->ift_op,
632: cur->ift_oe - old->ift_oe,
633: cur->ift_co - old->ift_co);
1.64 elad 634:
635: if (dflag)
636: printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr));
637: }
638:
1.72 joerg 639: __dead static void
1.64 elad 640: sidewaysintpr_sysctl(unsigned interval)
641: {
642: sigset_t emptyset;
643: int line;
644:
645: fetchifs();
646: if (ip_cur.ift_name[0] == '\0') {
647: fprintf(stderr, "%s: %s: unknown interface\n",
648: getprogname(), interface);
649: exit(1);
650: }
651:
652: (void)signal(SIGALRM, catchalarm);
653: signalled = 0;
654: (void)alarm(interval);
655: banner:
656: iftot_banner(&ip_cur);
657:
658: line = 0;
659: bzero(&ip_old, sizeof(ip_old));
660: bzero(&sum_old, sizeof(sum_old));
661: loop:
662: bzero(&sum_cur, sizeof(sum_cur));
663:
664: fetchifs();
665:
666: iftot_print(&ip_cur, &ip_old);
667:
668: ip_old = ip_cur;
669:
670: iftot_print_sum(&sum_cur, &sum_old);
671:
672: sum_old = sum_cur;
1.1 cgd 673:
1.64 elad 674: putchar('\n');
675: fflush(stdout);
676: line++;
677: sigemptyset(&emptyset);
678: if (!signalled)
679: sigsuspend(&emptyset);
680: signalled = 0;
681: (void)alarm(interval);
682: if (line == 21)
683: goto banner;
684: goto loop;
685: /*NOTREACHED*/
686: }
1.1 cgd 687:
1.8 mycroft 688: static void
1.64 elad 689: sidewaysintpr_kvm(unsigned interval, u_long off)
1.1 cgd 690: {
1.57 ragge 691: struct itimerval it;
1.1 cgd 692: struct ifnet ifnet;
1.7 cgd 693: u_long firstifnet;
1.25 lukem 694: struct iftot *ip, *total;
695: int line;
1.1 cgd 696: struct iftot *lastif, *sum, *interesting;
1.15 thorpej 697: struct ifnet_head ifhead; /* TAILQ_HEAD */
1.1 cgd 698: int oldmask;
699:
1.15 thorpej 700: /*
701: * Find the pointer to the first ifnet structure. Replace
702: * the pointer to the TAILQ_HEAD with the actual pointer
703: * to the first list element.
704: */
705: if (kread(off, (char *)&ifhead, sizeof ifhead))
1.8 mycroft 706: return;
1.15 thorpej 707: firstifnet = (u_long)ifhead.tqh_first;
708:
1.1 cgd 709: lastif = iftot;
710: sum = iftot + MAXIF - 1;
711: total = sum - 1;
1.17 cgd 712: interesting = (interface == NULL) ? iftot : NULL;
1.1 cgd 713: for (off = firstifnet, ip = iftot; off;) {
1.8 mycroft 714: if (kread(off, (char *)&ifnet, sizeof ifnet))
715: break;
1.25 lukem 716: memset(ip->ift_name, 0, sizeof(ip->ift_name));
1.31 mycroft 717: snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname);
1.19 thorpej 718: if (interface && strcmp(ifnet.if_xname, interface) == 0)
1.1 cgd 719: interesting = ip;
720: ip++;
721: if (ip >= iftot + MAXIF - 2)
722: break;
1.10 mycroft 723: off = (u_long)ifnet.if_list.tqe_next;
1.17 cgd 724: }
725: if (interesting == NULL) {
726: fprintf(stderr, "%s: %s: unknown interface\n",
1.47 cgd 727: getprogname(), interface);
1.17 cgd 728: exit(1);
1.1 cgd 729: }
730: lastif = ip;
731:
732: (void)signal(SIGALRM, catchalarm);
1.64 elad 733: signalled = false;
1.57 ragge 734:
735: it.it_interval.tv_sec = it.it_value.tv_sec = interval;
736: it.it_interval.tv_usec = it.it_value.tv_usec = 0;
737: setitimer(ITIMER_REAL, &it, NULL);
738:
1.1 cgd 739: banner:
1.31 mycroft 740: if (bflag)
741: printf("%7.7s in %8.8s %6.6s out %5.5s",
742: interesting->ift_name, " ",
743: interesting->ift_name, " ");
744: else
745: printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
746: interesting->ift_name, " ",
747: interesting->ift_name, " ", " ");
748: if (dflag)
749: printf(" %5.5s", " ");
1.1 cgd 750: if (lastif - iftot > 0) {
1.31 mycroft 751: if (bflag)
752: printf(" %7.7s in %8.8s %6.6s out %5.5s",
753: "total", " ", "total", " ");
754: else
755: printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
756: "total", " ", "total", " ", " ");
1.1 cgd 757: if (dflag)
1.31 mycroft 758: printf(" %5.5s", " ");
1.1 cgd 759: }
760: for (ip = iftot; ip < iftot + MAXIF; ip++) {
761: ip->ift_ip = 0;
1.26 kml 762: ip->ift_ib = 0;
1.1 cgd 763: ip->ift_ie = 0;
764: ip->ift_op = 0;
1.26 kml 765: ip->ift_ob = 0;
1.1 cgd 766: ip->ift_oe = 0;
767: ip->ift_co = 0;
768: ip->ift_dr = 0;
769: }
770: putchar('\n');
1.31 mycroft 771: if (bflag)
1.26 kml 772: printf("%10.10s %8.8s %10.10s %5.5s",
1.31 mycroft 773: "bytes", " ", "bytes", " ");
774: else
775: printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
776: "packets", "errs", "packets", "errs", "colls");
1.1 cgd 777: if (dflag)
1.31 mycroft 778: printf(" %5.5s", "drops");
1.29 ross 779: if (lastif - iftot > 0) {
1.31 mycroft 780: if (bflag)
781: printf(" %10.10s %8.8s %10.10s %5.5s",
782: "bytes", " ", "bytes", " ");
783: else
784: printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
785: "packets", "errs", "packets", "errs", "colls");
786: if (dflag)
787: printf(" %5.5s", "drops");
1.29 ross 788: }
1.1 cgd 789: putchar('\n');
790: fflush(stdout);
791: line = 0;
792: loop:
793: sum->ift_ip = 0;
1.26 kml 794: sum->ift_ib = 0;
1.1 cgd 795: sum->ift_ie = 0;
796: sum->ift_op = 0;
1.26 kml 797: sum->ift_ob = 0;
1.1 cgd 798: sum->ift_oe = 0;
799: sum->ift_co = 0;
800: sum->ift_dr = 0;
801: for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
1.8 mycroft 802: if (kread(off, (char *)&ifnet, sizeof ifnet)) {
803: off = 0;
804: continue;
805: }
1.1 cgd 806: if (ip == interesting) {
1.26 kml 807: if (bflag) {
1.68 pooka 808: char humbuf[HUMBUF_SIZE];
809:
810: if (hflag && humanize_number(humbuf,
811: sizeof(humbuf),
812: ifnet.if_ibytes - ip->ift_ib, "",
813: HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
814: printf("%10s %8.8s ", humbuf, " ");
815: else
816: printf("%10llu %8.8s ",
817: (unsigned long long)
818: (ifnet.if_ibytes-ip->ift_ib), " ");
819:
820: if (hflag && humanize_number(humbuf,
821: sizeof(humbuf),
822: ifnet.if_obytes - ip->ift_ob, "",
823: HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
824: printf("%10s %5.5s", humbuf, " ");
825: else
826: printf("%10llu %5.5s",
827: (unsigned long long)
828: (ifnet.if_obytes-ip->ift_ob), " ");
1.26 kml 829: } else {
1.33 bouyer 830: printf("%8llu %5llu %8llu %5llu %5llu",
831: (unsigned long long)
832: (ifnet.if_ipackets - ip->ift_ip),
833: (unsigned long long)
834: (ifnet.if_ierrors - ip->ift_ie),
835: (unsigned long long)
836: (ifnet.if_opackets - ip->ift_op),
837: (unsigned long long)
838: (ifnet.if_oerrors - ip->ift_oe),
839: (unsigned long long)
840: (ifnet.if_collisions - ip->ift_co));
1.26 kml 841: }
1.1 cgd 842: if (dflag)
1.33 bouyer 843: printf(" %5llu",
844: (unsigned long long)
845: (ifnet.if_snd.ifq_drops - ip->ift_dr));
1.1 cgd 846: }
847: ip->ift_ip = ifnet.if_ipackets;
1.26 kml 848: ip->ift_ib = ifnet.if_ibytes;
1.1 cgd 849: ip->ift_ie = ifnet.if_ierrors;
850: ip->ift_op = ifnet.if_opackets;
1.26 kml 851: ip->ift_ob = ifnet.if_obytes;
1.1 cgd 852: ip->ift_oe = ifnet.if_oerrors;
853: ip->ift_co = ifnet.if_collisions;
854: ip->ift_dr = ifnet.if_snd.ifq_drops;
855: sum->ift_ip += ip->ift_ip;
1.26 kml 856: sum->ift_ib += ip->ift_ib;
1.1 cgd 857: sum->ift_ie += ip->ift_ie;
858: sum->ift_op += ip->ift_op;
1.26 kml 859: sum->ift_ob += ip->ift_ob;
1.1 cgd 860: sum->ift_oe += ip->ift_oe;
861: sum->ift_co += ip->ift_co;
862: sum->ift_dr += ip->ift_dr;
1.10 mycroft 863: off = (u_long)ifnet.if_list.tqe_next;
1.1 cgd 864: }
865: if (lastif - iftot > 0) {
1.26 kml 866: if (bflag) {
1.68 pooka 867: char humbuf[HUMBUF_SIZE];
868:
869: if (hflag && humanize_number(humbuf,
870: sizeof(humbuf), sum->ift_ib - total->ift_ib, "",
871: HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
1.69 enami 872: printf(" %10s %8.8s ", humbuf, " ");
1.68 pooka 873: else
1.69 enami 874: printf(" %10llu %8.8s ",
1.68 pooka 875: (unsigned long long)
876: (sum->ift_ib - total->ift_ib), " ");
877:
878: if (hflag && humanize_number(humbuf,
879: sizeof(humbuf), sum->ift_ob - total->ift_ob, "",
880: HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0)
881: printf("%10s %5.5s", humbuf, " ");
882: else
883: printf("%10llu %5.5s",
884: (unsigned long long)
885: (sum->ift_ob - total->ift_ob), " ");
1.26 kml 886: } else {
1.33 bouyer 887: printf(" %8llu %5llu %8llu %5llu %5llu",
888: (unsigned long long)
889: (sum->ift_ip - total->ift_ip),
890: (unsigned long long)
891: (sum->ift_ie - total->ift_ie),
892: (unsigned long long)
893: (sum->ift_op - total->ift_op),
894: (unsigned long long)
895: (sum->ift_oe - total->ift_oe),
896: (unsigned long long)
897: (sum->ift_co - total->ift_co));
1.26 kml 898: }
1.1 cgd 899: if (dflag)
1.33 bouyer 900: printf(" %5llu",
901: (unsigned long long)(sum->ift_dr - total->ift_dr));
1.1 cgd 902: }
903: *total = *sum;
904: putchar('\n');
905: fflush(stdout);
906: line++;
907: oldmask = sigblock(sigmask(SIGALRM));
908: if (! signalled) {
909: sigpause(0);
910: }
911: sigsetmask(oldmask);
1.64 elad 912: signalled = false;
1.1 cgd 913: if (line == 21)
914: goto banner;
915: goto loop;
916: /*NOTREACHED*/
917: }
918:
919: /*
1.64 elad 920: * Print a running summary of interface statistics.
921: * Repeat display every interval seconds, showing statistics
922: * collected over that interval. Assumes that interval is non-zero.
923: * First line printed at top of screen is always cumulative.
924: */
925: static void
1.74 matt 926: sidewaysintpr(unsigned int interval, u_long off)
1.64 elad 927: {
928:
929: if (use_sysctl) {
930: sidewaysintpr_sysctl(interval);
931: } else {
932: sidewaysintpr_kvm(interval, off);
933: }
934: }
935:
936: /*
1.1 cgd 937: * Called if an interval expires before sidewaysintpr has completed a loop.
938: * Sets a flag to not wait for the alarm.
939: */
1.8 mycroft 940: static void
1.74 matt 941: catchalarm(int signo)
1.1 cgd 942: {
1.28 mrg 943:
1.64 elad 944: signalled = true;
945: }
946:
947: static void
948: get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
949: {
950: int i;
951:
952: for (i = 0; i < RTAX_MAX; i++) {
953: if (addrs & (1 << i)) {
954: rti_info[i] = sa;
1.71 martin 955: sa = (struct sockaddr *)((char *)(sa) +
956: RT_ROUNDUP(sa->sa_len));
1.64 elad 957: } else
958: rti_info[i] = NULL;
959: }
960: }
961:
962: static void
963: fetchifs(void)
964: {
965: struct if_msghdr *ifm;
966: int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
967: struct rt_msghdr *rtm;
968: struct if_data *ifd = NULL;
969: struct sockaddr *sa, *rti_info[RTAX_MAX];
970: struct sockaddr_dl *sdl;
971: char *buf, *next, *lim;
972: char name[IFNAMSIZ];
973: size_t len;
974:
1.70 pooka 975: if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
1.64 elad 976: err(1, "sysctl");
977: if ((buf = malloc(len)) == NULL)
978: err(1, NULL);
1.70 pooka 979: if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1)
1.64 elad 980: err(1, "sysctl");
981:
982: lim = buf + len;
983: for (next = buf; next < lim; next += rtm->rtm_msglen) {
984: rtm = (struct rt_msghdr *)next;
985: if (rtm->rtm_version != RTM_VERSION)
986: continue;
987: switch (rtm->rtm_type) {
988: case RTM_IFINFO:
989: ifm = (struct if_msghdr *)next;
990: ifd = &ifm->ifm_data;
991:
992: sa = (struct sockaddr *)(ifm + 1);
993: get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
994:
995: sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
996: if (sdl == NULL || sdl->sdl_family != AF_LINK)
997: continue;
998: bzero(name, sizeof(name));
999: if (sdl->sdl_nlen >= IFNAMSIZ)
1000: memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
1001: else if (sdl->sdl_nlen > 0)
1002: memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
1003:
1004: if (interface != 0 && !strcmp(name, interface)) {
1005: strlcpy(ip_cur.ift_name, name,
1006: sizeof(ip_cur.ift_name));
1007: ip_cur.ift_ip = ifd->ifi_ipackets;
1008: ip_cur.ift_ib = ifd->ifi_ibytes;
1009: ip_cur.ift_ie = ifd->ifi_ierrors;
1010: ip_cur.ift_op = ifd->ifi_opackets;
1011: ip_cur.ift_ob = ifd->ifi_obytes;
1012: ip_cur.ift_oe = ifd->ifi_oerrors;
1013: ip_cur.ift_co = ifd->ifi_collisions;
1014: ip_cur.ift_dr = 0;
1015: /* XXX-elad ifnet.if_snd.ifq_drops */
1016: }
1017:
1018: sum_cur.ift_ip += ifd->ifi_ipackets;
1019: sum_cur.ift_ib += ifd->ifi_ibytes;
1020: sum_cur.ift_ie += ifd->ifi_ierrors;
1021: sum_cur.ift_op += ifd->ifi_opackets;
1022: sum_cur.ift_ob += ifd->ifi_obytes;
1023: sum_cur.ift_oe += ifd->ifi_oerrors;
1024: sum_cur.ift_co += ifd->ifi_collisions;
1025: sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */
1026: break;
1027: }
1028: }
1029: if (interface == NULL) {
1030: strlcpy(ip_cur.ift_name, name,
1031: sizeof(ip_cur.ift_name));
1032: ip_cur.ift_ip = ifd->ifi_ipackets;
1033: ip_cur.ift_ib = ifd->ifi_ibytes;
1034: ip_cur.ift_ie = ifd->ifi_ierrors;
1035: ip_cur.ift_op = ifd->ifi_opackets;
1036: ip_cur.ift_ob = ifd->ifi_obytes;
1037: ip_cur.ift_oe = ifd->ifi_oerrors;
1038: ip_cur.ift_co = ifd->ifi_collisions;
1039: ip_cur.ift_dr = 0;
1040: /* XXX-elad ifnet.if_snd.ifq_drops */
1041: }
1.1 cgd 1042: }
CVSweb <webmaster@jp.NetBSD.org>