No empty .Rs/.Re
[netbsd-mini2440.git] / usr.bin / netstat / if.c
blobc6d9f52277b8e30595de2be1cff8e6b0a7159d09
1 /* $NetBSD: if.c,v 1.66 2009/09/13 21:46:23 pgoyette Exp $ */
3 /*
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
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.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
36 #else
37 __RCSID("$NetBSD: if.c,v 1.66 2009/09/13 21:46:23 pgoyette Exp $");
38 #endif
39 #endif /* not lint */
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
45 #include <sys/time.h>
46 #include <sys/sysctl.h>
48 #include <net/if.h>
49 #include <net/if_dl.h>
50 #include <net/if_types.h>
51 #include <net/route.h>
52 #include <netinet/in.h>
53 #include <netinet/in_var.h>
54 #include <netiso/iso.h>
55 #include <netiso/iso_var.h>
56 #include <arpa/inet.h>
58 #include <kvm.h>
59 #include <signal.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <netdb.h>
65 #include <err.h>
67 #include "netstat.h"
69 #define MAXIF 100
71 struct iftot {
72 char ift_name[IFNAMSIZ]; /* interface name */
73 u_quad_t ift_ip; /* input packets */
74 u_quad_t ift_ib; /* input bytes */
75 u_quad_t ift_ie; /* input errors */
76 u_quad_t ift_op; /* output packets */
77 u_quad_t ift_ob; /* output bytes */
78 u_quad_t ift_oe; /* output errors */
79 u_quad_t ift_co; /* collisions */
80 int ift_dr; /* drops */
83 static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *);
84 static void sidewaysintpr(u_int, u_long);
86 static void iftot_banner(struct iftot *);
87 static void iftot_print_sum(struct iftot *, struct iftot *);
88 static void iftot_print(struct iftot *, struct iftot *);
90 static void catchalarm __P((int));
91 static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
92 static void fetchifs(void);
94 static void intpr_sysctl(void);
95 static void intpr_kvm(u_long, void (*)(const char *));
97 struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old;
98 bool signalled; /* set if alarm goes off "early" */
101 * Print a description of the network interfaces.
102 * NOTE: ifnetaddr is the location of the kernel global "ifnet",
103 * which is a TAILQ_HEAD.
105 void
106 intpr(interval, ifnetaddr, pfunc)
107 int interval;
108 u_long ifnetaddr;
109 void (*pfunc)(const char *);
112 if (interval) {
113 sidewaysintpr((unsigned)interval, ifnetaddr);
114 return;
117 if (use_sysctl) {
118 intpr_sysctl();
119 } else {
120 intpr_kvm(ifnetaddr, pfunc);
125 static void
126 intpr_header(void)
129 if (!sflag & !pflag) {
130 if (bflag) {
131 printf("%-5.5s %-5.5s %-13.13s %-17.17s "
132 "%10.10s %10.10s",
133 "Name", "Mtu", "Network", "Address",
134 "Ibytes", "Obytes");
135 } else {
136 printf("%-5.5s %-5.5s %-13.13s %-17.17s "
137 "%8.8s %5.5s %8.8s %5.5s %5.5s",
138 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
139 "Opkts", "Oerrs", "Colls");
141 if (tflag)
142 printf(" %4.4s", "Time");
143 if (dflag)
144 printf(" %5.5s", "Drops");
145 putchar('\n');
149 static void
150 intpr_sysctl(void)
152 struct if_msghdr *ifm;
153 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
154 char *buf = NULL, *next, *lim, *cp;
155 struct rt_msghdr *rtm;
156 struct ifa_msghdr *ifam;
157 struct if_data *ifd = NULL;
158 struct sockaddr *sa, *rti_info[RTAX_MAX];
159 struct sockaddr_dl *sdl;
160 uint64_t total = 0;
161 size_t len;
162 char name[IFNAMSIZ + 1]; /* + 1 for `*' */
164 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
165 err(1, "sysctl");
166 if ((buf = malloc(len)) == NULL)
167 err(1, NULL);
168 if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
169 err(1, "sysctl");
171 intpr_header();
173 lim = buf + len;
174 for (next = buf; next < lim; next += rtm->rtm_msglen) {
175 rtm = (struct rt_msghdr *)next;
176 if (rtm->rtm_version != RTM_VERSION)
177 continue;
178 switch (rtm->rtm_type) {
179 case RTM_IFINFO:
180 total = 0;
181 ifm = (struct if_msghdr *)next;
182 ifd = &ifm->ifm_data;
184 sa = (struct sockaddr *)(ifm + 1);
185 get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
187 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
188 if (sdl == NULL || sdl->sdl_family != AF_LINK) {
189 continue;
191 bzero(name, sizeof(name));
192 if (sdl->sdl_nlen >= IFNAMSIZ)
193 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
194 else if (sdl->sdl_nlen > 0)
195 memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
197 if (interface != 0 && strcmp(name, interface) != 0)
198 continue;
200 /* mark inactive interfaces with a '*' */
201 cp = strchr(name, '\0');
202 if ((ifm->ifm_flags & IFF_UP) == 0)
203 *cp++ = '*';
204 *cp = '\0';
206 if (qflag) {
207 total = ifd->ifi_ibytes + ifd->ifi_obytes +
208 ifd->ifi_ipackets + ifd->ifi_ierrors +
209 ifd->ifi_opackets + ifd->ifi_oerrors +
210 ifd->ifi_collisions;
211 if (tflag)
212 total += 0; // XXX-elad ifnet.if_timer;
213 if (dflag)
214 total += 0; // XXX-elad ifnet.if_snd.ifq_drops;
215 if (total == 0)
216 continue;
219 printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
220 print_addr(rti_info[RTAX_IFP], rti_info, ifd);
221 break;
223 case RTM_NEWADDR:
224 if (qflag && total == 0)
225 continue;
226 if (interface != 0 && strcmp(name, interface) != 0)
227 continue;
228 ifam = (struct ifa_msghdr *)next;
229 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
230 RTA_BRD)) == 0)
231 break;
233 sa = (struct sockaddr *)(ifam + 1);
235 get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
237 printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu);
238 print_addr(rti_info[RTAX_IFA], rti_info, ifd);
239 break;
244 static void
245 intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *))
247 struct ifnet ifnet;
248 union {
249 struct ifaddr ifa;
250 struct in_ifaddr in;
251 #ifdef INET6
252 struct in6_ifaddr in6;
253 #endif /* INET6 */
254 struct iso_ifaddr iso;
255 } ifaddr;
256 u_long ifaddraddr;
257 struct ifnet_head ifhead; /* TAILQ_HEAD */
258 char name[IFNAMSIZ + 1]; /* + 1 for `*' */
260 if (ifnetaddr == 0) {
261 printf("ifnet: symbol not defined\n");
262 return;
266 * Find the pointer to the first ifnet structure. Replace
267 * the pointer to the TAILQ_HEAD with the actual pointer
268 * to the first list element.
270 if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
271 return;
272 ifnetaddr = (u_long)ifhead.tqh_first;
274 intpr_header();
276 ifaddraddr = 0;
277 while (ifnetaddr || ifaddraddr) {
278 char *cp;
279 int n;
281 if (ifaddraddr == 0) {
282 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
283 return;
284 memmove(name, ifnet.if_xname, IFNAMSIZ);
285 name[IFNAMSIZ - 1] = '\0'; /* sanity */
286 ifnetaddr = (u_long)ifnet.if_list.tqe_next;
287 if (interface != 0 && strcmp(name, interface) != 0)
288 continue;
289 cp = strchr(name, '\0');
291 if (pfunc) {
292 (*pfunc)(name);
293 continue;
296 if ((ifnet.if_flags & IFF_UP) == 0)
297 *cp++ = '*';
298 *cp = '\0';
299 ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
301 if (vflag)
302 n = strlen(name) < 5 ? 5 : strlen(name);
303 else
304 n = 5;
305 printf("%-*.*s %-5llu ", n, n, name,
306 (unsigned long long)ifnet.if_mtu);
307 if (ifaddraddr == 0) {
308 printf("%-13.13s ", "none");
309 printf("%-17.17s ", "none");
310 } else {
311 struct sockaddr *sa;
313 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
314 ifaddraddr = 0;
315 continue;
317 #define CP(x) ((char *)(x))
318 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
319 CP(&ifaddr);
320 sa = (struct sockaddr *)cp;
321 print_addr(sa, (void *)&ifaddr, &ifnet.if_data);
323 ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
328 static void
329 print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd)
331 char hexsep = '.'; /* for hexprint */
332 static const char hexfmt[] = "%02x%c"; /* for hexprint */
333 char hbuf[NI_MAXHOST]; /* for getnameinfo() */
334 #ifdef INET6
335 const int niflag = NI_NUMERICHOST;
336 struct sockaddr_in6 *sin6, *netmask6;
337 #endif
338 in_addr_t netmask;
339 struct sockaddr_in *sin;
340 char *cp;
341 int n, m;
343 switch (sa->sa_family) {
344 case AF_UNSPEC:
345 printf("%-13.13s ", "none");
346 printf("%-17.17s ", "none");
347 break;
348 case AF_INET:
349 sin = (struct sockaddr_in *)sa;
350 #ifdef notdef
352 * can't use inet_makeaddr because kernel
353 * keeps nets unshifted.
355 in = inet_makeaddr(ifaddr.in.ia_subnet,
356 INADDR_ANY);
357 cp = netname4(in.s_addr,
358 ifaddr.in.ia_subnetmask);
359 #else
360 if (use_sysctl) {
361 netmask = ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr;
362 } else {
363 struct in_ifaddr *ifaddr_in = (void *)rtinfo;
364 netmask = ifaddr_in->ia_subnetmask;
366 cp = netname4(sin->sin_addr.s_addr, netmask);
367 #endif
368 if (vflag)
369 n = strlen(cp) < 13 ? 13 : strlen(cp);
370 else
371 n = 13;
372 printf("%-*.*s ", n, n, cp);
373 cp = routename4(sin->sin_addr.s_addr);
374 if (vflag)
375 n = strlen(cp) < 17 ? 17 : strlen(cp);
376 else
377 n = 17;
378 printf("%-*.*s ", n, n, cp);
380 #if 0 /* XXX-elad */
381 if (aflag) {
382 u_long multiaddr;
383 struct in_multi inm;
385 multiaddr = (u_long)
386 ifaddr.in.ia_multiaddrs.lh_first;
387 while (multiaddr != 0) {
388 kread(multiaddr, (char *)&inm,
389 sizeof inm);
390 printf("\n%25s %-17.17s ", "",
391 routename4(
392 inm.inm_addr.s_addr));
393 multiaddr =
394 (u_long)inm.inm_list.le_next;
397 #endif /* 0 */
398 break;
399 #ifdef INET6
400 case AF_INET6:
401 sin6 = (struct sockaddr_in6 *)sa;
402 #ifdef __KAME__
403 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
404 sin6->sin6_scope_id =
405 ntohs(*(u_int16_t *)
406 &sin6->sin6_addr.s6_addr[2]);
407 /* too little width */
408 if (!vflag)
409 sin6->sin6_scope_id = 0;
410 sin6->sin6_addr.s6_addr[2] = 0;
411 sin6->sin6_addr.s6_addr[3] = 0;
413 #endif
415 if (use_sysctl) {
416 netmask6 = (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK];
417 } else {
418 struct in6_ifaddr *ifaddr_in6 = (void *)rtinfo;
419 netmask6 = &ifaddr_in6->ia_prefixmask;
422 cp = netname6(sin6, netmask6);
423 if (vflag)
424 n = strlen(cp) < 13 ? 13 : strlen(cp);
425 else
426 n = 13;
427 printf("%-*.*s ", n, n, cp);
428 if (getnameinfo((struct sockaddr *)sin6,
429 sin6->sin6_len,
430 hbuf, sizeof(hbuf), NULL, 0,
431 niflag) != 0) {
432 strlcpy(hbuf, "?", sizeof(hbuf));
434 cp = hbuf;
435 if (vflag)
436 n = strlen(cp) < 17 ? 17 : strlen(cp);
437 else
438 n = 17;
439 printf("%-*.*s ", n, n, cp);
441 #if 0 /* XXX-elad */
442 if (aflag) {
443 u_long multiaddr;
444 struct in6_multi inm;
445 struct sockaddr_in6 as6;
447 multiaddr = (u_long)
448 ifaddr.in6.ia6_multiaddrs.lh_first;
449 while (multiaddr != 0) {
450 kread(multiaddr, (char *)&inm,
451 sizeof inm);
452 memset(&as6, 0, sizeof(as6));
453 as6.sin6_len = sizeof(struct sockaddr_in6);
454 as6.sin6_family = AF_INET6;
455 as6.sin6_addr = inm.in6m_addr;
456 #ifdef __KAME__
457 if (IN6_IS_ADDR_MC_LINKLOCAL(&as6.sin6_addr)) {
458 as6.sin6_scope_id =
459 ntohs(*(u_int16_t *)
460 &as6.sin6_addr.s6_addr[2]);
461 as6.sin6_addr.s6_addr[2] = 0;
462 as6.sin6_addr.s6_addr[3] = 0;
464 #endif
465 if (getnameinfo((struct sockaddr *)&as6,
466 as6.sin6_len, hbuf,
467 sizeof(hbuf), NULL, 0,
468 niflag) != 0) {
469 strlcpy(hbuf, "??",
470 sizeof(hbuf));
472 cp = hbuf;
473 if (vflag)
474 n = strlen(cp) < 17
475 ? 17 : strlen(cp);
476 else
477 n = 17;
478 printf("\n%25s %-*.*s ", "",
479 n, n, cp);
480 multiaddr =
481 (u_long)inm.in6m_entry.le_next;
484 #endif /* 0 */
485 break;
486 #endif /*INET6*/
487 #ifndef SMALL
488 case AF_APPLETALK:
489 printf("atalk:%-7.7s ",
490 atalk_print(sa,0x10));
491 printf("%-17.17s ", atalk_print(sa,0x0b));
492 break;
493 #endif
494 case AF_LINK:
495 printf("%-13.13s ", "<Link>");
496 if (getnameinfo(sa, sa->sa_len,
497 hbuf, sizeof(hbuf), NULL, 0,
498 NI_NUMERICHOST) != 0) {
499 strlcpy(hbuf, "?", sizeof(hbuf));
501 cp = hbuf;
502 if (vflag)
503 n = strlen(cp) < 17 ? 17 : strlen(cp);
504 else
505 n = 17;
506 printf("%-*.*s ", n, n, cp);
507 break;
509 default:
510 m = printf("(%d)", sa->sa_family);
511 for (cp = sa->sa_len + (char *)sa;
512 --cp > sa->sa_data && (*cp == 0);) {}
513 n = cp - sa->sa_data + 1;
514 cp = sa->sa_data;
516 while (--n >= 0)
517 m += printf(hexfmt, *cp++ & 0xff,
518 n > 0 ? hexsep : ' ');
519 m = 32 - m;
520 while (m-- > 0)
521 putchar(' ');
522 break;
525 if (bflag) {
526 printf("%10llu %10llu",
527 (unsigned long long)ifd->ifi_ibytes,
528 (unsigned long long)ifd->ifi_obytes);
529 } else {
530 printf("%8llu %5llu %8llu %5llu %5llu",
531 (unsigned long long)ifd->ifi_ipackets,
532 (unsigned long long)ifd->ifi_ierrors,
533 (unsigned long long)ifd->ifi_opackets,
534 (unsigned long long)ifd->ifi_oerrors,
535 (unsigned long long)ifd->ifi_collisions);
537 if (tflag)
538 printf(" %4d", 0 /* XXX-elad ifnet.if_timer */);
539 if (dflag)
540 printf(" %5d", 0 /* XXX-elad ifnet.if_snd.ifq_drops */);
541 putchar('\n');
544 static void
545 iftot_banner(struct iftot *ift)
547 if (bflag)
548 printf("%7.7s in %8.8s %6.6s out %5.5s",
549 ift->ift_name, " ",
550 ift->ift_name, " ");
551 else
552 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
553 ift->ift_name, " ",
554 ift->ift_name, " ", " ");
555 if (dflag)
556 printf(" %5.5s", " ");
558 if (bflag)
559 printf(" %7.7s in %8.8s %6.6s out %5.5s",
560 "total", " ", "total", " ");
561 else
562 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
563 "total", " ", "total", " ", " ");
564 if (dflag)
565 printf(" %5.5s", " ");
566 putchar('\n');
567 if (bflag)
568 printf("%10.10s %8.8s %10.10s %5.5s",
569 "bytes", " ", "bytes", " ");
570 else
571 printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
572 "packets", "errs", "packets", "errs", "colls");
573 if (dflag)
574 printf(" %5.5s", "drops");
576 if (bflag)
577 printf(" %10.10s %8.8s %10.10s %5.5s",
578 "bytes", " ", "bytes", " ");
579 else
580 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
581 "packets", "errs", "packets", "errs", "colls");
582 if (dflag)
583 printf(" %5.5s", "drops");
584 putchar('\n');
585 fflush(stdout);
588 static void
589 iftot_print(struct iftot *cur, struct iftot *old)
591 if (bflag)
592 printf("%10" PRIu64 "%8.8s %10" PRIu64 "%5.5s",
593 cur->ift_ib - old->ift_ib, " ",
594 cur->ift_ob - old->ift_ob, " ");
595 else
596 printf("%8" PRIu64 "%5" PRIu64 "%8" PRIu64 "%5" PRIu64 "%5" PRIu64,
597 cur->ift_ip - old->ift_ip,
598 cur->ift_ie - old->ift_ie,
599 cur->ift_op - old->ift_op,
600 cur->ift_oe - old->ift_oe,
601 cur->ift_co - old->ift_co);
602 if (dflag)
603 printf(" %5llu",
604 /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */
605 0LL);
608 static void
609 iftot_print_sum(struct iftot *cur, struct iftot *old)
611 if (bflag)
612 printf(" %10" PRIu64 "%8.8s %10" PRIu64 "%5.5s",
613 cur->ift_ib - old->ift_ib, " ",
614 cur->ift_ob - old->ift_ob, " ");
615 else
616 printf(" %8" PRIu64 "%5" PRIu64 "%8" PRIu64 "%5" PRIu64 "%5" PRIu64,
617 cur->ift_ip - old->ift_ip,
618 cur->ift_ie - old->ift_ie,
619 cur->ift_op - old->ift_op,
620 cur->ift_oe - old->ift_oe,
621 cur->ift_co - old->ift_co);
623 if (dflag)
624 printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr));
627 static void
628 sidewaysintpr_sysctl(unsigned interval)
630 sigset_t emptyset;
631 int line;
633 fetchifs();
634 if (ip_cur.ift_name[0] == '\0') {
635 fprintf(stderr, "%s: %s: unknown interface\n",
636 getprogname(), interface);
637 exit(1);
640 (void)signal(SIGALRM, catchalarm);
641 signalled = 0;
642 (void)alarm(interval);
643 banner:
644 iftot_banner(&ip_cur);
646 line = 0;
647 bzero(&ip_old, sizeof(ip_old));
648 bzero(&sum_old, sizeof(sum_old));
649 loop:
650 bzero(&sum_cur, sizeof(sum_cur));
652 fetchifs();
654 iftot_print(&ip_cur, &ip_old);
656 ip_old = ip_cur;
658 iftot_print_sum(&sum_cur, &sum_old);
660 sum_old = sum_cur;
662 putchar('\n');
663 fflush(stdout);
664 line++;
665 sigemptyset(&emptyset);
666 if (!signalled)
667 sigsuspend(&emptyset);
668 signalled = 0;
669 (void)alarm(interval);
670 if (line == 21)
671 goto banner;
672 goto loop;
673 /*NOTREACHED*/
676 static void
677 sidewaysintpr_kvm(unsigned interval, u_long off)
679 struct itimerval it;
680 struct ifnet ifnet;
681 u_long firstifnet;
682 struct iftot *ip, *total;
683 int line;
684 struct iftot *lastif, *sum, *interesting;
685 struct ifnet_head ifhead; /* TAILQ_HEAD */
686 int oldmask;
689 * Find the pointer to the first ifnet structure. Replace
690 * the pointer to the TAILQ_HEAD with the actual pointer
691 * to the first list element.
693 if (kread(off, (char *)&ifhead, sizeof ifhead))
694 return;
695 firstifnet = (u_long)ifhead.tqh_first;
697 lastif = iftot;
698 sum = iftot + MAXIF - 1;
699 total = sum - 1;
700 interesting = (interface == NULL) ? iftot : NULL;
701 for (off = firstifnet, ip = iftot; off;) {
702 if (kread(off, (char *)&ifnet, sizeof ifnet))
703 break;
704 memset(ip->ift_name, 0, sizeof(ip->ift_name));
705 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname);
706 if (interface && strcmp(ifnet.if_xname, interface) == 0)
707 interesting = ip;
708 ip++;
709 if (ip >= iftot + MAXIF - 2)
710 break;
711 off = (u_long)ifnet.if_list.tqe_next;
713 if (interesting == NULL) {
714 fprintf(stderr, "%s: %s: unknown interface\n",
715 getprogname(), interface);
716 exit(1);
718 lastif = ip;
720 (void)signal(SIGALRM, catchalarm);
721 signalled = false;
723 it.it_interval.tv_sec = it.it_value.tv_sec = interval;
724 it.it_interval.tv_usec = it.it_value.tv_usec = 0;
725 setitimer(ITIMER_REAL, &it, NULL);
727 banner:
728 if (bflag)
729 printf("%7.7s in %8.8s %6.6s out %5.5s",
730 interesting->ift_name, " ",
731 interesting->ift_name, " ");
732 else
733 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
734 interesting->ift_name, " ",
735 interesting->ift_name, " ", " ");
736 if (dflag)
737 printf(" %5.5s", " ");
738 if (lastif - iftot > 0) {
739 if (bflag)
740 printf(" %7.7s in %8.8s %6.6s out %5.5s",
741 "total", " ", "total", " ");
742 else
743 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
744 "total", " ", "total", " ", " ");
745 if (dflag)
746 printf(" %5.5s", " ");
748 for (ip = iftot; ip < iftot + MAXIF; ip++) {
749 ip->ift_ip = 0;
750 ip->ift_ib = 0;
751 ip->ift_ie = 0;
752 ip->ift_op = 0;
753 ip->ift_ob = 0;
754 ip->ift_oe = 0;
755 ip->ift_co = 0;
756 ip->ift_dr = 0;
758 putchar('\n');
759 if (bflag)
760 printf("%10.10s %8.8s %10.10s %5.5s",
761 "bytes", " ", "bytes", " ");
762 else
763 printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
764 "packets", "errs", "packets", "errs", "colls");
765 if (dflag)
766 printf(" %5.5s", "drops");
767 if (lastif - iftot > 0) {
768 if (bflag)
769 printf(" %10.10s %8.8s %10.10s %5.5s",
770 "bytes", " ", "bytes", " ");
771 else
772 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
773 "packets", "errs", "packets", "errs", "colls");
774 if (dflag)
775 printf(" %5.5s", "drops");
777 putchar('\n');
778 fflush(stdout);
779 line = 0;
780 loop:
781 sum->ift_ip = 0;
782 sum->ift_ib = 0;
783 sum->ift_ie = 0;
784 sum->ift_op = 0;
785 sum->ift_ob = 0;
786 sum->ift_oe = 0;
787 sum->ift_co = 0;
788 sum->ift_dr = 0;
789 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
790 if (kread(off, (char *)&ifnet, sizeof ifnet)) {
791 off = 0;
792 continue;
794 if (ip == interesting) {
795 if (bflag) {
796 printf("%10llu %8.8s %10llu %5.5s",
797 (unsigned long long)(ifnet.if_ibytes -
798 ip->ift_ib), " ",
799 (unsigned long long)(ifnet.if_obytes -
800 ip->ift_ob), " ");
801 } else {
802 printf("%8llu %5llu %8llu %5llu %5llu",
803 (unsigned long long)
804 (ifnet.if_ipackets - ip->ift_ip),
805 (unsigned long long)
806 (ifnet.if_ierrors - ip->ift_ie),
807 (unsigned long long)
808 (ifnet.if_opackets - ip->ift_op),
809 (unsigned long long)
810 (ifnet.if_oerrors - ip->ift_oe),
811 (unsigned long long)
812 (ifnet.if_collisions - ip->ift_co));
814 if (dflag)
815 printf(" %5llu",
816 (unsigned long long)
817 (ifnet.if_snd.ifq_drops - ip->ift_dr));
819 ip->ift_ip = ifnet.if_ipackets;
820 ip->ift_ib = ifnet.if_ibytes;
821 ip->ift_ie = ifnet.if_ierrors;
822 ip->ift_op = ifnet.if_opackets;
823 ip->ift_ob = ifnet.if_obytes;
824 ip->ift_oe = ifnet.if_oerrors;
825 ip->ift_co = ifnet.if_collisions;
826 ip->ift_dr = ifnet.if_snd.ifq_drops;
827 sum->ift_ip += ip->ift_ip;
828 sum->ift_ib += ip->ift_ib;
829 sum->ift_ie += ip->ift_ie;
830 sum->ift_op += ip->ift_op;
831 sum->ift_ob += ip->ift_ob;
832 sum->ift_oe += ip->ift_oe;
833 sum->ift_co += ip->ift_co;
834 sum->ift_dr += ip->ift_dr;
835 off = (u_long)ifnet.if_list.tqe_next;
837 if (lastif - iftot > 0) {
838 if (bflag) {
839 printf(" %10llu %8.8s %10llu %5.5s",
840 (unsigned long long)
841 (sum->ift_ib - total->ift_ib), " ",
842 (unsigned long long)
843 (sum->ift_ob - total->ift_ob), " ");
844 } else {
845 printf(" %8llu %5llu %8llu %5llu %5llu",
846 (unsigned long long)
847 (sum->ift_ip - total->ift_ip),
848 (unsigned long long)
849 (sum->ift_ie - total->ift_ie),
850 (unsigned long long)
851 (sum->ift_op - total->ift_op),
852 (unsigned long long)
853 (sum->ift_oe - total->ift_oe),
854 (unsigned long long)
855 (sum->ift_co - total->ift_co));
857 if (dflag)
858 printf(" %5llu",
859 (unsigned long long)(sum->ift_dr - total->ift_dr));
861 *total = *sum;
862 putchar('\n');
863 fflush(stdout);
864 line++;
865 oldmask = sigblock(sigmask(SIGALRM));
866 if (! signalled) {
867 sigpause(0);
869 sigsetmask(oldmask);
870 signalled = false;
871 if (line == 21)
872 goto banner;
873 goto loop;
874 /*NOTREACHED*/
878 * Print a running summary of interface statistics.
879 * Repeat display every interval seconds, showing statistics
880 * collected over that interval. Assumes that interval is non-zero.
881 * First line printed at top of screen is always cumulative.
883 static void
884 sidewaysintpr(interval, off)
885 unsigned interval;
886 u_long off;
889 if (use_sysctl) {
890 sidewaysintpr_sysctl(interval);
891 } else {
892 sidewaysintpr_kvm(interval, off);
897 * Called if an interval expires before sidewaysintpr has completed a loop.
898 * Sets a flag to not wait for the alarm.
900 static void
901 catchalarm(signo)
902 int signo;
905 signalled = true;
908 #define ROUNDUP(a, size) \
909 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
911 #define NEXT_SA(ap) (ap) = (struct sockaddr *) \
912 ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\
913 sizeof(u_long)) : sizeof(u_long)))
915 static void
916 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
918 int i;
920 for (i = 0; i < RTAX_MAX; i++) {
921 if (addrs & (1 << i)) {
922 rti_info[i] = sa;
923 NEXT_SA(sa);
924 /* sa = (struct sockaddr *)((char *)(sa) +
925 roundup(sa->sa_len, sizeof(long))); */
926 } else
927 rti_info[i] = NULL;
931 static void
932 fetchifs(void)
934 struct if_msghdr *ifm;
935 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
936 struct rt_msghdr *rtm;
937 struct if_data *ifd = NULL;
938 struct sockaddr *sa, *rti_info[RTAX_MAX];
939 struct sockaddr_dl *sdl;
940 char *buf, *next, *lim;
941 char name[IFNAMSIZ];
942 size_t len;
944 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
945 err(1, "sysctl");
946 if ((buf = malloc(len)) == NULL)
947 err(1, NULL);
948 if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
949 err(1, "sysctl");
951 lim = buf + len;
952 for (next = buf; next < lim; next += rtm->rtm_msglen) {
953 rtm = (struct rt_msghdr *)next;
954 if (rtm->rtm_version != RTM_VERSION)
955 continue;
956 switch (rtm->rtm_type) {
957 case RTM_IFINFO:
958 ifm = (struct if_msghdr *)next;
959 ifd = &ifm->ifm_data;
961 sa = (struct sockaddr *)(ifm + 1);
962 get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
964 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
965 if (sdl == NULL || sdl->sdl_family != AF_LINK)
966 continue;
967 bzero(name, sizeof(name));
968 if (sdl->sdl_nlen >= IFNAMSIZ)
969 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
970 else if (sdl->sdl_nlen > 0)
971 memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
973 if (interface != 0 && !strcmp(name, interface)) {
974 strlcpy(ip_cur.ift_name, name,
975 sizeof(ip_cur.ift_name));
976 ip_cur.ift_ip = ifd->ifi_ipackets;
977 ip_cur.ift_ib = ifd->ifi_ibytes;
978 ip_cur.ift_ie = ifd->ifi_ierrors;
979 ip_cur.ift_op = ifd->ifi_opackets;
980 ip_cur.ift_ob = ifd->ifi_obytes;
981 ip_cur.ift_oe = ifd->ifi_oerrors;
982 ip_cur.ift_co = ifd->ifi_collisions;
983 ip_cur.ift_dr = 0;
984 /* XXX-elad ifnet.if_snd.ifq_drops */
987 sum_cur.ift_ip += ifd->ifi_ipackets;
988 sum_cur.ift_ib += ifd->ifi_ibytes;
989 sum_cur.ift_ie += ifd->ifi_ierrors;
990 sum_cur.ift_op += ifd->ifi_opackets;
991 sum_cur.ift_ob += ifd->ifi_obytes;
992 sum_cur.ift_oe += ifd->ifi_oerrors;
993 sum_cur.ift_co += ifd->ifi_collisions;
994 sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */
995 break;
998 if (interface == NULL) {
999 strlcpy(ip_cur.ift_name, name,
1000 sizeof(ip_cur.ift_name));
1001 ip_cur.ift_ip = ifd->ifi_ipackets;
1002 ip_cur.ift_ib = ifd->ifi_ibytes;
1003 ip_cur.ift_ie = ifd->ifi_ierrors;
1004 ip_cur.ift_op = ifd->ifi_opackets;
1005 ip_cur.ift_ob = ifd->ifi_obytes;
1006 ip_cur.ift_oe = ifd->ifi_oerrors;
1007 ip_cur.ift_co = ifd->ifi_collisions;
1008 ip_cur.ift_dr = 0;
1009 /* XXX-elad ifnet.if_snd.ifq_drops */