]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/if.c
1ff9fd92eb1edad31b1f6541661d6ac2957dd974
[apple/network_cmds.git] / netstat.tproj / if.c
1 /*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 /*
36 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
37 */
38 static const char rcsid[] =
39 "$Id: if.c,v 1.7 2006/01/16 04:53:59 lindak Exp $";
40 #endif /* not lint */
41
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/sysctl.h>
45 #include <sys/time.h>
46
47 #include <net/if.h>
48 #include <net/if_var.h>
49 #include <net/if_dl.h>
50 #include <net/if_types.h>
51 #include <net/if_mib.h>
52 #include <net/ethernet.h>
53 #include <net/route.h>
54
55 #include <netinet/in.h>
56 #include <netinet/in_var.h>
57
58 #ifdef IPX
59 #include <netipx/ipx.h>
60 #include <netipx/ipx_if.h>
61 #endif
62
63 #ifdef NS
64 #include <netns/ns.h>
65 #include <netns/ns_if.h>
66 #endif
67 #include <arpa/inet.h>
68
69 #include <signal.h>
70 #include <stdio.h>
71 #include <string.h>
72 #include <unistd.h>
73 #include <stdlib.h>
74 #include <err.h>
75
76 #include "netstat.h"
77
78 #define YES 1
79 #define NO 0
80
81 #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
82
83 #define NEXT_SA(p) (struct sockaddr *) \
84 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(u_long)) : \
85 sizeof(u_long)))
86
87 static void sidewaysintpr ();
88 static void catchalarm (int);
89
90 #ifdef INET6
91 char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
92 static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
93 #endif
94
95 #if 0
96 #ifdef INET6
97 static int bdg_done;
98 #endif
99
100 /* print bridge statistics */
101 void
102 bdg_stats(u_long dummy , char *name, int af )
103 {
104 int i;
105 size_t slen ;
106 struct bdg_stats s ;
107 int mib[4] ;
108
109 slen = sizeof(s);
110
111 mib[0] = CTL_NET ;
112 mib[1] = PF_LINK ;
113 mib[2] = IFT_ETHER ;
114 if (sysctl(mib,4, &s,&slen,NULL,0)==-1)
115 return ; /* no bridging */
116 #ifdef INET6
117 if (bdg_done != 0)
118 return;
119 else
120 bdg_done = 1;
121 #endif
122 printf("-- Bridging statistics (%s) --\n", name) ;
123 printf(
124 "Name In Out Forward Drop Bcast Mcast Local Unknown\n");
125 for (i = 0 ; i < 16 ; i++) {
126 if (s.s[i].name[0])
127 printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n",
128 s.s[i].name,
129 s.s[i].p_in[(int)BDG_IN],
130 s.s[i].p_in[(int)BDG_OUT],
131 s.s[i].p_in[(int)BDG_FORWARD],
132 s.s[i].p_in[(int)BDG_DROP],
133 s.s[i].p_in[(int)BDG_BCAST],
134 s.s[i].p_in[(int)BDG_MCAST],
135 s.s[i].p_in[(int)BDG_LOCAL],
136 s.s[i].p_in[(int)BDG_UNKNOWN] );
137 }
138 }
139
140 #endif
141
142
143 /*
144 * Display a formatted value, or a '-' in the same space.
145 */
146 static void
147 show_stat(const char *fmt, int width, u_int64_t value, short showvalue)
148 {
149 char newfmt[32];
150
151 /* Construct the format string */
152 if (showvalue) {
153 sprintf(newfmt, "%%%d%s", width, fmt);
154 printf(newfmt, value);
155 } else {
156 sprintf(newfmt, "%%%ds", width);
157 printf(newfmt, "-");
158 }
159 }
160
161 size_t
162 get_rti_info(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
163 {
164 int i;
165 size_t len = 0;
166
167 for (i = 0; i < RTAX_MAX; i++) {
168 if (addrs & (1 << i)) {
169 rti_info[i] = sa;
170 if (sa->sa_len < sizeof(struct sockaddr))
171 len += sizeof(struct sockaddr);
172 else
173 len += sa->sa_len;
174 sa = NEXT_SA(sa);
175 } else {
176 rti_info[i] = NULL;
177 }
178 }
179 return len;
180 }
181
182 static void
183 multipr(int family, char *buf, char *lim)
184 {
185 char *next;
186
187 for (next = buf; next < lim; ) {
188 struct ifma_msghdr2 *ifmam = (struct ifma_msghdr2 *)next;
189 struct sockaddr *rti_info[RTAX_MAX];
190 struct sockaddr *sa;
191 const char *fmt = 0;
192
193 next += ifmam->ifmam_msglen;
194 if (ifmam->ifmam_type == RTM_IFINFO2)
195 break;
196 else if (ifmam->ifmam_type != RTM_NEWMADDR2)
197 continue;
198 get_rti_info(ifmam->ifmam_addrs, (struct sockaddr*)(ifmam + 1), rti_info);
199 sa = rti_info[RTAX_IFA];
200
201 if (sa->sa_family != family)
202 continue;
203 switch (sa->sa_family) {
204 case AF_INET: {
205 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
206
207 fmt = routename(sin->sin_addr.s_addr);
208 break;
209 }
210 #ifdef INET6
211 case AF_INET6: {
212 struct sockaddr_in6 sin6;
213
214 memcpy(&sin6, sa, sizeof(struct sockaddr_in6));
215
216 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
217 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) {
218 sin6.sin6_scope_id =
219 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
220 sin6.sin6_addr.s6_addr[2] = 0;
221 sin6.sin6_addr.s6_addr[3] = 0;
222 }
223
224 printf("%23s %-19.19s(refs: %d)\n", "",
225 inet_ntop(AF_INET6,
226 &sin6.sin6_addr,
227 ntop_buf,
228 sizeof(ntop_buf)),
229 ifmam->ifmam_refcount);
230 break;
231 }
232 #endif /* INET6 */
233 case AF_LINK: {
234 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
235
236 switch (sdl->sdl_type) {
237 case IFT_ETHER:
238 case IFT_FDDI:
239 fmt = ether_ntoa(
240 (struct ether_addr *)
241 LLADDR(sdl));
242 break;
243 }
244 break;
245 }
246 }
247 if (fmt)
248 printf("%23s %s\n", "", fmt);
249 }
250 }
251
252 /*
253 * Print a description of the network interfaces.
254 */
255 void
256 intpr(void (*pfunc)(char *))
257 {
258 u_int64_t opackets = 0;
259 u_int64_t ipackets = 0;
260 u_int64_t obytes = 0;
261 u_int64_t ibytes = 0;
262 u_int64_t oerrors = 0;
263 u_int64_t ierrors = 0;
264 u_int64_t collisions = 0;
265 u_long mtu = 0;
266 short timer = 0;
267 int drops = 0;
268 struct sockaddr *sa = NULL;
269 char name[32];
270 short network_layer;
271 short link_layer;
272 int mib[6];
273 char *buf = NULL, *lim, *next;
274 size_t len;
275 struct if_msghdr *ifm;
276 struct sockaddr *rti_info[RTAX_MAX];
277 unsigned int ifindex = 0;
278
279 if (interval) {
280 sidewaysintpr();
281 return;
282 }
283
284 if (interface != 0)
285 ifindex = if_nametoindex(interface);
286
287 mib[0] = CTL_NET; // networking subsystem
288 mib[1] = PF_ROUTE; // type of information
289 mib[2] = 0; // protocol (IPPROTO_xxx)
290 mib[3] = 0; // address family
291 mib[4] = NET_RT_IFLIST2; // operation
292 mib[5] = 0;
293 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
294 return;
295 if ((buf = malloc(len)) == NULL) {
296 printf("malloc failed\n");
297 exit(1);
298 }
299 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
300 if (buf)
301 free(buf);
302 return;
303 }
304 if (!pfunc) {
305 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
306 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
307 if (bflag)
308 printf(" %10.10s","Ibytes");
309 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
310 if (bflag)
311 printf(" %10.10s","Obytes");
312 printf(" %5s", "Coll");
313 if (tflag)
314 printf(" %s", "Time");
315 if (dflag)
316 printf(" %s", "Drop");
317 putchar('\n');
318 }
319 lim = buf + len;
320 for (next = buf; next < lim; ) {
321 char *cp;
322 int n, m;
323
324 network_layer = 0;
325 link_layer = 0;
326 ifm = (struct if_msghdr *)next;
327 next += ifm->ifm_msglen;
328
329 if (ifm->ifm_type == RTM_IFINFO2) {
330 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
331 struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
332
333 strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
334 name[sdl->sdl_nlen] = 0;
335 if (interface != 0 && if2m->ifm_index != ifindex)
336 continue;
337 cp = index(name, '\0');
338
339 if (pfunc) {
340 (*pfunc)(name);
341 continue;
342 }
343
344 if ((if2m->ifm_flags & IFF_UP) == 0)
345 *cp++ = '*';
346 *cp = '\0';
347
348 /*
349 * Get the interface stats. These may get
350 * overriden below on a per-interface basis.
351 */
352 opackets = if2m->ifm_data.ifi_opackets;
353 ipackets = if2m->ifm_data.ifi_ipackets;
354 obytes = if2m->ifm_data.ifi_obytes;
355 ibytes = if2m->ifm_data.ifi_ibytes;
356 oerrors =if2m->ifm_data.ifi_oerrors;
357 ierrors = if2m->ifm_data.ifi_ierrors;
358 collisions = if2m->ifm_data.ifi_collisions;
359 timer = if2m->ifm_timer;
360 drops = if2m->ifm_snd_drops;
361 mtu = if2m->ifm_data.ifi_mtu;
362
363 get_rti_info(if2m->ifm_addrs, (struct sockaddr*)(if2m + 1), rti_info);
364 sa = rti_info[RTAX_IFP];
365 } else if (ifm->ifm_type == RTM_NEWADDR) {
366 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
367
368 if (interface != 0 && ifam->ifam_index != ifindex)
369 continue;
370 get_rti_info(ifam->ifam_addrs, (struct sockaddr*)(ifam + 1), rti_info);
371 sa = rti_info[RTAX_IFA];
372 } else
373 continue;
374 printf("%-5.5s %-5lu ", name, mtu);
375
376 if (sa == 0) {
377 printf("%-13.13s ", "none");
378 printf("%-15.15s ", "none");
379 } else {
380 switch (sa->sa_family) {
381 case AF_UNSPEC:
382 printf("%-13.13s ", "none");
383 printf("%-15.15s ", "none");
384 break;
385 case AF_INET: {
386 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
387 struct sockaddr_in mask;
388
389 mask.sin_addr.s_addr = 0;
390 memcpy(&mask, rti_info[RTAX_NETMASK], ((struct sockaddr_in *)rti_info[RTAX_NETMASK])->sin_len);
391
392 printf("%-13.13s ", netname(sin->sin_addr.s_addr & mask.sin_addr.s_addr,
393 ntohl(mask.sin_addr.s_addr)));
394
395 printf("%-15.15s ",
396 routename(sin->sin_addr.s_addr));
397
398 network_layer = 1;
399 break;
400 }
401 #ifdef INET6
402 case AF_INET6: {
403 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
404 struct sockaddr *mask = (struct sockaddr *)rti_info[RTAX_NETMASK];
405
406 printf("%-11.11s ",
407 netname6(sin6,
408 mask));
409 printf("%-17.17s ",
410 (char *)inet_ntop(AF_INET6,
411 &sin6->sin6_addr,
412 ntop_buf, sizeof(ntop_buf)));
413
414 network_layer = 1;
415 break;
416 }
417 #endif /*INET6*/
418 case AF_LINK:
419 {
420 struct sockaddr_dl *sdl =
421 (struct sockaddr_dl *)sa;
422 char linknum[10];
423 cp = (char *)LLADDR(sdl);
424 n = sdl->sdl_alen;
425 sprintf(linknum, "<Link#%d>", sdl->sdl_index);
426 m = printf("%-11.11s ", linknum);
427 }
428 goto hexprint;
429 default:
430 m = printf("(%d)", sa->sa_family);
431 for (cp = sa->sa_len + (char *)sa;
432 --cp > sa->sa_data && (*cp == 0);) {}
433 n = cp - sa->sa_data + 1;
434 cp = sa->sa_data;
435 hexprint:
436 while (--n >= 0)
437 m += printf("%02x%c", *cp++ & 0xff,
438 n > 0 ? ':' : ' ');
439 m = 30 - m;
440 while (m-- > 0)
441 putchar(' ');
442
443 link_layer = 1;
444 break;
445 }
446 #ifndef __APPLE__
447 /*
448 * Fixup the statistics for interfaces that
449 * update stats for their network addresses
450 */
451 if (network_layer) {
452 opackets = ifaddr.in.ia_ifa.if_opackets;
453 ipackets = ifaddr.in.ia_ifa.if_ipackets;
454 obytes = ifaddr.in.ia_ifa.if_obytes;
455 ibytes = ifaddr.in.ia_ifa.if_ibytes;
456 }
457 #endif
458 }
459
460 show_stat("llu", 8, ipackets, link_layer|network_layer);
461 printf(" ");
462 show_stat("llu", 5, ierrors, link_layer);
463 printf(" ");
464 if (bflag) {
465 show_stat("llu", 10, ibytes, link_layer|network_layer);
466 printf(" ");
467 }
468 show_stat("llu", 8, opackets, link_layer|network_layer);
469 printf(" ");
470 show_stat("llu", 5, oerrors, link_layer);
471 printf(" ");
472 if (bflag) {
473 show_stat("llu", 10, obytes, link_layer|network_layer);
474 printf(" ");
475 }
476 show_stat("llu", 5, collisions, link_layer);
477 if (tflag) {
478 printf(" ");
479 show_stat("ll", 3, timer, link_layer);
480 }
481 if (dflag) {
482 printf(" ");
483 show_stat("ll", 3, drops, link_layer);
484 }
485 putchar('\n');
486
487 if (aflag)
488 multipr(sa->sa_family, next, lim);
489 }
490 }
491
492 struct iftot {
493 SLIST_ENTRY(iftot) chain;
494 char ift_name[16]; /* interface name */
495 u_int64_t ift_ip; /* input packets */
496 u_int64_t ift_ie; /* input errors */
497 u_int64_t ift_op; /* output packets */
498 u_int64_t ift_oe; /* output errors */
499 u_int64_t ift_co; /* collisions */
500 u_int64_t ift_dr; /* drops */
501 u_int64_t ift_ib; /* input bytes */
502 u_int64_t ift_ob; /* output bytes */
503 };
504
505 u_char signalled; /* set if alarm goes off "early" */
506
507 /*
508 * Print a running summary of interface statistics.
509 * Repeat display every interval seconds, showing statistics
510 * collected over that interval. Assumes that interval is non-zero.
511 * First line printed at top of screen is always cumulative.
512 * XXX - should be rewritten to use ifmib(4).
513 */
514 static void
515 sidewaysintpr()
516 {
517 struct iftot *total, *sum, *interesting;
518 register int line;
519 int first;
520 int name[6];
521 size_t len;
522 unsigned int ifcount, i;
523 struct ifmibdata *ifmdall = 0;
524 int interesting_row;
525 sigset_t sigset, oldsigset;
526 struct itimerval timer_interval;
527
528
529 /* Common OID prefix */
530 name[0] = CTL_NET;
531 name[1] = PF_LINK;
532 name[2] = NETLINK_GENERIC;
533
534 len = sizeof(int);
535 name[3] = IFMIB_SYSTEM;
536 name[4] = IFMIB_IFCOUNT;
537 if (sysctl(name, 5, &ifcount, &len, 0, 0) == 1)
538 err(1, "sysctl IFMIB_IFCOUNT");
539
540 len = ifcount * sizeof(struct ifmibdata);
541 ifmdall = malloc(len);
542 if (ifmdall == 0)
543 err(1, "malloc failed");
544 name[3] = IFMIB_IFALLDATA;
545 name[4] = 0;
546 name[5] = IFDATA_GENERAL;
547 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
548 err(1, "sysctl IFMIB_IFALLDATA");
549
550 interesting = NULL;
551 interesting_row = 0;
552 for (i = 0; i < ifcount; i++) {
553 struct ifmibdata *ifmd = ifmdall + i;
554
555 if (interface && strcmp(ifmd->ifmd_name, interface) == 0) {
556 if ((interesting = calloc(ifcount, sizeof(struct iftot))) == NULL)
557 err(1, "malloc failed");
558 interesting_row = i + 1;
559 snprintf(interesting->ift_name, 16, "(%s)", ifmd->ifmd_name);;
560 }
561 }
562 if ((total = calloc(1, sizeof(struct iftot))) == NULL)
563 err(1, "malloc failed");
564
565 if ((sum = calloc(1, sizeof(struct iftot))) == NULL)
566 err(1, "malloc failed");
567
568 /* create a timer that fires repeatedly every interval seconds */
569 timer_interval.it_value.tv_sec = interval;
570 timer_interval.it_value.tv_usec = 0;
571 timer_interval.it_interval.tv_sec = interval;
572 timer_interval.it_interval.tv_usec = 0;
573 (void)signal(SIGALRM, catchalarm);
574 signalled = NO;
575 (void)setitimer(ITIMER_REAL, &timer_interval, NULL);
576 first = 1;
577 banner:
578 printf("%17s %14s %16s", "input",
579 interesting ? interesting->ift_name : "(Total)", "output");
580 putchar('\n');
581 printf("%10s %5s %10s %10s %5s %10s %5s",
582 "packets", "errs", "bytes", "packets", "errs", "bytes", "colls");
583 if (dflag)
584 printf(" %5.5s", "drops");
585 putchar('\n');
586 fflush(stdout);
587 line = 0;
588 loop:
589 if (interesting != NULL) {
590 struct ifmibdata ifmd;
591
592 len = sizeof(struct ifmibdata);
593 name[3] = IFMIB_IFDATA;
594 name[4] = interesting_row;
595 name[5] = IFDATA_GENERAL;
596 if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1)
597 err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
598
599 if (!first) {
600 printf("%10llu %5llu %10llu %10llu %5llu %10llu %5llu",
601 ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip,
602 ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie,
603 ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib,
604 ifmd.ifmd_data.ifi_opackets - interesting->ift_op,
605 ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe,
606 ifmd.ifmd_data.ifi_obytes - interesting->ift_ob,
607 ifmd.ifmd_data.ifi_collisions - interesting->ift_co);
608 if (dflag)
609 printf(" %5llu", ifmd.ifmd_snd_drops - interesting->ift_dr);
610 }
611 interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets;
612 interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors;
613 interesting->ift_ib = ifmd.ifmd_data.ifi_ibytes;
614 interesting->ift_op = ifmd.ifmd_data.ifi_opackets;
615 interesting->ift_oe = ifmd.ifmd_data.ifi_oerrors;
616 interesting->ift_ob = ifmd.ifmd_data.ifi_obytes;
617 interesting->ift_co = ifmd.ifmd_data.ifi_collisions;
618 interesting->ift_dr = ifmd.ifmd_snd_drops;
619 } else {
620 unsigned int latest_ifcount;
621
622 len = sizeof(int);
623 name[3] = IFMIB_SYSTEM;
624 name[4] = IFMIB_IFCOUNT;
625 if (sysctl(name, 5, &latest_ifcount, &len, 0, 0) == 1)
626 err(1, "sysctl IFMIB_IFCOUNT");
627 if (latest_ifcount > ifcount) {
628 ifcount = latest_ifcount;
629 len = ifcount * sizeof(struct ifmibdata);
630 free(ifmdall);
631 ifmdall = malloc(len);
632 if (ifmdall == 0)
633 err(1, "malloc failed");
634 } else if (latest_ifcount > ifcount) {
635 ifcount = latest_ifcount;
636 len = ifcount * sizeof(struct ifmibdata);
637 }
638 len = ifcount * sizeof(struct ifmibdata);
639 name[3] = IFMIB_IFALLDATA;
640 name[4] = 0;
641 name[5] = IFDATA_GENERAL;
642 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
643 err(1, "sysctl IFMIB_IFALLDATA");
644
645 sum->ift_ip = 0;
646 sum->ift_ie = 0;
647 sum->ift_ib = 0;
648 sum->ift_op = 0;
649 sum->ift_oe = 0;
650 sum->ift_ob = 0;
651 sum->ift_co = 0;
652 sum->ift_dr = 0;
653 for (i = 0; i < ifcount; i++) {
654 struct ifmibdata *ifmd = ifmdall + i;
655
656 sum->ift_ip += ifmd->ifmd_data.ifi_ipackets;
657 sum->ift_ie += ifmd->ifmd_data.ifi_ierrors;
658 sum->ift_ib += ifmd->ifmd_data.ifi_ibytes;
659 sum->ift_op += ifmd->ifmd_data.ifi_opackets;
660 sum->ift_oe += ifmd->ifmd_data.ifi_oerrors;
661 sum->ift_ob += ifmd->ifmd_data.ifi_obytes;
662 sum->ift_co += ifmd->ifmd_data.ifi_collisions;
663 sum->ift_dr += ifmd->ifmd_snd_drops;
664 }
665 if (!first) {
666 printf("%10llu %5llu %10llu %10llu %5llu %10llu %5llu",
667 sum->ift_ip - total->ift_ip,
668 sum->ift_ie - total->ift_ie,
669 sum->ift_ib - total->ift_ib,
670 sum->ift_op - total->ift_op,
671 sum->ift_oe - total->ift_oe,
672 sum->ift_ob - total->ift_ob,
673 sum->ift_co - total->ift_co);
674 if (dflag)
675 printf(" %5llu", sum->ift_dr - total->ift_dr);
676 }
677 *total = *sum;
678 }
679 if (!first)
680 putchar('\n');
681 fflush(stdout);
682 sigemptyset(&sigset);
683 sigaddset(&sigset, SIGALRM);
684 (void)sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
685 if (!signalled) {
686 sigemptyset(&sigset);
687 sigsuspend(&sigset);
688 }
689 (void)sigprocmask(SIG_SETMASK, &oldsigset, NULL);
690
691 signalled = NO;
692 line++;
693 first = 0;
694 if (line == 21)
695 goto banner;
696 else
697 goto loop;
698 /*NOTREACHED*/
699 }
700
701 void
702 intervalpr(void (*pr)(u_long, char *, int), u_long off, char *name , int af)
703 {
704 struct itimerval timer_interval;
705 sigset_t sigset, oldsigset;
706
707 /* create a timer that fires repeatedly every interval seconds */
708 timer_interval.it_value.tv_sec = interval;
709 timer_interval.it_value.tv_usec = 0;
710 timer_interval.it_interval.tv_sec = interval;
711 timer_interval.it_interval.tv_usec = 0;
712 (void) signal(SIGALRM, catchalarm);
713 signalled = NO;
714 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
715
716 for (;;) {
717 pr(off, name, af);
718
719 fflush(stdout);
720 sigemptyset(&sigset);
721 sigaddset(&sigset, SIGALRM);
722 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
723 if (!signalled) {
724 sigemptyset(&sigset);
725 sigsuspend(&sigset);
726 }
727 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
728 signalled = NO;
729 }
730 }
731
732 /*
733 * Called if an interval expires before sidewaysintpr has completed a loop.
734 * Sets a flag to not wait for the alarm.
735 */
736 static void
737 catchalarm(int signo )
738 {
739 signalled = YES;
740 }