2 * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1983, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
65 static const char rcsid
[] =
66 "$Id: if.c,v 1.7 2006/01/16 04:53:59 lindak Exp $";
69 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <sys/sysctl.h>
75 #include <net/if_var.h>
76 #include <net/if_dl.h>
77 #include <net/if_types.h>
78 #include <net/if_mib.h>
79 #include <net/if_llreach.h>
80 #include <net/ethernet.h>
81 #include <net/route.h>
83 #include <netinet/in.h>
84 #include <netinet/in_var.h>
86 #include <arpa/inet.h>
101 #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
103 #define NEXT_SA(p) (struct sockaddr *) \
104 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \
107 static void sidewaysintpr ();
108 static void catchalarm (int);
109 static char *sec2str(time_t);
110 static void llreach_sysctl(uint32_t);
113 char *netname6 (struct sockaddr_in6
*, struct sockaddr
*);
114 static char ntop_buf
[INET6_ADDRSTRLEN
]; /* for inet_ntop() */
118 * Display a formatted value, or a '-' in the same space.
121 show_stat(const char *fmt
, int width
, u_int64_t value
, short showvalue
)
125 /* Construct the format string */
127 snprintf(newfmt
, sizeof(newfmt
), "%%%d%s", width
, fmt
);
128 printf(newfmt
, value
);
130 snprintf(newfmt
, sizeof(newfmt
), "%%%ds", width
);
136 get_rti_info(int addrs
, struct sockaddr
*sa
, struct sockaddr
**rti_info
)
141 for (i
= 0; i
< RTAX_MAX
; i
++) {
142 if (addrs
& (1 << i
)) {
144 if (sa
->sa_len
< sizeof(struct sockaddr
))
145 len
+= sizeof(struct sockaddr
);
157 multipr(int family
, char *buf
, char *lim
)
161 for (next
= buf
; next
< lim
; ) {
162 struct ifma_msghdr2
*ifmam
= (struct ifma_msghdr2
*)next
;
163 struct sockaddr
*rti_info
[RTAX_MAX
];
167 next
+= ifmam
->ifmam_msglen
;
168 if (ifmam
->ifmam_type
== RTM_IFINFO2
)
170 else if (ifmam
->ifmam_type
!= RTM_NEWMADDR2
)
172 get_rti_info(ifmam
->ifmam_addrs
, (struct sockaddr
*)(ifmam
+ 1), rti_info
);
173 sa
= rti_info
[RTAX_IFA
];
175 if (sa
->sa_family
!= family
)
177 switch (sa
->sa_family
) {
179 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
181 fmt
= routename(sin
->sin_addr
.s_addr
);
186 struct sockaddr_in6 sin6
;
188 memcpy(&sin6
, sa
, sizeof(struct sockaddr_in6
));
190 if (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
191 IN6_IS_ADDR_MC_NODELOCAL(&sin6
.sin6_addr
) ||
192 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) {
193 sin6
.sin6_scope_id
= ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
194 sin6
.sin6_addr
.s6_addr
[2] = 0;
195 sin6
.sin6_addr
.s6_addr
[3] = 0;
198 printf("%23s %-19.19s(refs: %d)\n", "",
199 inet_ntop(AF_INET6
, &sin6
.sin6_addr
,
200 ntop_buf
, sizeof(ntop_buf
)),
201 ifmam
->ifmam_refcount
);
206 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sa
;
208 switch (sdl
->sdl_type
) {
211 fmt
= ether_ntoa((struct ether_addr
*)
219 printf("%23s %s\n", "", fmt
);
224 * Print a description of the network interfaces.
227 intpr(void (*pfunc
)(char *))
229 u_int64_t opackets
= 0;
230 u_int64_t ipackets
= 0;
231 u_int64_t obytes
= 0;
232 u_int64_t ibytes
= 0;
233 u_int64_t oerrors
= 0;
234 u_int64_t ierrors
= 0;
235 u_int64_t collisions
= 0;
239 struct sockaddr
*sa
= NULL
;
244 char *buf
= NULL
, *lim
, *next
;
246 struct if_msghdr
*ifm
;
247 struct sockaddr
*rti_info
[RTAX_MAX
];
248 unsigned int ifindex
= 0;
256 ifindex
= if_nametoindex(interface
);
258 mib
[0] = CTL_NET
; // networking subsystem
259 mib
[1] = PF_ROUTE
; // type of information
260 mib
[2] = 0; // protocol (IPPROTO_xxx)
261 mib
[3] = 0; // address family
262 mib
[4] = NET_RT_IFLIST2
; // operation
264 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
266 if ((buf
= malloc(len
)) == NULL
) {
267 printf("malloc failed\n");
270 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
277 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
278 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
280 printf(" %8.8s", "Itcpkts");
282 printf(" %10.10s","Ibytes");
284 printf(" %10.10s", "Itcbytes");
286 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
288 printf(" %8.8s", "Otcpkts");
290 printf(" %10.10s","Obytes");
292 printf(" %10.10s", "Otcbytes");
294 printf(" %5s", "Coll");
296 printf(" %s", "Time");
298 printf(" %s", "Drop");
302 for (next
= buf
; next
< lim
; ) {
305 struct ifmibdata_supplemental ifmsupp
;
306 u_int64_t ift_itcp
= 0; /* input tc packets */
307 u_int64_t ift_itcb
= 0; /* input tc bytes */
308 u_int64_t ift_otcp
= 0; /* output tc packets */
309 u_int64_t ift_otcb
= 0; /* output tc bytes */
311 bzero(&ifmsupp
, sizeof(struct ifmibdata_supplemental
));
315 ifm
= (struct if_msghdr
*)next
;
316 next
+= ifm
->ifm_msglen
;
318 if (ifm
->ifm_type
== RTM_IFINFO2
) {
319 struct if_msghdr2
*if2m
= (struct if_msghdr2
*)ifm
;
320 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)(if2m
+ 1);
322 strncpy(name
, sdl
->sdl_data
, sdl
->sdl_nlen
);
323 name
[sdl
->sdl_nlen
] = 0;
324 if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
326 cp
= index(name
, '\0');
333 if ((if2m
->ifm_flags
& IFF_UP
) == 0)
338 * Get the interface stats. These may get
339 * overriden below on a per-interface basis.
341 opackets
= if2m
->ifm_data
.ifi_opackets
;
342 ipackets
= if2m
->ifm_data
.ifi_ipackets
;
343 obytes
= if2m
->ifm_data
.ifi_obytes
;
344 ibytes
= if2m
->ifm_data
.ifi_ibytes
;
345 oerrors
=if2m
->ifm_data
.ifi_oerrors
;
346 ierrors
= if2m
->ifm_data
.ifi_ierrors
;
347 collisions
= if2m
->ifm_data
.ifi_collisions
;
348 timer
= if2m
->ifm_timer
;
349 drops
= if2m
->ifm_snd_drops
;
350 mtu
= if2m
->ifm_data
.ifi_mtu
;
354 size_t miblen
= sizeof(struct ifmibdata_supplemental
);
356 /* Common OID prefix */
359 name
[2] = NETLINK_GENERIC
;
360 name
[3] = IFMIB_IFDATA
;
361 name
[4] = if2m
->ifm_index
;
362 name
[5] = IFDATA_SUPPLEMENTAL
;
363 if (sysctl(name
, 6, &ifmsupp
, &miblen
, (void *)0, 0) == -1)
364 err(1, "sysctl IFDATA_SUPPLEMENTAL");
368 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
;
369 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
;
370 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
;
371 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
;
374 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
;
375 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
;
376 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
;
377 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
;
380 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
;
381 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
;
382 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
;
383 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
;
394 get_rti_info(if2m
->ifm_addrs
, (struct sockaddr
*)(if2m
+ 1), rti_info
);
395 sa
= rti_info
[RTAX_IFP
];
396 } else if (ifm
->ifm_type
== RTM_NEWADDR
) {
397 struct ifa_msghdr
*ifam
= (struct ifa_msghdr
*)ifm
;
399 if (interface
!= 0 && ifam
->ifam_index
!= ifindex
)
401 get_rti_info(ifam
->ifam_addrs
, (struct sockaddr
*)(ifam
+ 1), rti_info
);
402 sa
= rti_info
[RTAX_IFA
];
406 printf("%-5.5s %-5u ", name
, mtu
);
409 printf("%-13.13s ", "none");
410 printf("%-15.15s ", "none");
412 switch (sa
->sa_family
) {
414 printf("%-13.13s ", "none");
415 printf("%-15.15s ", "none");
419 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
420 struct sockaddr_in mask
;
422 mask
.sin_addr
.s_addr
= 0;
424 rti_info
[RTAX_NETMASK
],
425 ((struct sockaddr_in
*)rti_info
[RTAX_NETMASK
])->sin_len
);
428 netname(sin
->sin_addr
.s_addr
& mask
.sin_addr
.s_addr
,
429 ntohl(mask
.sin_addr
.s_addr
)));
432 routename(sin
->sin_addr
.s_addr
));
439 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)sa
;
440 struct sockaddr
*mask
= (struct sockaddr
*)rti_info
[RTAX_NETMASK
];
446 (char *)inet_ntop(AF_INET6
,
448 ntop_buf
, sizeof(ntop_buf
)));
455 struct sockaddr_dl
*sdl
=
456 (struct sockaddr_dl
*)sa
;
458 cp
= (char *)LLADDR(sdl
);
460 snprintf(linknum
, sizeof(linknum
), "<Link#%d>", sdl
->sdl_index
);
461 m
= printf("%-11.11s ", linknum
);
466 m
= printf("(%d)", sa
->sa_family
);
467 for (cp
= sa
->sa_len
+ (char *)sa
;
468 --cp
> sa
->sa_data
&& (*cp
== 0);) {}
469 n
= cp
- sa
->sa_data
+ 1;
473 m
+= printf("%02x%c", *cp
++ & 0xff,
484 show_stat("llu", 8, ipackets
, link_layer
|network_layer
);
486 show_stat("llu", 5, ierrors
, link_layer
);
489 show_stat("llu", 8, ift_itcp
, link_layer
|network_layer
);
493 show_stat("llu", 10, ibytes
, link_layer
|network_layer
);
496 show_stat("llu", 8, ift_itcb
, link_layer
|network_layer
);
500 show_stat("llu", 8, opackets
, link_layer
|network_layer
);
502 show_stat("llu", 5, oerrors
, link_layer
);
505 show_stat("llu", 8, ift_otcp
, link_layer
|network_layer
);
509 show_stat("llu", 10, obytes
, link_layer
|network_layer
);
512 show_stat("llu", 8, ift_otcb
, link_layer
|network_layer
);
516 show_stat("llu", 5, collisions
, link_layer
);
519 show_stat("ll", 3, timer
, link_layer
);
523 show_stat("ll", 3, drops
, link_layer
);
528 multipr(sa
->sa_family
, next
, lim
);
534 SLIST_ENTRY(iftot
) chain
;
535 char ift_name
[16]; /* interface name */
536 u_int64_t ift_ip
; /* input packets */
537 u_int64_t ift_ie
; /* input errors */
538 u_int64_t ift_op
; /* output packets */
539 u_int64_t ift_oe
; /* output errors */
540 u_int64_t ift_co
; /* collisions */
541 u_int64_t ift_dr
; /* drops */
542 u_int64_t ift_ib
; /* input bytes */
543 u_int64_t ift_ob
; /* output bytes */
544 u_int64_t ift_itcp
; /* input tc packets */
545 u_int64_t ift_itcb
; /* input tc bytes */
546 u_int64_t ift_otcp
; /* output tc packets */
547 u_int64_t ift_otcb
; /* output tc bytes */
550 u_char signalled
; /* set if alarm goes off "early" */
553 * Print a running summary of interface statistics.
554 * Repeat display every interval seconds, showing statistics
555 * collected over that interval. Assumes that interval is non-zero.
556 * First line printed at top of screen is always cumulative.
557 * XXX - should be rewritten to use ifmib(4).
562 struct iftot
*total
, *sum
, *interesting
;
567 unsigned int ifcount
, i
;
568 struct ifmibdata
*ifmdall
= 0;
570 sigset_t sigset
, oldsigset
;
571 struct itimerval timer_interval
;
573 /* Common OID prefix */
576 name
[2] = NETLINK_GENERIC
;
579 name
[3] = IFMIB_SYSTEM
;
580 name
[4] = IFMIB_IFCOUNT
;
581 if (sysctl(name
, 5, &ifcount
, &len
, 0, 0) == 1)
582 err(1, "sysctl IFMIB_IFCOUNT");
584 len
= ifcount
* sizeof(struct ifmibdata
);
585 ifmdall
= malloc(len
);
587 err(1, "malloc failed");
588 name
[3] = IFMIB_IFALLDATA
;
590 name
[5] = IFDATA_GENERAL
;
591 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
592 err(1, "sysctl IFMIB_IFALLDATA");
596 for (i
= 0; i
< ifcount
; i
++) {
597 struct ifmibdata
*ifmd
= ifmdall
+ i
;
599 if (interface
&& strcmp(ifmd
->ifmd_name
, interface
) == 0) {
600 if ((interesting
= calloc(ifcount
, sizeof(struct iftot
))) == NULL
)
601 err(1, "malloc failed");
602 interesting_row
= if_nametoindex(interface
);
603 snprintf(interesting
->ift_name
, 16, "(%s)", ifmd
->ifmd_name
);;
606 if ((total
= calloc(1, sizeof(struct iftot
))) == NULL
)
607 err(1, "malloc failed");
609 if ((sum
= calloc(1, sizeof(struct iftot
))) == NULL
)
610 err(1, "malloc failed");
612 /* create a timer that fires repeatedly every interval seconds */
613 timer_interval
.it_value
.tv_sec
= interval
;
614 timer_interval
.it_value
.tv_usec
= 0;
615 timer_interval
.it_interval
.tv_sec
= interval
;
616 timer_interval
.it_interval
.tv_usec
= 0;
617 (void)signal(SIGALRM
, catchalarm
);
619 (void)setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
623 printf("%37s %14s %16s", "input",
624 interesting
? interesting
->ift_name
: "(Total)", "output");
626 printf("%17s %14s %16s", "input",
627 interesting
? interesting
->ift_name
: "(Total)", "output");
629 printf("%10s %5s %10s ",
630 "packets", "errs", "bytes");
632 printf(" %10s %10s", "tcpkts", "tcbytes");
633 printf("%10s %5s %10s %5s",
634 "packets", "errs", "bytes", "colls");
636 printf(" %5.5s", "drops");
638 printf(" %10s %10s", "tcpkts", "tcbytes");
643 if (interesting
!= NULL
) {
644 struct ifmibdata ifmd
;
645 struct ifmibdata_supplemental ifmsupp
;
647 len
= sizeof(struct ifmibdata
);
648 name
[3] = IFMIB_IFDATA
;
649 name
[4] = interesting_row
;
650 name
[5] = IFDATA_GENERAL
;
651 if (sysctl(name
, 6, &ifmd
, &len
, (void *)0, 0) == -1)
652 err(1, "sysctl IFDATA_GENERAL %d", interesting_row
);
655 len
= sizeof(struct ifmibdata_supplemental
);
656 name
[3] = IFMIB_IFDATA
;
657 name
[4] = interesting_row
;
658 name
[5] = IFDATA_SUPPLEMENTAL
;
659 if (sysctl(name
, 6, &ifmsupp
, &len
, (void *)0, 0) == -1)
660 err(1, "sysctl IFDATA_SUPPLEMENTAL %d", interesting_row
);
663 printf("%10llu %5llu %10llu ",
664 ifmd
.ifmd_data
.ifi_ipackets
- interesting
->ift_ip
,
665 ifmd
.ifmd_data
.ifi_ierrors
- interesting
->ift_ie
,
666 ifmd
.ifmd_data
.ifi_ibytes
- interesting
->ift_ib
);
669 printf("%10llu %10llu ",
670 ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
- interesting
->ift_itcp
,
671 ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
- interesting
->ift_itcb
);
674 printf("%10llu %10llu ",
675 ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
- interesting
->ift_itcp
,
676 ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
- interesting
->ift_itcb
);
679 printf("%10llu %10llu ",
680 ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
- interesting
->ift_itcp
,
681 ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
- interesting
->ift_itcb
);
686 printf("%10llu %5llu %10llu %5llu",
687 ifmd
.ifmd_data
.ifi_opackets
- interesting
->ift_op
,
688 ifmd
.ifmd_data
.ifi_oerrors
- interesting
->ift_oe
,
689 ifmd
.ifmd_data
.ifi_obytes
- interesting
->ift_ob
,
690 ifmd
.ifmd_data
.ifi_collisions
- interesting
->ift_co
);
692 printf(" %5llu", ifmd
.ifmd_snd_drops
- interesting
->ift_dr
);
695 printf(" %10llu %10llu",
696 ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
- interesting
->ift_otcp
,
697 ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
- interesting
->ift_otcb
);
700 printf(" %10llu %10llu",
701 ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
- interesting
->ift_otcp
,
702 ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
- interesting
->ift_otcb
);
705 printf(" %10llu %10llu",
706 ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
- interesting
->ift_otcp
,
707 ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
- interesting
->ift_otcb
);
713 interesting
->ift_ip
= ifmd
.ifmd_data
.ifi_ipackets
;
714 interesting
->ift_ie
= ifmd
.ifmd_data
.ifi_ierrors
;
715 interesting
->ift_ib
= ifmd
.ifmd_data
.ifi_ibytes
;
716 interesting
->ift_op
= ifmd
.ifmd_data
.ifi_opackets
;
717 interesting
->ift_oe
= ifmd
.ifmd_data
.ifi_oerrors
;
718 interesting
->ift_ob
= ifmd
.ifmd_data
.ifi_obytes
;
719 interesting
->ift_co
= ifmd
.ifmd_data
.ifi_collisions
;
720 interesting
->ift_dr
= ifmd
.ifmd_snd_drops
;
721 /* private counters */
724 interesting
->ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
;
725 interesting
->ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
;
726 interesting
->ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
;
727 interesting
->ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
;
730 interesting
->ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
;
731 interesting
->ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
;
732 interesting
->ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
;
733 interesting
->ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
;
736 interesting
->ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
;
737 interesting
->ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
;
738 interesting
->ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
;
739 interesting
->ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
;
745 unsigned int latest_ifcount
;
746 struct ifmibdata_supplemental
*ifmsuppall
= NULL
;
749 name
[3] = IFMIB_SYSTEM
;
750 name
[4] = IFMIB_IFCOUNT
;
751 if (sysctl(name
, 5, &latest_ifcount
, &len
, 0, 0) == 1)
752 err(1, "sysctl IFMIB_IFCOUNT");
753 if (latest_ifcount
> ifcount
) {
754 ifcount
= latest_ifcount
;
755 len
= ifcount
* sizeof(struct ifmibdata
);
757 ifmdall
= malloc(len
);
759 err(1, "malloc ifmdall failed");
760 } else if (latest_ifcount
> ifcount
) {
761 ifcount
= latest_ifcount
;
762 len
= ifcount
* sizeof(struct ifmibdata
);
764 len
= ifcount
* sizeof(struct ifmibdata
);
765 name
[3] = IFMIB_IFALLDATA
;
767 name
[5] = IFDATA_GENERAL
;
768 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
769 err(1, "sysctl IFMIB_IFALLDATA");
771 len
= ifcount
* sizeof(struct ifmibdata_supplemental
);
772 ifmsuppall
= malloc(len
);
773 if (ifmsuppall
== NULL
)
774 err(1, "malloc ifmsuppall failed");
775 name
[3] = IFMIB_IFALLDATA
;
777 name
[5] = IFDATA_SUPPLEMENTAL
;
778 if (sysctl(name
, 6, ifmsuppall
, &len
, (void *)0, 0) == -1)
779 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
793 for (i
= 0; i
< ifcount
; i
++) {
794 struct ifmibdata
*ifmd
= ifmdall
+ i
;
796 sum
->ift_ip
+= ifmd
->ifmd_data
.ifi_ipackets
;
797 sum
->ift_ie
+= ifmd
->ifmd_data
.ifi_ierrors
;
798 sum
->ift_ib
+= ifmd
->ifmd_data
.ifi_ibytes
;
799 sum
->ift_op
+= ifmd
->ifmd_data
.ifi_opackets
;
800 sum
->ift_oe
+= ifmd
->ifmd_data
.ifi_oerrors
;
801 sum
->ift_ob
+= ifmd
->ifmd_data
.ifi_obytes
;
802 sum
->ift_co
+= ifmd
->ifmd_data
.ifi_collisions
;
803 sum
->ift_dr
+= ifmd
->ifmd_snd_drops
;
804 /* private counters */
806 struct ifmibdata_supplemental
*ifmsupp
= ifmsuppall
+ i
;
809 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkpackets
;
810 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkbytes
;
811 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_obkpackets
;
812 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_obkbytes
;
815 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivipackets
;
816 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivibytes
;
817 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovipackets
;
818 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovibytes
;
821 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivopackets
;
822 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivobytes
;
823 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovopackets
;
824 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovobytes
;
832 printf("%10llu %5llu %10llu ",
833 sum
->ift_ip
- total
->ift_ip
,
834 sum
->ift_ie
- total
->ift_ie
,
835 sum
->ift_ib
- total
->ift_ib
);
837 printf(" %10llu %10llu",
838 sum
->ift_itcp
- total
->ift_itcp
,
839 sum
->ift_itcb
- total
->ift_itcb
);
840 printf("%10llu %5llu %10llu %5llu",
841 sum
->ift_op
- total
->ift_op
,
842 sum
->ift_oe
- total
->ift_oe
,
843 sum
->ift_ob
- total
->ift_ob
,
844 sum
->ift_co
- total
->ift_co
);
846 printf(" %5llu", sum
->ift_dr
- total
->ift_dr
);
848 printf(" %10llu %10llu",
849 sum
->ift_otcp
- total
->ift_otcp
,
850 sum
->ift_otcb
- total
->ift_otcb
);
857 sigemptyset(&sigset
);
858 sigaddset(&sigset
, SIGALRM
);
859 (void)sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
861 sigemptyset(&sigset
);
864 (void)sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
877 intervalpr(void (*pr
)(uint32_t, char *, int), uint32_t off
, char *name
, int af
)
879 struct itimerval timer_interval
;
880 sigset_t sigset
, oldsigset
;
882 /* create a timer that fires repeatedly every interval seconds */
883 timer_interval
.it_value
.tv_sec
= interval
;
884 timer_interval
.it_value
.tv_usec
= 0;
885 timer_interval
.it_interval
.tv_sec
= interval
;
886 timer_interval
.it_interval
.tv_usec
= 0;
887 (void) signal(SIGALRM
, catchalarm
);
889 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
895 sigemptyset(&sigset
);
896 sigaddset(&sigset
, SIGALRM
);
897 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
899 sigemptyset(&sigset
);
902 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
908 * Called if an interval expires before sidewaysintpr has completed a loop.
909 * Sets a flag to not wait for the alarm.
912 catchalarm(int signo
)
921 static char result
[256];
922 int days
, hours
, mins
, secs
;
926 days
= total
/ 3600 / 24;
927 hours
= (total
/ 3600) % 24;
928 mins
= (total
/ 60) % 60;
933 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dd", days
);
935 if (!first
|| hours
) {
937 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dh", hours
);
939 if (!first
|| mins
) {
941 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dm", mins
);
943 snprintf(p
, sizeof(result
) - (p
- result
), "%ds", secs
);
949 intpr_ri(void (*pfunc
)(char *))
952 char *buf
= NULL
, *lim
, *next
;
954 unsigned int ifindex
= 0;
955 struct if_msghdr2
*if2m
;
957 if (interface
!= 0) {
958 ifindex
= if_nametoindex(interface
);
960 printf("interface name is not valid: %s\n", interface
);
965 mib
[0] = CTL_NET
; /* networking subsystem */
966 mib
[1] = PF_ROUTE
; /* type of information */
967 mib
[2] = 0; /* protocol (IPPROTO_xxx) */
968 mib
[3] = 0; /* address family */
969 mib
[4] = NET_RT_IFLIST2
; /* operation */
971 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
973 if ((buf
= malloc(len
)) == NULL
) {
974 printf("malloc failed\n");
977 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
982 printf("%-6s %-17s %8.8s %-9.9s %4s %4s\n",
983 "Proto", "Linklayer Address", "Netif", "Expire", "Refs", "Prbs");
986 if2m
= (struct if_msghdr2
*)buf
;
988 for (next
= buf
; next
< lim
; ) {
989 if2m
= (struct if_msghdr2
*)next
;
990 next
+= if2m
->ifm_msglen
;
992 if (if2m
->ifm_type
!= RTM_IFINFO2
)
994 else if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
997 llreach_sysctl(if2m
->ifm_index
);
1003 llreach_sysctl(uint32_t ifindex
)
1005 #define MAX_SYSCTL_TRY 5
1006 int mib
[6], i
, ntry
= 0;
1007 size_t mibsize
, len
, needed
, cnt
;
1008 struct if_llreach_info
*lri
;
1009 struct timeval time
;
1011 char ifname
[IF_NAMESIZE
];
1013 bzero(&mib
, sizeof (mib
));
1014 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1015 if (sysctlnametomib("net.link.generic.system.llreach_info", mib
,
1017 perror("sysctlnametomib");
1024 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1026 if (sysctl(mib
, mibsize
, NULL
, &needed
, NULL
, 0) == -1) {
1027 perror("sysctl net.link.generic.system.llreach_info");
1030 if ((buf
= malloc(needed
)) == NULL
) {
1034 if (sysctl(mib
, mibsize
, buf
, &needed
, NULL
, 0) == -1) {
1035 if (errno
!= ENOMEM
|| ++ntry
>= MAX_SYSCTL_TRY
) {
1042 } while (buf
== NULL
);
1045 cnt
= len
/ sizeof (*lri
);
1046 lri
= (struct if_llreach_info
*)buf
;
1048 gettimeofday(&time
, 0);
1049 if (if_indextoname(ifindex
, ifname
) == NULL
)
1050 snprintf(ifname
, sizeof (ifname
), "%s", "?");
1052 for (i
= 0; i
< cnt
; i
++, lri
++) {
1053 printf("0x%-4x %-17s %8.8s ", lri
->lri_proto
,
1054 ether_ntoa((struct ether_addr
*)lri
->lri_addr
), ifname
);
1056 if (lri
->lri_expire
> time
.tv_sec
)
1057 printf("%-9.9s", sec2str(lri
->lri_expire
- time
.tv_sec
));
1058 else if (lri
->lri_expire
== 0)
1059 printf("%-9.9s", "permanent");
1061 printf("%-9.9s", "expired");
1063 printf(" %4d", lri
->lri_refcnt
);
1064 if (lri
->lri_probes
)
1065 printf(" %4d", lri
->lri_probes
);
1067 len
-= sizeof (*lri
);
1070 fprintf(stderr
, "warning: %u trailing bytes from %s\n",
1071 (unsigned int)len
, "net.link.generic.system.llreach_info");
1076 #undef MAX_SYSCTL_TRY