Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / cmd / cmd-inet / usr.bin / netstat / netstat.c
blobb7318155d507cfdea42c1ced098154c6bd56879b
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
24 * netstat.c 2.2, last change 9/9/91
25 * MROUTING Revision 3.5
26 * Copyright 2018, Joyent, Inc.
30 * simple netstat based on snmp/mib-2 interface to the TCP/IP stack
32 * NOTES:
33 * 1. A comment "LINTED: (note 1)" appears before certain lines where
34 * lint would have complained, "pointer cast may result in improper
35 * alignment". These are lines where lint had suspected potential
36 * improper alignment of a data structure; in each such situation
37 * we have relied on the kernel guaranteeing proper alignment.
38 * 2. Some 'for' loops have been commented as "'for' loop 1", etc
39 * because they have 'continue' or 'break' statements in their
40 * bodies. 'continue' statements have been used inside some loops
41 * where avoiding them would have led to deep levels of indentation.
43 * TODO:
44 * Add ability to request subsets from kernel (with level = MIB2_IP;
45 * name = 0 meaning everything for compatibility)
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdarg.h>
51 #include <unistd.h>
52 #include <strings.h>
53 #include <string.h>
54 #include <errno.h>
55 #include <ctype.h>
56 #include <kstat.h>
57 #include <assert.h>
58 #include <locale.h>
59 #include <synch.h>
60 #include <thread.h>
62 #include <sys/types.h>
63 #include <sys/stream.h>
64 #include <stropts.h>
65 #include <sys/strstat.h>
66 #include <sys/tihdr.h>
68 #include <sys/socket.h>
69 #include <sys/sockio.h>
70 #include <netinet/in.h>
71 #include <net/if.h>
72 #include <net/route.h>
74 #include <inet/mib2.h>
75 #include <inet/ip.h>
76 #include <inet/arp.h>
77 #include <inet/tcp.h>
78 #include <netinet/igmp_var.h>
79 #include <netinet/ip_mroute.h>
81 #include <arpa/inet.h>
82 #include <netdb.h>
83 #include <fcntl.h>
84 #include <sys/systeminfo.h>
85 #include <arpa/inet.h>
87 #include <netinet/dhcp.h>
88 #include <dhcpagent_ipc.h>
89 #include <dhcpagent_util.h>
90 #include <compat.h>
92 #include "statcommon.h"
94 extern void unixpr(kstat_ctl_t *kc);
96 #define STR_EXPAND 4
98 #define V4MASK_TO_V6(v4, v6) ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
99 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \
100 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \
101 (v6)._S6_un._S6_u32[3] = (v4))
103 #define IN6_IS_V4MASK(v6) ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
104 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \
105 (v6)._S6_un._S6_u32[2] == 0xfffffffful)
108 * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
109 * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
110 * possible for an administrator to plumb new interfaces between those two
111 * calls, resulting in the failure of the latter. This addition makes that
112 * less likely.
114 #define LIFN_GUARD_VALUE 10
116 typedef struct mib_item_s {
117 struct mib_item_s *next_item;
118 int group;
119 int mib_id;
120 int length;
121 void *valp;
122 } mib_item_t;
124 struct ifstat {
125 uint64_t ipackets;
126 uint64_t ierrors;
127 uint64_t opackets;
128 uint64_t oerrors;
129 uint64_t collisions;
132 struct iflist {
133 struct iflist *next_if;
134 char ifname[LIFNAMSIZ];
135 struct ifstat tot;
138 static mib_item_t *mibget(int sd);
139 static void mibfree(mib_item_t *firstitem);
140 static int mibopen(void);
141 static void mib_get_constants(mib_item_t *item);
142 static mib_item_t *mib_item_dup(mib_item_t *item);
143 static mib_item_t *mib_item_diff(mib_item_t *item1,
144 mib_item_t *item2);
145 static void mib_item_destroy(mib_item_t **item);
147 static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b);
148 static char *octetstr(const Octet_t *op, int code,
149 char *dst, uint_t dstlen);
150 static char *pr_addr(uint_t addr,
151 char *dst, uint_t dstlen);
152 static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
153 static char *pr_addr6(const in6_addr_t *addr,
154 char *dst, uint_t dstlen);
155 static char *pr_mask(uint_t addr,
156 char *dst, uint_t dstlen);
157 static char *pr_prefix6(const struct in6_addr *addr,
158 uint_t prefixlen, char *dst, uint_t dstlen);
159 static char *pr_ap(uint_t addr, uint_t port,
160 char *proto, char *dst, uint_t dstlen);
161 static char *pr_ap6(const in6_addr_t *addr, uint_t port,
162 char *proto, char *dst, uint_t dstlen);
163 static char *pr_net(uint_t addr, uint_t mask,
164 char *dst, uint_t dstlen);
165 static char *pr_netaddr(uint_t addr, uint_t mask,
166 char *dst, uint_t dstlen);
167 static char *fmodestr(uint_t fmode);
168 static char *portname(uint_t port, char *proto,
169 char *dst, uint_t dstlen);
171 static const char *mitcp_state(int code);
172 static const char *miudp_state(int code);
174 static void stat_report(mib_item_t *item);
175 static void mrt_stat_report(mib_item_t *item);
176 static void arp_report(mib_item_t *item);
177 static void ndp_report(mib_item_t *item);
178 static void mrt_report(mib_item_t *item);
179 static void if_stat_total(struct ifstat *oldstats,
180 struct ifstat *newstats, struct ifstat *sumstats);
181 static void if_report(mib_item_t *item, char *ifname,
182 int Iflag_only, boolean_t once_only);
183 static void if_report_ip4(mib2_ipAddrEntry_t *ap,
184 char ifname[], char logintname[],
185 struct ifstat *statptr, boolean_t ksp_not_null);
186 static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
187 char ifname[], char logintname[],
188 struct ifstat *statptr, boolean_t ksp_not_null);
189 static void ire_report(const mib_item_t *item);
190 static void tcp_report(const mib_item_t *item);
191 static void udp_report(const mib_item_t *item);
192 static void group_report(mib_item_t *item);
193 static void dce_report(mib_item_t *item);
194 static void print_ip_stats(mib2_ip_t *ip);
195 static void print_icmp_stats(mib2_icmp_t *icmp);
196 static void print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
197 static void print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
198 static void print_sctp_stats(mib2_sctp_t *tcp);
199 static void print_tcp_stats(mib2_tcp_t *tcp);
200 static void print_udp_stats(mib2_udp_t *udp);
201 static void print_rawip_stats(mib2_rawip_t *rawip);
202 static void print_igmp_stats(struct igmpstat *igps);
203 static void print_mrt_stats(struct mrtstat *mrts);
204 static void sctp_report(const mib_item_t *item);
205 static void sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
206 mib2_ipv6IfStatsEntry_t *sum6);
207 static void sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
208 mib2_ipv6IfIcmpEntry_t *sum6);
209 static void m_report(void);
210 static void dhcp_report(char *);
212 static uint64_t kstat_named_value(kstat_t *, char *);
213 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
214 static int isnum(char *);
215 static char *plural(int n);
216 static char *pluraly(int n);
217 static char *plurales(int n);
218 static void process_filter(char *arg);
219 static char *ifindex2str(uint_t, char *);
220 static boolean_t family_selected(int family);
222 static void usage(char *);
223 static void fatal(int errcode, char *str1, ...);
225 #define PLURAL(n) plural((int)n)
226 #define PLURALY(n) pluraly((int)n)
227 #define PLURALES(n) plurales((int)n)
228 #define IFLAGMOD(flg, val1, val2) if (flg == val1) flg = val2
229 #define MDIFF(diff, elem2, elem1, member) (diff)->member = \
230 (elem2)->member - (elem1)->member
233 static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */
234 static boolean_t CIDRflag = B_FALSE; /* CIDR for IPv4 -i/-r addrs */
235 static boolean_t Dflag = B_FALSE; /* DCE info */
236 static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */
237 static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */
238 static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */
239 static boolean_t Rflag = B_FALSE; /* Routing Tables */
240 static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */
241 static boolean_t Vflag = B_FALSE; /* Verbose */
242 static boolean_t Pflag = B_FALSE; /* Net to Media Tables */
243 static boolean_t Gflag = B_FALSE; /* Multicast group membership */
244 static boolean_t MMflag = B_FALSE; /* Multicast routing table */
245 static boolean_t DHCPflag = B_FALSE; /* DHCP statistics */
246 static boolean_t Xflag = B_FALSE; /* Debug Info */
248 static int v4compat = 0; /* Compatible printing format for status */
250 static int proto = IPPROTO_MAX; /* all protocols */
251 kstat_ctl_t *kc = NULL;
254 * Name service timeout detection constants.
256 static mutex_t ns_lock = ERRORCHECKMUTEX;
257 static boolean_t ns_active = B_FALSE; /* Is a lookup ongoing? */
258 static hrtime_t ns_starttime; /* Time the lookup started */
259 static int ns_sleeptime = 2; /* Time in seconds between checks */
260 static int ns_warntime = 2; /* Time in seconds before warning */
263 * Sizes of data structures extracted from the base mib.
264 * This allows the size of the tables entries to grow while preserving
265 * binary compatibility.
267 static int ipAddrEntrySize;
268 static int ipRouteEntrySize;
269 static int ipNetToMediaEntrySize;
270 static int ipMemberEntrySize;
271 static int ipGroupSourceEntrySize;
272 static int vifctlSize;
273 static int mfcctlSize;
275 static int ipv6IfStatsEntrySize;
276 static int ipv6IfIcmpEntrySize;
277 static int ipv6AddrEntrySize;
278 static int ipv6RouteEntrySize;
279 static int ipv6NetToMediaEntrySize;
280 static int ipv6MemberEntrySize;
281 static int ipv6GroupSourceEntrySize;
283 static int ipDestEntrySize;
285 static int tcpConnEntrySize;
286 static int tcp6ConnEntrySize;
287 static int udpEntrySize;
288 static int udp6EntrySize;
289 static int sctpEntrySize;
290 static int sctpLocalEntrySize;
291 static int sctpRemoteEntrySize;
293 #define protocol_selected(p) (proto == IPPROTO_MAX || proto == (p))
295 /* Machinery used for -f (filter) option */
296 enum { FK_AF = 0, FK_OUTIF, FK_DST, FK_FLAGS, NFILTERKEYS };
298 static const char *filter_keys[NFILTERKEYS] = {
299 "af", "outif", "dst", "flags"
302 /* Flags on routes */
303 #define FLF_A 0x00000001
304 #define FLF_b 0x00000002
305 #define FLF_D 0x00000004
306 #define FLF_G 0x00000008
307 #define FLF_H 0x00000010
308 #define FLF_L 0x00000020
309 #define FLF_U 0x00000040
310 #define FLF_S 0x00000100
311 #define FLF_C 0x00000200 /* IRE_IF_CLONE */
312 #define FLF_I 0x00000400 /* RTF_INDIRECT */
313 #define FLF_R 0x00000800 /* RTF_REJECT */
314 #define FLF_B 0x00001000 /* RTF_BLACKHOLE */
315 #define FLF_Z 0x00100000 /* RTF_ZONE */
317 static const char flag_list[] = "AbDGHLUMSCIRBZ";
319 typedef struct filter_rule filter_t;
321 struct filter_rule {
322 filter_t *f_next;
323 union {
324 int f_family;
325 const char *f_ifname;
326 struct {
327 struct hostent *f_address;
328 in6_addr_t f_mask;
329 } a;
330 struct {
331 uint_t f_flagset;
332 uint_t f_flagclear;
333 } f;
334 } u;
338 * The user-specified filters are linked into lists separated by
339 * keyword (type of filter). Thus, the matching algorithm is:
340 * For each non-empty filter list
341 * If no filters in the list match
342 * then stop here; route doesn't match
343 * If loop above completes, then route does match and will be
344 * displayed.
346 static filter_t *filters[NFILTERKEYS];
348 static uint_t timestamp_fmt = NODATE;
350 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
351 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't */
352 #endif
354 static void
355 ns_lookup_start(void)
357 mutex_enter(&ns_lock);
358 ns_active = B_TRUE;
359 ns_starttime = gethrtime();
360 mutex_exit(&ns_lock);
363 static void
364 ns_lookup_end(void)
366 mutex_enter(&ns_lock);
367 ns_active = B_FALSE;
368 mutex_exit(&ns_lock);
372 * When name services are not functioning, this program appears to hang to the
373 * user. To try and give the user a chance of figuring out that this might be
374 * the case, we end up warning them and suggest that they may want to use the -n
375 * flag.
377 /* ARGSUSED */
378 static void *
379 ns_warning_thr(void *unsued)
381 for (;;) {
382 hrtime_t now;
384 (void) sleep(ns_sleeptime);
385 now = gethrtime();
386 mutex_enter(&ns_lock);
387 if (ns_active && now - ns_starttime >= ns_warntime * NANOSEC) {
388 (void) fprintf(stderr, "warning: data "
389 "available, but name service lookups are "
390 "taking a while. Use the -n option to "
391 "disable name service lookups.\n");
392 mutex_exit(&ns_lock);
393 return (NULL);
395 mutex_exit(&ns_lock);
398 /* LINTED: E_STMT_NOT_REACHED */
399 return (NULL);
404 main(int argc, char **argv)
406 char *name;
407 mib_item_t *item = NULL;
408 mib_item_t *previtem = NULL;
409 int sd = -1;
410 char *ifname = NULL;
411 int interval = 0; /* Single time by default */
412 int count = -1; /* Forever */
413 int c;
414 int d;
416 * Possible values of 'Iflag_only':
417 * -1, no feature-flags;
418 * 0, IFlag and other feature-flags enabled
419 * 1, IFlag is the only feature-flag enabled
420 * : trinary variable, modified using IFLAGMOD()
422 int Iflag_only = -1;
423 boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
424 extern char *optarg;
425 extern int optind;
426 char *default_ip_str = NULL;
428 name = argv[0];
430 v4compat = get_compat_flag(&default_ip_str);
431 if (v4compat == DEFAULT_PROT_BAD_VALUE)
432 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
433 default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
434 free(default_ip_str);
436 (void) setlocale(LC_ALL, "");
437 (void) textdomain(TEXT_DOMAIN);
439 while ((c = getopt(argc, argv, "acdimnrspMgvxf:P:I:DT:")) != -1) {
440 switch ((char)c) {
441 case 'a': /* all connections */
442 Aflag = B_TRUE;
443 break;
445 case 'c':
446 CIDRflag = B_TRUE;
447 break;
449 case 'd': /* DCE info */
450 Dflag = B_TRUE;
451 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
452 break;
454 case 'i': /* interface (ill/ipif report) */
455 Iflag = B_TRUE;
456 IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
457 break;
459 case 'm': /* streams msg report */
460 Mflag = B_TRUE;
461 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
462 break;
464 case 'n': /* numeric format */
465 Nflag = B_TRUE;
466 break;
468 case 'r': /* route tables */
469 Rflag = B_TRUE;
470 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
471 break;
473 case 's': /* per-protocol statistics */
474 Sflag = B_TRUE;
475 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
476 break;
478 case 'p': /* arp/ndp table */
479 Pflag = B_TRUE;
480 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
481 break;
483 case 'M': /* multicast routing tables */
484 MMflag = B_TRUE;
485 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
486 break;
488 case 'g': /* multicast group membership */
489 Gflag = B_TRUE;
490 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
491 break;
493 case 'v': /* verbose output format */
494 Vflag = B_TRUE;
495 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
496 break;
498 case 'x': /* turn on debugging */
499 Xflag = B_TRUE;
500 break;
502 case 'f':
503 process_filter(optarg);
504 break;
506 case 'P':
507 if (strcmp(optarg, "ip") == 0) {
508 proto = IPPROTO_IP;
509 } else if (strcmp(optarg, "ipv6") == 0 ||
510 strcmp(optarg, "ip6") == 0) {
511 v4compat = 0; /* Overridden */
512 proto = IPPROTO_IPV6;
513 } else if (strcmp(optarg, "icmp") == 0) {
514 proto = IPPROTO_ICMP;
515 } else if (strcmp(optarg, "icmpv6") == 0 ||
516 strcmp(optarg, "icmp6") == 0) {
517 v4compat = 0; /* Overridden */
518 proto = IPPROTO_ICMPV6;
519 } else if (strcmp(optarg, "igmp") == 0) {
520 proto = IPPROTO_IGMP;
521 } else if (strcmp(optarg, "udp") == 0) {
522 proto = IPPROTO_UDP;
523 } else if (strcmp(optarg, "tcp") == 0) {
524 proto = IPPROTO_TCP;
525 } else if (strcmp(optarg, "sctp") == 0) {
526 proto = IPPROTO_SCTP;
527 } else if (strcmp(optarg, "raw") == 0 ||
528 strcmp(optarg, "rawip") == 0) {
529 proto = IPPROTO_RAW;
530 } else {
531 fatal(1, "%s: unknown protocol.\n", optarg);
533 break;
535 case 'I':
536 ifname = optarg;
537 Iflag = B_TRUE;
538 IFLAGMOD(Iflag_only, -1, 1); /* see macro def'n */
539 break;
541 case 'D':
542 DHCPflag = B_TRUE;
543 Iflag_only = 0;
544 break;
546 case 'T':
547 if (optarg) {
548 if (*optarg == 'u')
549 timestamp_fmt = UDATE;
550 else if (*optarg == 'd')
551 timestamp_fmt = DDATE;
552 else
553 usage(name);
554 } else {
555 usage(name);
557 break;
559 case '?':
560 default:
561 usage(name);
566 * Handle other arguments: find interval, count; the
567 * flags that accept 'interval' and 'count' are OR'd
568 * in the outermost 'if'; more flags may be added as
569 * required
571 if (Iflag || Sflag || Mflag) {
572 for (d = optind; d < argc; d++) {
573 if (isnum(argv[d])) {
574 interval = atoi(argv[d]);
575 if (d + 1 < argc &&
576 isnum(argv[d + 1])) {
577 count = atoi(argv[d + 1]);
578 optind++;
580 optind++;
581 if (interval == 0 || count == 0)
582 usage(name);
583 break;
587 if (optind < argc) {
588 if (Iflag && isnum(argv[optind])) {
589 count = atoi(argv[optind]);
590 if (count == 0)
591 usage(name);
592 optind++;
595 if (optind < argc) {
596 (void) fprintf(stderr,
597 "%s: extra arguments\n", name);
598 usage(name);
600 if (interval)
601 setbuf(stdout, NULL);
604 * Start up the thread to check for name services warnings.
606 if (thr_create(NULL, 0, ns_warning_thr, NULL,
607 THR_DETACHED | THR_DAEMON, NULL) != 0) {
608 fatal(1, "%s: failed to create name services "
609 "thread: %s\n", name, strerror(errno));
612 if (DHCPflag) {
613 dhcp_report(Iflag ? ifname : NULL);
614 exit(0);
617 /* Get data structures: priming before iteration */
618 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
619 sd = mibopen();
620 if (sd == -1)
621 fatal(1, "can't open mib stream\n");
622 if ((item = mibget(sd)) == NULL) {
623 (void) close(sd);
624 fatal(1, "mibget() failed\n");
626 /* Extract constant sizes - need do once only */
627 mib_get_constants(item);
629 if ((kc = kstat_open()) == NULL) {
630 mibfree(item);
631 (void) close(sd);
632 fail(1, "kstat_open(): can't open /dev/kstat");
635 if (interval <= 0) {
636 count = 1;
637 once_only = B_TRUE;
639 /* 'for' loop 1: */
640 for (;;) {
641 mib_item_t *curritem = NULL; /* only for -[M]s */
643 if (timestamp_fmt != NODATE)
644 print_timestamp(timestamp_fmt);
646 /* netstat: AF_INET[6] behaviour */
647 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
648 if (Sflag) {
649 curritem = mib_item_diff(previtem, item);
650 if (curritem == NULL)
651 fatal(1, "can't process mib data, "
652 "out of memory\n");
653 mib_item_destroy(&previtem);
656 if (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
657 MMflag || Pflag || Gflag || DHCPflag)) {
658 if (protocol_selected(IPPROTO_UDP))
659 udp_report(item);
660 if (protocol_selected(IPPROTO_TCP))
661 tcp_report(item);
662 if (protocol_selected(IPPROTO_SCTP))
663 sctp_report(item);
665 if (Iflag)
666 if_report(item, ifname, Iflag_only, once_only);
667 if (Mflag)
668 m_report();
669 if (Rflag)
670 ire_report(item);
671 if (Sflag && MMflag) {
672 mrt_stat_report(curritem);
673 } else {
674 if (Sflag)
675 stat_report(curritem);
676 if (MMflag)
677 mrt_report(item);
679 if (Gflag)
680 group_report(item);
681 if (Pflag) {
682 if (family_selected(AF_INET))
683 arp_report(item);
684 if (family_selected(AF_INET6))
685 ndp_report(item);
687 if (Dflag)
688 dce_report(item);
689 mib_item_destroy(&curritem);
692 /* netstat: AF_UNIX behaviour */
693 if (family_selected(AF_UNIX) &&
694 (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
695 MMflag || Pflag || Gflag)))
696 unixpr(kc);
697 (void) kstat_close(kc);
699 /* iteration handling code */
700 if (count > 0 && --count == 0)
701 break;
702 (void) sleep(interval);
704 /* re-populating of data structures */
705 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
706 if (Sflag) {
707 /* previtem is a cut-down list */
708 previtem = mib_item_dup(item);
709 if (previtem == NULL)
710 fatal(1, "can't process mib data, "
711 "out of memory\n");
713 mibfree(item);
714 (void) close(sd);
715 if ((sd = mibopen()) == -1)
716 fatal(1, "can't open mib stream anymore\n");
717 if ((item = mibget(sd)) == NULL) {
718 (void) close(sd);
719 fatal(1, "mibget() failed\n");
722 if ((kc = kstat_open()) == NULL)
723 fail(1, "kstat_open(): can't open /dev/kstat");
725 } /* 'for' loop 1 ends */
726 mibfree(item);
727 (void) close(sd);
728 return (0);
732 static int
733 isnum(char *p)
735 int len;
736 int i;
738 len = strlen(p);
739 for (i = 0; i < len; i++)
740 if (!isdigit(p[i]))
741 return (0);
742 return (1);
746 /* --------------------------------- MIBGET -------------------------------- */
748 static mib_item_t *
749 mibget(int sd)
752 * buf is an automatic for this function, so the
753 * compiler has complete control over its alignment;
754 * it is assumed this alignment is satisfactory for
755 * it to be casted to certain other struct pointers
756 * here, such as struct T_optmgmt_ack * .
758 uintptr_t buf[512 / sizeof (uintptr_t)];
759 int flags;
760 int i, j, getcode;
761 struct strbuf ctlbuf, databuf;
762 struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
763 struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
764 struct T_error_ack *tea = (struct T_error_ack *)buf;
765 struct opthdr *req;
766 mib_item_t *first_item = NULL;
767 mib_item_t *last_item = NULL;
768 mib_item_t *temp;
770 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
771 tor->OPT_offset = sizeof (struct T_optmgmt_req);
772 tor->OPT_length = sizeof (struct opthdr);
773 tor->MGMT_flags = T_CURRENT;
777 * Note: we use the special level value below so that IP will return
778 * us information concerning IRE_MARK_TESTHIDDEN routes.
780 req = (struct opthdr *)&tor[1];
781 req->level = EXPER_IP_AND_ALL_IRES;
782 req->name = 0;
783 req->len = 1;
785 ctlbuf.buf = (char *)buf;
786 ctlbuf.len = tor->OPT_length + tor->OPT_offset;
787 flags = 0;
788 if (putmsg(sd, &ctlbuf, NULL, flags) == -1) {
789 perror("mibget: putmsg(ctl) failed");
790 goto error_exit;
794 * Each reply consists of a ctl part for one fixed structure
795 * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
796 * containing an opthdr structure. level/name identify the entry,
797 * len is the size of the data part of the message.
799 req = (struct opthdr *)&toa[1];
800 ctlbuf.maxlen = sizeof (buf);
801 j = 1;
802 for (;;) {
803 flags = 0;
804 getcode = getmsg(sd, &ctlbuf, NULL, &flags);
805 if (getcode == -1) {
806 perror("mibget getmsg(ctl) failed");
807 if (Xflag) {
808 (void) fputs("# level name len\n",
809 stderr);
810 i = 0;
811 for (last_item = first_item; last_item;
812 last_item = last_item->next_item)
813 (void) printf("%d %4d %5d %d\n",
814 ++i,
815 last_item->group,
816 last_item->mib_id,
817 last_item->length);
819 goto error_exit;
821 if (getcode == 0 &&
822 ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
823 toa->PRIM_type == T_OPTMGMT_ACK &&
824 toa->MGMT_flags == T_SUCCESS &&
825 req->len == 0) {
826 if (Xflag)
827 (void) printf("mibget getmsg() %d returned "
828 "EOD (level %ld, name %ld)\n",
829 j, req->level, req->name);
830 return (first_item); /* this is EOD msg */
833 if (ctlbuf.len >= sizeof (struct T_error_ack) &&
834 tea->PRIM_type == T_ERROR_ACK) {
835 (void) fprintf(stderr,
836 "mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, "
837 "UNIX_error = 0x%lx\n",
838 j, tea->TLI_error, tea->UNIX_error);
840 errno = (tea->TLI_error == TSYSERR) ?
841 tea->UNIX_error : EPROTO;
842 goto error_exit;
845 if (getcode != MOREDATA ||
846 ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
847 toa->PRIM_type != T_OPTMGMT_ACK ||
848 toa->MGMT_flags != T_SUCCESS) {
849 (void) printf("mibget getmsg(ctl) %d returned %d, "
850 "ctlbuf.len = %d, PRIM_type = %ld\n",
851 j, getcode, ctlbuf.len, toa->PRIM_type);
853 if (toa->PRIM_type == T_OPTMGMT_ACK)
854 (void) printf("T_OPTMGMT_ACK: "
855 "MGMT_flags = 0x%lx, req->len = %ld\n",
856 toa->MGMT_flags, req->len);
857 errno = ENOMSG;
858 goto error_exit;
861 temp = (mib_item_t *)malloc(sizeof (mib_item_t));
862 if (temp == NULL) {
863 perror("mibget malloc failed");
864 goto error_exit;
866 if (last_item != NULL)
867 last_item->next_item = temp;
868 else
869 first_item = temp;
870 last_item = temp;
871 last_item->next_item = NULL;
872 last_item->group = req->level;
873 last_item->mib_id = req->name;
874 last_item->length = req->len;
875 last_item->valp = malloc((int)req->len);
876 if (last_item->valp == NULL)
877 goto error_exit;
878 if (Xflag)
879 (void) printf("msg %d: group = %4d mib_id = %5d"
880 "length = %d\n",
881 j, last_item->group, last_item->mib_id,
882 last_item->length);
884 databuf.maxlen = last_item->length;
885 databuf.buf = (char *)last_item->valp;
886 databuf.len = 0;
887 flags = 0;
888 getcode = getmsg(sd, NULL, &databuf, &flags);
889 if (getcode == -1) {
890 perror("mibget getmsg(data) failed");
891 goto error_exit;
892 } else if (getcode != 0) {
893 (void) printf("mibget getmsg(data) returned %d, "
894 "databuf.maxlen = %d, databuf.len = %d\n",
895 getcode, databuf.maxlen, databuf.len);
896 goto error_exit;
898 j++;
900 /* NOTREACHED */
902 error_exit:;
903 mibfree(first_item);
904 return (NULL);
908 * mibfree: frees a linked list of type (mib_item_t *)
909 * returned by mibget(); this is NOT THE SAME AS
910 * mib_item_destroy(), so should be used for objects
911 * returned by mibget() only
913 static void
914 mibfree(mib_item_t *firstitem)
916 mib_item_t *lastitem;
918 while (firstitem != NULL) {
919 lastitem = firstitem;
920 firstitem = firstitem->next_item;
921 free(lastitem->valp);
922 free(lastitem);
926 static int
927 mibopen(void)
929 int sd;
931 sd = open("/dev/arp", O_RDWR);
932 if (sd == -1) {
933 perror("arp open");
934 return (-1);
936 if (ioctl(sd, I_PUSH, "tcp") == -1) {
937 perror("tcp I_PUSH");
938 (void) close(sd);
939 return (-1);
941 if (ioctl(sd, I_PUSH, "udp") == -1) {
942 perror("udp I_PUSH");
943 (void) close(sd);
944 return (-1);
946 if (ioctl(sd, I_PUSH, "icmp") == -1) {
947 perror("icmp I_PUSH");
948 (void) close(sd);
949 return (-1);
951 return (sd);
955 * mib_item_dup: returns a clean mib_item_t * linked
956 * list, so that for every element item->mib_id is 0;
957 * to deallocate this linked list, use mib_item_destroy
959 static mib_item_t *
960 mib_item_dup(mib_item_t *item)
962 int c = 0;
963 mib_item_t *localp;
964 mib_item_t *tempp;
966 for (tempp = item; tempp; tempp = tempp->next_item)
967 if (tempp->mib_id == 0)
968 c++;
969 tempp = NULL;
971 localp = (mib_item_t *)malloc(c * sizeof (mib_item_t));
972 if (localp == NULL)
973 return (NULL);
974 c = 0;
975 for (; item; item = item->next_item) {
976 if (item->mib_id == 0) {
977 /* Replicate item in localp */
978 (localp[c]).next_item = NULL;
979 (localp[c]).group = item->group;
980 (localp[c]).mib_id = item->mib_id;
981 (localp[c]).length = item->length;
982 (localp[c]).valp = (uintptr_t *)malloc(
983 item->length);
984 if ((localp[c]).valp == NULL) {
985 mib_item_destroy(&localp);
986 return (NULL);
988 (void *) memcpy((localp[c]).valp,
989 item->valp,
990 item->length);
991 tempp = &(localp[c]);
992 if (c > 0)
993 (localp[c - 1]).next_item = tempp;
994 c++;
997 return (localp);
1001 * mib_item_diff: takes two (mib_item_t *) linked lists
1002 * item1 and item2 and computes the difference between
1003 * differentiable values in item2 against item1 for every
1004 * given member of item2; returns an mib_item_t * linked
1005 * list of diff's, or a copy of item2 if item1 is NULL;
1006 * will return NULL if system out of memory; works only
1007 * for item->mib_id == 0
1009 static mib_item_t *
1010 mib_item_diff(mib_item_t *item1, mib_item_t *item2)
1012 int nitems = 0; /* no. of items in item2 */
1013 mib_item_t *tempp2; /* walking copy of item2 */
1014 mib_item_t *tempp1; /* walking copy of item1 */
1015 mib_item_t *diffp;
1016 mib_item_t *diffptr; /* walking copy of diffp */
1017 mib_item_t *prevp = NULL;
1019 if (item1 == NULL) {
1020 diffp = mib_item_dup(item2);
1021 return (diffp);
1024 for (tempp2 = item2;
1025 tempp2;
1026 tempp2 = tempp2->next_item) {
1027 if (tempp2->mib_id == 0)
1028 switch (tempp2->group) {
1030 * upon adding a case here, the same
1031 * must also be added in the next
1032 * switch statement, alongwith
1033 * appropriate code
1035 case MIB2_IP:
1036 case MIB2_IP6:
1037 case EXPER_DVMRP:
1038 case EXPER_IGMP:
1039 case MIB2_ICMP:
1040 case MIB2_ICMP6:
1041 case MIB2_TCP:
1042 case MIB2_UDP:
1043 case MIB2_SCTP:
1044 case EXPER_RAWIP:
1045 nitems++;
1048 tempp2 = NULL;
1049 if (nitems == 0) {
1050 diffp = mib_item_dup(item2);
1051 return (diffp);
1054 diffp = (mib_item_t *)calloc(nitems, sizeof (mib_item_t));
1055 if (diffp == NULL)
1056 return (NULL);
1057 diffptr = diffp;
1058 /* 'for' loop 1: */
1059 for (tempp2 = item2; tempp2 != NULL; tempp2 = tempp2->next_item) {
1060 if (tempp2->mib_id != 0)
1061 continue; /* 'for' loop 1 */
1062 /* 'for' loop 2: */
1063 for (tempp1 = item1; tempp1 != NULL;
1064 tempp1 = tempp1->next_item) {
1065 if (!(tempp1->mib_id == 0 &&
1066 tempp1->group == tempp2->group &&
1067 tempp1->mib_id == tempp2->mib_id))
1068 continue; /* 'for' loop 2 */
1069 /* found comparable data sets */
1070 if (prevp != NULL)
1071 prevp->next_item = diffptr;
1072 switch (tempp2->group) {
1074 * Indenting note: Because of long variable names
1075 * in cases MIB2_IP6 and MIB2_ICMP6, their contents
1076 * have been indented by one tab space only
1078 case MIB2_IP: {
1079 mib2_ip_t *i2 = (mib2_ip_t *)tempp2->valp;
1080 mib2_ip_t *i1 = (mib2_ip_t *)tempp1->valp;
1081 mib2_ip_t *d;
1083 diffptr->group = tempp2->group;
1084 diffptr->mib_id = tempp2->mib_id;
1085 diffptr->length = tempp2->length;
1086 d = (mib2_ip_t *)calloc(tempp2->length, 1);
1087 if (d == NULL)
1088 goto mibdiff_out_of_memory;
1089 diffptr->valp = d;
1090 d->ipForwarding = i2->ipForwarding;
1091 d->ipDefaultTTL = i2->ipDefaultTTL;
1092 MDIFF(d, i2, i1, ipInReceives);
1093 MDIFF(d, i2, i1, ipInHdrErrors);
1094 MDIFF(d, i2, i1, ipInAddrErrors);
1095 MDIFF(d, i2, i1, ipInCksumErrs);
1096 MDIFF(d, i2, i1, ipForwDatagrams);
1097 MDIFF(d, i2, i1, ipForwProhibits);
1098 MDIFF(d, i2, i1, ipInUnknownProtos);
1099 MDIFF(d, i2, i1, ipInDiscards);
1100 MDIFF(d, i2, i1, ipInDelivers);
1101 MDIFF(d, i2, i1, ipOutRequests);
1102 MDIFF(d, i2, i1, ipOutDiscards);
1103 MDIFF(d, i2, i1, ipOutNoRoutes);
1104 MDIFF(d, i2, i1, ipReasmTimeout);
1105 MDIFF(d, i2, i1, ipReasmReqds);
1106 MDIFF(d, i2, i1, ipReasmOKs);
1107 MDIFF(d, i2, i1, ipReasmFails);
1108 MDIFF(d, i2, i1, ipReasmDuplicates);
1109 MDIFF(d, i2, i1, ipReasmPartDups);
1110 MDIFF(d, i2, i1, ipFragOKs);
1111 MDIFF(d, i2, i1, ipFragFails);
1112 MDIFF(d, i2, i1, ipFragCreates);
1113 MDIFF(d, i2, i1, ipRoutingDiscards);
1114 MDIFF(d, i2, i1, tcpInErrs);
1115 MDIFF(d, i2, i1, udpNoPorts);
1116 MDIFF(d, i2, i1, udpInCksumErrs);
1117 MDIFF(d, i2, i1, udpInOverflows);
1118 MDIFF(d, i2, i1, rawipInOverflows);
1119 MDIFF(d, i2, i1, ipsecInSucceeded);
1120 MDIFF(d, i2, i1, ipsecInFailed);
1121 MDIFF(d, i2, i1, ipInIPv6);
1122 MDIFF(d, i2, i1, ipOutIPv6);
1123 MDIFF(d, i2, i1, ipOutSwitchIPv6);
1124 prevp = diffptr++;
1125 break;
1127 case MIB2_IP6: {
1128 mib2_ipv6IfStatsEntry_t *i2;
1129 mib2_ipv6IfStatsEntry_t *i1;
1130 mib2_ipv6IfStatsEntry_t *d;
1132 i2 = (mib2_ipv6IfStatsEntry_t *)tempp2->valp;
1133 i1 = (mib2_ipv6IfStatsEntry_t *)tempp1->valp;
1134 diffptr->group = tempp2->group;
1135 diffptr->mib_id = tempp2->mib_id;
1136 diffptr->length = tempp2->length;
1137 d = (mib2_ipv6IfStatsEntry_t *)calloc(
1138 tempp2->length, 1);
1139 if (d == NULL)
1140 goto mibdiff_out_of_memory;
1141 diffptr->valp = d;
1142 d->ipv6Forwarding = i2->ipv6Forwarding;
1143 d->ipv6DefaultHopLimit =
1144 i2->ipv6DefaultHopLimit;
1146 MDIFF(d, i2, i1, ipv6InReceives);
1147 MDIFF(d, i2, i1, ipv6InHdrErrors);
1148 MDIFF(d, i2, i1, ipv6InTooBigErrors);
1149 MDIFF(d, i2, i1, ipv6InNoRoutes);
1150 MDIFF(d, i2, i1, ipv6InAddrErrors);
1151 MDIFF(d, i2, i1, ipv6InUnknownProtos);
1152 MDIFF(d, i2, i1, ipv6InTruncatedPkts);
1153 MDIFF(d, i2, i1, ipv6InDiscards);
1154 MDIFF(d, i2, i1, ipv6InDelivers);
1155 MDIFF(d, i2, i1, ipv6OutForwDatagrams);
1156 MDIFF(d, i2, i1, ipv6OutRequests);
1157 MDIFF(d, i2, i1, ipv6OutDiscards);
1158 MDIFF(d, i2, i1, ipv6OutNoRoutes);
1159 MDIFF(d, i2, i1, ipv6OutFragOKs);
1160 MDIFF(d, i2, i1, ipv6OutFragFails);
1161 MDIFF(d, i2, i1, ipv6OutFragCreates);
1162 MDIFF(d, i2, i1, ipv6ReasmReqds);
1163 MDIFF(d, i2, i1, ipv6ReasmOKs);
1164 MDIFF(d, i2, i1, ipv6ReasmFails);
1165 MDIFF(d, i2, i1, ipv6InMcastPkts);
1166 MDIFF(d, i2, i1, ipv6OutMcastPkts);
1167 MDIFF(d, i2, i1, ipv6ReasmDuplicates);
1168 MDIFF(d, i2, i1, ipv6ReasmPartDups);
1169 MDIFF(d, i2, i1, ipv6ForwProhibits);
1170 MDIFF(d, i2, i1, udpInCksumErrs);
1171 MDIFF(d, i2, i1, udpInOverflows);
1172 MDIFF(d, i2, i1, rawipInOverflows);
1173 MDIFF(d, i2, i1, ipv6InIPv4);
1174 MDIFF(d, i2, i1, ipv6OutIPv4);
1175 MDIFF(d, i2, i1, ipv6OutSwitchIPv4);
1176 prevp = diffptr++;
1177 break;
1179 case EXPER_DVMRP: {
1180 struct mrtstat *m2;
1181 struct mrtstat *m1;
1182 struct mrtstat *d;
1184 m2 = (struct mrtstat *)tempp2->valp;
1185 m1 = (struct mrtstat *)tempp1->valp;
1186 diffptr->group = tempp2->group;
1187 diffptr->mib_id = tempp2->mib_id;
1188 diffptr->length = tempp2->length;
1189 d = (struct mrtstat *)calloc(tempp2->length, 1);
1190 if (d == NULL)
1191 goto mibdiff_out_of_memory;
1192 diffptr->valp = d;
1193 MDIFF(d, m2, m1, mrts_mfc_hits);
1194 MDIFF(d, m2, m1, mrts_mfc_misses);
1195 MDIFF(d, m2, m1, mrts_fwd_in);
1196 MDIFF(d, m2, m1, mrts_fwd_out);
1197 d->mrts_upcalls = m2->mrts_upcalls;
1198 MDIFF(d, m2, m1, mrts_fwd_drop);
1199 MDIFF(d, m2, m1, mrts_bad_tunnel);
1200 MDIFF(d, m2, m1, mrts_cant_tunnel);
1201 MDIFF(d, m2, m1, mrts_wrong_if);
1202 MDIFF(d, m2, m1, mrts_upq_ovflw);
1203 MDIFF(d, m2, m1, mrts_cache_cleanups);
1204 MDIFF(d, m2, m1, mrts_drop_sel);
1205 MDIFF(d, m2, m1, mrts_q_overflow);
1206 MDIFF(d, m2, m1, mrts_pkt2large);
1207 MDIFF(d, m2, m1, mrts_pim_badversion);
1208 MDIFF(d, m2, m1, mrts_pim_rcv_badcsum);
1209 MDIFF(d, m2, m1, mrts_pim_badregisters);
1210 MDIFF(d, m2, m1, mrts_pim_regforwards);
1211 MDIFF(d, m2, m1, mrts_pim_regsend_drops);
1212 MDIFF(d, m2, m1, mrts_pim_malformed);
1213 MDIFF(d, m2, m1, mrts_pim_nomemory);
1214 prevp = diffptr++;
1215 break;
1217 case EXPER_IGMP: {
1218 struct igmpstat *i2;
1219 struct igmpstat *i1;
1220 struct igmpstat *d;
1222 i2 = (struct igmpstat *)tempp2->valp;
1223 i1 = (struct igmpstat *)tempp1->valp;
1224 diffptr->group = tempp2->group;
1225 diffptr->mib_id = tempp2->mib_id;
1226 diffptr->length = tempp2->length;
1227 d = (struct igmpstat *)calloc(
1228 tempp2->length, 1);
1229 if (d == NULL)
1230 goto mibdiff_out_of_memory;
1231 diffptr->valp = d;
1232 MDIFF(d, i2, i1, igps_rcv_total);
1233 MDIFF(d, i2, i1, igps_rcv_tooshort);
1234 MDIFF(d, i2, i1, igps_rcv_badsum);
1235 MDIFF(d, i2, i1, igps_rcv_queries);
1236 MDIFF(d, i2, i1, igps_rcv_badqueries);
1237 MDIFF(d, i2, i1, igps_rcv_reports);
1238 MDIFF(d, i2, i1, igps_rcv_badreports);
1239 MDIFF(d, i2, i1, igps_rcv_ourreports);
1240 MDIFF(d, i2, i1, igps_snd_reports);
1241 prevp = diffptr++;
1242 break;
1244 case MIB2_ICMP: {
1245 mib2_icmp_t *i2;
1246 mib2_icmp_t *i1;
1247 mib2_icmp_t *d;
1249 i2 = (mib2_icmp_t *)tempp2->valp;
1250 i1 = (mib2_icmp_t *)tempp1->valp;
1251 diffptr->group = tempp2->group;
1252 diffptr->mib_id = tempp2->mib_id;
1253 diffptr->length = tempp2->length;
1254 d = (mib2_icmp_t *)calloc(tempp2->length, 1);
1255 if (d == NULL)
1256 goto mibdiff_out_of_memory;
1257 diffptr->valp = d;
1258 MDIFF(d, i2, i1, icmpInMsgs);
1259 MDIFF(d, i2, i1, icmpInErrors);
1260 MDIFF(d, i2, i1, icmpInCksumErrs);
1261 MDIFF(d, i2, i1, icmpInUnknowns);
1262 MDIFF(d, i2, i1, icmpInDestUnreachs);
1263 MDIFF(d, i2, i1, icmpInTimeExcds);
1264 MDIFF(d, i2, i1, icmpInParmProbs);
1265 MDIFF(d, i2, i1, icmpInSrcQuenchs);
1266 MDIFF(d, i2, i1, icmpInRedirects);
1267 MDIFF(d, i2, i1, icmpInBadRedirects);
1268 MDIFF(d, i2, i1, icmpInEchos);
1269 MDIFF(d, i2, i1, icmpInEchoReps);
1270 MDIFF(d, i2, i1, icmpInTimestamps);
1271 MDIFF(d, i2, i1, icmpInAddrMasks);
1272 MDIFF(d, i2, i1, icmpInAddrMaskReps);
1273 MDIFF(d, i2, i1, icmpInFragNeeded);
1274 MDIFF(d, i2, i1, icmpOutMsgs);
1275 MDIFF(d, i2, i1, icmpOutDrops);
1276 MDIFF(d, i2, i1, icmpOutErrors);
1277 MDIFF(d, i2, i1, icmpOutDestUnreachs);
1278 MDIFF(d, i2, i1, icmpOutTimeExcds);
1279 MDIFF(d, i2, i1, icmpOutParmProbs);
1280 MDIFF(d, i2, i1, icmpOutSrcQuenchs);
1281 MDIFF(d, i2, i1, icmpOutRedirects);
1282 MDIFF(d, i2, i1, icmpOutEchos);
1283 MDIFF(d, i2, i1, icmpOutEchoReps);
1284 MDIFF(d, i2, i1, icmpOutTimestamps);
1285 MDIFF(d, i2, i1, icmpOutTimestampReps);
1286 MDIFF(d, i2, i1, icmpOutAddrMasks);
1287 MDIFF(d, i2, i1, icmpOutAddrMaskReps);
1288 MDIFF(d, i2, i1, icmpOutFragNeeded);
1289 MDIFF(d, i2, i1, icmpInOverflows);
1290 prevp = diffptr++;
1291 break;
1293 case MIB2_ICMP6: {
1294 mib2_ipv6IfIcmpEntry_t *i2;
1295 mib2_ipv6IfIcmpEntry_t *i1;
1296 mib2_ipv6IfIcmpEntry_t *d;
1298 i2 = (mib2_ipv6IfIcmpEntry_t *)tempp2->valp;
1299 i1 = (mib2_ipv6IfIcmpEntry_t *)tempp1->valp;
1300 diffptr->group = tempp2->group;
1301 diffptr->mib_id = tempp2->mib_id;
1302 diffptr->length = tempp2->length;
1303 d = (mib2_ipv6IfIcmpEntry_t *)calloc(tempp2->length, 1);
1304 if (d == NULL)
1305 goto mibdiff_out_of_memory;
1306 diffptr->valp = d;
1307 MDIFF(d, i2, i1, ipv6IfIcmpInMsgs);
1308 MDIFF(d, i2, i1, ipv6IfIcmpInErrors);
1309 MDIFF(d, i2, i1, ipv6IfIcmpInDestUnreachs);
1310 MDIFF(d, i2, i1, ipv6IfIcmpInAdminProhibs);
1311 MDIFF(d, i2, i1, ipv6IfIcmpInTimeExcds);
1312 MDIFF(d, i2, i1, ipv6IfIcmpInParmProblems);
1313 MDIFF(d, i2, i1, ipv6IfIcmpInPktTooBigs);
1314 MDIFF(d, i2, i1, ipv6IfIcmpInEchos);
1315 MDIFF(d, i2, i1, ipv6IfIcmpInEchoReplies);
1316 MDIFF(d, i2, i1, ipv6IfIcmpInRouterSolicits);
1317 MDIFF(d, i2, i1, ipv6IfIcmpInRouterAdvertisements);
1318 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborSolicits);
1319 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborAdvertisements);
1320 MDIFF(d, i2, i1, ipv6IfIcmpInRedirects);
1321 MDIFF(d, i2, i1, ipv6IfIcmpInBadRedirects);
1322 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembQueries);
1323 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembResponses);
1324 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembReductions);
1325 MDIFF(d, i2, i1, ipv6IfIcmpInOverflows);
1326 MDIFF(d, i2, i1, ipv6IfIcmpOutMsgs);
1327 MDIFF(d, i2, i1, ipv6IfIcmpOutErrors);
1328 MDIFF(d, i2, i1, ipv6IfIcmpOutDestUnreachs);
1329 MDIFF(d, i2, i1, ipv6IfIcmpOutAdminProhibs);
1330 MDIFF(d, i2, i1, ipv6IfIcmpOutTimeExcds);
1331 MDIFF(d, i2, i1, ipv6IfIcmpOutParmProblems);
1332 MDIFF(d, i2, i1, ipv6IfIcmpOutPktTooBigs);
1333 MDIFF(d, i2, i1, ipv6IfIcmpOutEchos);
1334 MDIFF(d, i2, i1, ipv6IfIcmpOutEchoReplies);
1335 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterSolicits);
1336 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterAdvertisements);
1337 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborSolicits);
1338 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborAdvertisements);
1339 MDIFF(d, i2, i1, ipv6IfIcmpOutRedirects);
1340 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembQueries);
1341 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembResponses);
1342 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembReductions);
1343 prevp = diffptr++;
1344 break;
1346 case MIB2_TCP: {
1347 mib2_tcp_t *t2;
1348 mib2_tcp_t *t1;
1349 mib2_tcp_t *d;
1351 t2 = (mib2_tcp_t *)tempp2->valp;
1352 t1 = (mib2_tcp_t *)tempp1->valp;
1353 diffptr->group = tempp2->group;
1354 diffptr->mib_id = tempp2->mib_id;
1355 diffptr->length = tempp2->length;
1356 d = (mib2_tcp_t *)calloc(tempp2->length, 1);
1357 if (d == NULL)
1358 goto mibdiff_out_of_memory;
1359 diffptr->valp = d;
1360 d->tcpRtoMin = t2->tcpRtoMin;
1361 d->tcpRtoMax = t2->tcpRtoMax;
1362 d->tcpMaxConn = t2->tcpMaxConn;
1363 MDIFF(d, t2, t1, tcpActiveOpens);
1364 MDIFF(d, t2, t1, tcpPassiveOpens);
1365 MDIFF(d, t2, t1, tcpAttemptFails);
1366 MDIFF(d, t2, t1, tcpEstabResets);
1367 d->tcpCurrEstab = t2->tcpCurrEstab;
1368 MDIFF(d, t2, t1, tcpHCOutSegs);
1369 MDIFF(d, t2, t1, tcpOutDataSegs);
1370 MDIFF(d, t2, t1, tcpOutDataBytes);
1371 MDIFF(d, t2, t1, tcpRetransSegs);
1372 MDIFF(d, t2, t1, tcpRetransBytes);
1373 MDIFF(d, t2, t1, tcpOutAck);
1374 MDIFF(d, t2, t1, tcpOutAckDelayed);
1375 MDIFF(d, t2, t1, tcpOutUrg);
1376 MDIFF(d, t2, t1, tcpOutWinUpdate);
1377 MDIFF(d, t2, t1, tcpOutWinProbe);
1378 MDIFF(d, t2, t1, tcpOutControl);
1379 MDIFF(d, t2, t1, tcpOutRsts);
1380 MDIFF(d, t2, t1, tcpOutFastRetrans);
1381 MDIFF(d, t2, t1, tcpHCInSegs);
1382 MDIFF(d, t2, t1, tcpInAckSegs);
1383 MDIFF(d, t2, t1, tcpInAckBytes);
1384 MDIFF(d, t2, t1, tcpInDupAck);
1385 MDIFF(d, t2, t1, tcpInAckUnsent);
1386 MDIFF(d, t2, t1, tcpInDataInorderSegs);
1387 MDIFF(d, t2, t1, tcpInDataInorderBytes);
1388 MDIFF(d, t2, t1, tcpInDataUnorderSegs);
1389 MDIFF(d, t2, t1, tcpInDataUnorderBytes);
1390 MDIFF(d, t2, t1, tcpInDataDupSegs);
1391 MDIFF(d, t2, t1, tcpInDataDupBytes);
1392 MDIFF(d, t2, t1, tcpInDataPartDupSegs);
1393 MDIFF(d, t2, t1, tcpInDataPartDupBytes);
1394 MDIFF(d, t2, t1, tcpInDataPastWinSegs);
1395 MDIFF(d, t2, t1, tcpInDataPastWinBytes);
1396 MDIFF(d, t2, t1, tcpInWinProbe);
1397 MDIFF(d, t2, t1, tcpInWinUpdate);
1398 MDIFF(d, t2, t1, tcpInClosed);
1399 MDIFF(d, t2, t1, tcpRttNoUpdate);
1400 MDIFF(d, t2, t1, tcpRttUpdate);
1401 MDIFF(d, t2, t1, tcpTimRetrans);
1402 MDIFF(d, t2, t1, tcpTimRetransDrop);
1403 MDIFF(d, t2, t1, tcpTimKeepalive);
1404 MDIFF(d, t2, t1, tcpTimKeepaliveProbe);
1405 MDIFF(d, t2, t1, tcpTimKeepaliveDrop);
1406 MDIFF(d, t2, t1, tcpListenDrop);
1407 MDIFF(d, t2, t1, tcpListenDropQ0);
1408 MDIFF(d, t2, t1, tcpHalfOpenDrop);
1409 MDIFF(d, t2, t1, tcpOutSackRetransSegs);
1410 prevp = diffptr++;
1411 break;
1413 case MIB2_UDP: {
1414 mib2_udp_t *u2;
1415 mib2_udp_t *u1;
1416 mib2_udp_t *d;
1418 u2 = (mib2_udp_t *)tempp2->valp;
1419 u1 = (mib2_udp_t *)tempp1->valp;
1420 diffptr->group = tempp2->group;
1421 diffptr->mib_id = tempp2->mib_id;
1422 diffptr->length = tempp2->length;
1423 d = (mib2_udp_t *)calloc(tempp2->length, 1);
1424 if (d == NULL)
1425 goto mibdiff_out_of_memory;
1426 diffptr->valp = d;
1427 MDIFF(d, u2, u1, udpHCInDatagrams);
1428 MDIFF(d, u2, u1, udpInErrors);
1429 MDIFF(d, u2, u1, udpHCOutDatagrams);
1430 MDIFF(d, u2, u1, udpOutErrors);
1431 prevp = diffptr++;
1432 break;
1434 case MIB2_SCTP: {
1435 mib2_sctp_t *s2;
1436 mib2_sctp_t *s1;
1437 mib2_sctp_t *d;
1439 s2 = (mib2_sctp_t *)tempp2->valp;
1440 s1 = (mib2_sctp_t *)tempp1->valp;
1441 diffptr->group = tempp2->group;
1442 diffptr->mib_id = tempp2->mib_id;
1443 diffptr->length = tempp2->length;
1444 d = (mib2_sctp_t *)calloc(tempp2->length, 1);
1445 if (d == NULL)
1446 goto mibdiff_out_of_memory;
1447 diffptr->valp = d;
1448 d->sctpRtoAlgorithm = s2->sctpRtoAlgorithm;
1449 d->sctpRtoMin = s2->sctpRtoMin;
1450 d->sctpRtoMax = s2->sctpRtoMax;
1451 d->sctpRtoInitial = s2->sctpRtoInitial;
1452 d->sctpMaxAssocs = s2->sctpMaxAssocs;
1453 d->sctpValCookieLife = s2->sctpValCookieLife;
1454 d->sctpMaxInitRetr = s2->sctpMaxInitRetr;
1455 d->sctpCurrEstab = s2->sctpCurrEstab;
1456 MDIFF(d, s2, s1, sctpActiveEstab);
1457 MDIFF(d, s2, s1, sctpPassiveEstab);
1458 MDIFF(d, s2, s1, sctpAborted);
1459 MDIFF(d, s2, s1, sctpShutdowns);
1460 MDIFF(d, s2, s1, sctpOutOfBlue);
1461 MDIFF(d, s2, s1, sctpChecksumError);
1462 MDIFF(d, s2, s1, sctpOutCtrlChunks);
1463 MDIFF(d, s2, s1, sctpOutOrderChunks);
1464 MDIFF(d, s2, s1, sctpOutUnorderChunks);
1465 MDIFF(d, s2, s1, sctpRetransChunks);
1466 MDIFF(d, s2, s1, sctpOutAck);
1467 MDIFF(d, s2, s1, sctpOutAckDelayed);
1468 MDIFF(d, s2, s1, sctpOutWinUpdate);
1469 MDIFF(d, s2, s1, sctpOutFastRetrans);
1470 MDIFF(d, s2, s1, sctpOutWinProbe);
1471 MDIFF(d, s2, s1, sctpInCtrlChunks);
1472 MDIFF(d, s2, s1, sctpInOrderChunks);
1473 MDIFF(d, s2, s1, sctpInUnorderChunks);
1474 MDIFF(d, s2, s1, sctpInAck);
1475 MDIFF(d, s2, s1, sctpInDupAck);
1476 MDIFF(d, s2, s1, sctpInAckUnsent);
1477 MDIFF(d, s2, s1, sctpFragUsrMsgs);
1478 MDIFF(d, s2, s1, sctpReasmUsrMsgs);
1479 MDIFF(d, s2, s1, sctpOutSCTPPkts);
1480 MDIFF(d, s2, s1, sctpInSCTPPkts);
1481 MDIFF(d, s2, s1, sctpInInvalidCookie);
1482 MDIFF(d, s2, s1, sctpTimRetrans);
1483 MDIFF(d, s2, s1, sctpTimRetransDrop);
1484 MDIFF(d, s2, s1, sctpTimHeartBeatProbe);
1485 MDIFF(d, s2, s1, sctpTimHeartBeatDrop);
1486 MDIFF(d, s2, s1, sctpListenDrop);
1487 MDIFF(d, s2, s1, sctpInClosed);
1488 prevp = diffptr++;
1489 break;
1491 case EXPER_RAWIP: {
1492 mib2_rawip_t *r2;
1493 mib2_rawip_t *r1;
1494 mib2_rawip_t *d;
1496 r2 = (mib2_rawip_t *)tempp2->valp;
1497 r1 = (mib2_rawip_t *)tempp1->valp;
1498 diffptr->group = tempp2->group;
1499 diffptr->mib_id = tempp2->mib_id;
1500 diffptr->length = tempp2->length;
1501 d = (mib2_rawip_t *)calloc(tempp2->length, 1);
1502 if (d == NULL)
1503 goto mibdiff_out_of_memory;
1504 diffptr->valp = d;
1505 MDIFF(d, r2, r1, rawipInDatagrams);
1506 MDIFF(d, r2, r1, rawipInErrors);
1507 MDIFF(d, r2, r1, rawipInCksumErrs);
1508 MDIFF(d, r2, r1, rawipOutDatagrams);
1509 MDIFF(d, r2, r1, rawipOutErrors);
1510 prevp = diffptr++;
1511 break;
1514 * there are more "group" types but they aren't
1515 * required for the -s and -Ms options
1518 } /* 'for' loop 2 ends */
1519 tempp1 = NULL;
1520 } /* 'for' loop 1 ends */
1521 tempp2 = NULL;
1522 diffptr--;
1523 diffptr->next_item = NULL;
1524 return (diffp);
1526 mibdiff_out_of_memory:;
1527 mib_item_destroy(&diffp);
1528 return (NULL);
1532 * mib_item_destroy: cleans up a mib_item_t *
1533 * that was created by calling mib_item_dup or
1534 * mib_item_diff
1536 static void
1537 mib_item_destroy(mib_item_t **itemp)
1539 int nitems = 0;
1540 int c = 0;
1541 mib_item_t *tempp;
1543 if (itemp == NULL || *itemp == NULL)
1544 return;
1546 for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1547 if (tempp->mib_id == 0)
1548 nitems++;
1549 else
1550 return; /* cannot destroy! */
1552 if (nitems == 0)
1553 return; /* cannot destroy! */
1555 for (c = nitems - 1; c >= 0; c--) {
1556 free((itemp[0][c]).valp);
1558 free(*itemp);
1560 *itemp = NULL;
1563 /* Compare two Octet_ts. Return B_TRUE if they match, B_FALSE if not. */
1564 static boolean_t
1565 octetstrmatch(const Octet_t *a, const Octet_t *b)
1567 if (a == NULL || b == NULL)
1568 return (B_FALSE);
1570 if (a->o_length != b->o_length)
1571 return (B_FALSE);
1573 return (memcmp(a->o_bytes, b->o_bytes, a->o_length) == 0);
1576 /* If octetstr() changes make an appropriate change to STR_EXPAND */
1577 static char *
1578 octetstr(const Octet_t *op, int code, char *dst, uint_t dstlen)
1580 int i;
1581 char *cp;
1583 cp = dst;
1584 if (op) {
1585 for (i = 0; i < op->o_length; i++) {
1586 switch (code) {
1587 case 'd':
1588 if (cp - dst + 4 > dstlen) {
1589 *cp = '\0';
1590 return (dst);
1592 (void) snprintf(cp, 5, "%d.",
1593 0xff & op->o_bytes[i]);
1594 cp = strchr(cp, '\0');
1595 break;
1596 case 'a':
1597 if (cp - dst + 1 > dstlen) {
1598 *cp = '\0';
1599 return (dst);
1601 *cp++ = op->o_bytes[i];
1602 break;
1603 case 'h':
1604 default:
1605 if (cp - dst + 3 > dstlen) {
1606 *cp = '\0';
1607 return (dst);
1609 (void) snprintf(cp, 4, "%02x:",
1610 0xff & op->o_bytes[i]);
1611 cp += 3;
1612 break;
1616 if (code != 'a' && cp != dst)
1617 cp--;
1618 *cp = '\0';
1619 return (dst);
1622 static const char *
1623 mitcp_state(int state)
1625 static char tcpsbuf[50];
1626 const char *cp;
1628 switch (state) {
1629 case TCPS_CLOSED:
1630 cp = "CLOSED";
1631 break;
1632 case TCPS_IDLE:
1633 cp = "IDLE";
1634 break;
1635 case TCPS_BOUND:
1636 cp = "BOUND";
1637 break;
1638 case TCPS_LISTEN:
1639 cp = "LISTEN";
1640 break;
1641 case TCPS_SYN_SENT:
1642 cp = "SYN_SENT";
1643 break;
1644 case TCPS_SYN_RCVD:
1645 cp = "SYN_RCVD";
1646 break;
1647 case TCPS_ESTABLISHED:
1648 cp = "ESTABLISHED";
1649 break;
1650 case TCPS_CLOSE_WAIT:
1651 cp = "CLOSE_WAIT";
1652 break;
1653 case TCPS_FIN_WAIT_1:
1654 cp = "FIN_WAIT_1";
1655 break;
1656 case TCPS_CLOSING:
1657 cp = "CLOSING";
1658 break;
1659 case TCPS_LAST_ACK:
1660 cp = "LAST_ACK";
1661 break;
1662 case TCPS_FIN_WAIT_2:
1663 cp = "FIN_WAIT_2";
1664 break;
1665 case TCPS_TIME_WAIT:
1666 cp = "TIME_WAIT";
1667 break;
1668 default:
1669 (void) snprintf(tcpsbuf, sizeof (tcpsbuf),
1670 "UnknownState(%d)", state);
1671 cp = tcpsbuf;
1672 break;
1675 return (cp);
1678 static const char *
1679 miudp_state(int state)
1681 static char udpsbuf[50];
1682 const char *cp;
1684 switch (state) {
1685 case MIB2_UDP_unbound:
1686 cp = "Unbound";
1687 break;
1688 case MIB2_UDP_idle:
1689 cp = "Idle";
1690 break;
1691 case MIB2_UDP_connected:
1692 cp = "Connected";
1693 break;
1694 default:
1695 (void) snprintf(udpsbuf, sizeof (udpsbuf),
1696 "Unknown State(%d)", state);
1697 cp = udpsbuf;
1698 break;
1701 return (cp);
1704 static int odd;
1706 static void
1707 prval_init(void)
1709 odd = 0;
1712 static void
1713 prval(char *str, Counter val)
1715 (void) printf("\t%-20s=%6u", str, val);
1716 if (odd++ & 1)
1717 (void) putchar('\n');
1720 static void
1721 prval64(char *str, Counter64 val)
1723 (void) printf("\t%-20s=%6llu", str, val);
1724 if (odd++ & 1)
1725 (void) putchar('\n');
1728 static void
1729 pr_int_val(char *str, int val)
1731 (void) printf("\t%-20s=%6d", str, val);
1732 if (odd++ & 1)
1733 (void) putchar('\n');
1736 static void
1737 pr_sctp_rtoalgo(char *str, int val)
1739 (void) printf("\t%-20s=", str);
1740 switch (val) {
1741 case MIB2_SCTP_RTOALGO_OTHER:
1742 (void) printf("%6.6s", "other");
1743 break;
1745 case MIB2_SCTP_RTOALGO_VANJ:
1746 (void) printf("%6.6s", "vanj");
1747 break;
1749 default:
1750 (void) printf("%6d", val);
1751 break;
1753 if (odd++ & 1)
1754 (void) putchar('\n');
1757 static void
1758 prval_end(void)
1760 if (odd++ & 1)
1761 (void) putchar('\n');
1764 /* Extract constant sizes */
1765 static void
1766 mib_get_constants(mib_item_t *item)
1768 /* 'for' loop 1: */
1769 for (; item; item = item->next_item) {
1770 if (item->mib_id != 0)
1771 continue; /* 'for' loop 1 */
1773 switch (item->group) {
1774 case MIB2_IP: {
1775 mib2_ip_t *ip = (mib2_ip_t *)item->valp;
1777 ipAddrEntrySize = ip->ipAddrEntrySize;
1778 ipRouteEntrySize = ip->ipRouteEntrySize;
1779 ipNetToMediaEntrySize = ip->ipNetToMediaEntrySize;
1780 ipMemberEntrySize = ip->ipMemberEntrySize;
1781 ipGroupSourceEntrySize = ip->ipGroupSourceEntrySize;
1782 ipDestEntrySize = ip->ipDestEntrySize;
1783 assert(IS_P2ALIGNED(ipAddrEntrySize,
1784 sizeof (mib2_ipAddrEntry_t *)));
1785 assert(IS_P2ALIGNED(ipRouteEntrySize,
1786 sizeof (mib2_ipRouteEntry_t *)));
1787 assert(IS_P2ALIGNED(ipNetToMediaEntrySize,
1788 sizeof (mib2_ipNetToMediaEntry_t *)));
1789 assert(IS_P2ALIGNED(ipMemberEntrySize,
1790 sizeof (ip_member_t *)));
1791 assert(IS_P2ALIGNED(ipGroupSourceEntrySize,
1792 sizeof (ip_grpsrc_t *)));
1793 break;
1795 case EXPER_DVMRP: {
1796 struct mrtstat *mrts = (struct mrtstat *)item->valp;
1798 vifctlSize = mrts->mrts_vifctlSize;
1799 mfcctlSize = mrts->mrts_mfcctlSize;
1800 assert(IS_P2ALIGNED(vifctlSize,
1801 sizeof (struct vifclt *)));
1802 assert(IS_P2ALIGNED(mfcctlSize,
1803 sizeof (struct mfcctl *)));
1804 break;
1806 case MIB2_IP6: {
1807 mib2_ipv6IfStatsEntry_t *ip6;
1808 /* Just use the first entry */
1810 ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp;
1811 ipv6IfStatsEntrySize = ip6->ipv6IfStatsEntrySize;
1812 ipv6AddrEntrySize = ip6->ipv6AddrEntrySize;
1813 ipv6RouteEntrySize = ip6->ipv6RouteEntrySize;
1814 ipv6NetToMediaEntrySize = ip6->ipv6NetToMediaEntrySize;
1815 ipv6MemberEntrySize = ip6->ipv6MemberEntrySize;
1816 ipv6GroupSourceEntrySize =
1817 ip6->ipv6GroupSourceEntrySize;
1818 assert(IS_P2ALIGNED(ipv6IfStatsEntrySize,
1819 sizeof (mib2_ipv6IfStatsEntry_t *)));
1820 assert(IS_P2ALIGNED(ipv6AddrEntrySize,
1821 sizeof (mib2_ipv6AddrEntry_t *)));
1822 assert(IS_P2ALIGNED(ipv6RouteEntrySize,
1823 sizeof (mib2_ipv6RouteEntry_t *)));
1824 assert(IS_P2ALIGNED(ipv6NetToMediaEntrySize,
1825 sizeof (mib2_ipv6NetToMediaEntry_t *)));
1826 assert(IS_P2ALIGNED(ipv6MemberEntrySize,
1827 sizeof (ipv6_member_t *)));
1828 assert(IS_P2ALIGNED(ipv6GroupSourceEntrySize,
1829 sizeof (ipv6_grpsrc_t *)));
1830 break;
1832 case MIB2_ICMP6: {
1833 mib2_ipv6IfIcmpEntry_t *icmp6;
1834 /* Just use the first entry */
1836 icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp;
1837 ipv6IfIcmpEntrySize = icmp6->ipv6IfIcmpEntrySize;
1838 assert(IS_P2ALIGNED(ipv6IfIcmpEntrySize,
1839 sizeof (mib2_ipv6IfIcmpEntry_t *)));
1840 break;
1842 case MIB2_TCP: {
1843 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp;
1845 tcpConnEntrySize = tcp->tcpConnTableSize;
1846 tcp6ConnEntrySize = tcp->tcp6ConnTableSize;
1847 assert(IS_P2ALIGNED(tcpConnEntrySize,
1848 sizeof (mib2_tcpConnEntry_t *)));
1849 assert(IS_P2ALIGNED(tcp6ConnEntrySize,
1850 sizeof (mib2_tcp6ConnEntry_t *)));
1851 break;
1853 case MIB2_UDP: {
1854 mib2_udp_t *udp = (mib2_udp_t *)item->valp;
1856 udpEntrySize = udp->udpEntrySize;
1857 udp6EntrySize = udp->udp6EntrySize;
1858 assert(IS_P2ALIGNED(udpEntrySize,
1859 sizeof (mib2_udpEntry_t *)));
1860 assert(IS_P2ALIGNED(udp6EntrySize,
1861 sizeof (mib2_udp6Entry_t *)));
1862 break;
1864 case MIB2_SCTP: {
1865 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp;
1867 sctpEntrySize = sctp->sctpEntrySize;
1868 sctpLocalEntrySize = sctp->sctpLocalEntrySize;
1869 sctpRemoteEntrySize = sctp->sctpRemoteEntrySize;
1870 break;
1873 } /* 'for' loop 1 ends */
1875 if (Xflag) {
1876 (void) puts("mib_get_constants:");
1877 (void) printf("\tipv6IfStatsEntrySize %d\n",
1878 ipv6IfStatsEntrySize);
1879 (void) printf("\tipAddrEntrySize %d\n", ipAddrEntrySize);
1880 (void) printf("\tipRouteEntrySize %d\n", ipRouteEntrySize);
1881 (void) printf("\tipNetToMediaEntrySize %d\n",
1882 ipNetToMediaEntrySize);
1883 (void) printf("\tipMemberEntrySize %d\n", ipMemberEntrySize);
1884 (void) printf("\tvifctlSize %d\n", vifctlSize);
1885 (void) printf("\tmfcctlSize %d\n", mfcctlSize);
1887 (void) printf("\tipv6AddrEntrySize %d\n", ipv6AddrEntrySize);
1888 (void) printf("\tipv6RouteEntrySize %d\n", ipv6RouteEntrySize);
1889 (void) printf("\tipv6NetToMediaEntrySize %d\n",
1890 ipv6NetToMediaEntrySize);
1891 (void) printf("\tipv6MemberEntrySize %d\n",
1892 ipv6MemberEntrySize);
1893 (void) printf("\tipv6IfIcmpEntrySize %d\n",
1894 ipv6IfIcmpEntrySize);
1895 (void) printf("\tipDestEntrySize %d\n", ipDestEntrySize);
1896 (void) printf("\ttcpConnEntrySize %d\n", tcpConnEntrySize);
1897 (void) printf("\ttcp6ConnEntrySize %d\n", tcp6ConnEntrySize);
1898 (void) printf("\tudpEntrySize %d\n", udpEntrySize);
1899 (void) printf("\tudp6EntrySize %d\n", udp6EntrySize);
1900 (void) printf("\tsctpEntrySize %d\n", sctpEntrySize);
1901 (void) printf("\tsctpLocalEntrySize %d\n", sctpLocalEntrySize);
1902 (void) printf("\tsctpRemoteEntrySize %d\n",
1903 sctpRemoteEntrySize);
1908 /* ----------------------------- STAT_REPORT ------------------------------- */
1910 static void
1911 stat_report(mib_item_t *item)
1913 int jtemp = 0;
1914 char ifname[LIFNAMSIZ + 1];
1916 /* 'for' loop 1: */
1917 for (; item; item = item->next_item) {
1918 if (Xflag) {
1919 (void) printf("\n--- Entry %d ---\n", ++jtemp);
1920 (void) printf("Group = %d, mib_id = %d, "
1921 "length = %d, valp = 0x%p\n",
1922 item->group, item->mib_id,
1923 item->length, item->valp);
1925 if (item->mib_id != 0)
1926 continue; /* 'for' loop 1 */
1928 switch (item->group) {
1929 case MIB2_IP: {
1930 mib2_ip_t *ip = (mib2_ip_t *)item->valp;
1932 if (protocol_selected(IPPROTO_IP) &&
1933 family_selected(AF_INET)) {
1934 (void) fputs(v4compat ? "\nIP" : "\nIPv4",
1935 stdout);
1936 print_ip_stats(ip);
1938 break;
1940 case MIB2_ICMP: {
1941 mib2_icmp_t *icmp =
1942 (mib2_icmp_t *)item->valp;
1944 if (protocol_selected(IPPROTO_ICMP) &&
1945 family_selected(AF_INET)) {
1946 (void) fputs(v4compat ? "\nICMP" : "\nICMPv4",
1947 stdout);
1948 print_icmp_stats(icmp);
1950 break;
1952 case MIB2_IP6: {
1953 mib2_ipv6IfStatsEntry_t *ip6;
1954 mib2_ipv6IfStatsEntry_t sum6;
1956 if (!(protocol_selected(IPPROTO_IPV6)) ||
1957 !(family_selected(AF_INET6)))
1958 break;
1959 bzero(&sum6, sizeof (sum6));
1960 /* 'for' loop 2a: */
1961 for (ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp;
1962 (char *)ip6 < (char *)item->valp + item->length;
1963 /* LINTED: (note 1) */
1964 ip6 = (mib2_ipv6IfStatsEntry_t *)((char *)ip6 +
1965 ipv6IfStatsEntrySize)) {
1966 if (ip6->ipv6IfIndex == 0) {
1968 * The "unknown interface" ip6
1969 * mib. Just add to the sum.
1971 sum_ip6_stats(ip6, &sum6);
1972 continue; /* 'for' loop 2a */
1974 if (Aflag) {
1975 (void) printf("\nIPv6 for %s\n",
1976 ifindex2str(ip6->ipv6IfIndex,
1977 ifname));
1978 print_ip6_stats(ip6);
1980 sum_ip6_stats(ip6, &sum6);
1981 } /* 'for' loop 2a ends */
1982 (void) fputs("\nIPv6", stdout);
1983 print_ip6_stats(&sum6);
1984 break;
1986 case MIB2_ICMP6: {
1987 mib2_ipv6IfIcmpEntry_t *icmp6;
1988 mib2_ipv6IfIcmpEntry_t sum6;
1990 if (!(protocol_selected(IPPROTO_ICMPV6)) ||
1991 !(family_selected(AF_INET6)))
1992 break;
1993 bzero(&sum6, sizeof (sum6));
1994 /* 'for' loop 2b: */
1995 for (icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp;
1996 (char *)icmp6 < (char *)item->valp + item->length;
1997 icmp6 = (void *)((char *)icmp6 +
1998 ipv6IfIcmpEntrySize)) {
1999 if (icmp6->ipv6IfIcmpIfIndex == 0) {
2001 * The "unknown interface" icmp6
2002 * mib. Just add to the sum.
2004 sum_icmp6_stats(icmp6, &sum6);
2005 continue; /* 'for' loop 2b: */
2007 if (Aflag) {
2008 (void) printf("\nICMPv6 for %s\n",
2009 ifindex2str(
2010 icmp6->ipv6IfIcmpIfIndex, ifname));
2011 print_icmp6_stats(icmp6);
2013 sum_icmp6_stats(icmp6, &sum6);
2014 } /* 'for' loop 2b ends */
2015 (void) fputs("\nICMPv6", stdout);
2016 print_icmp6_stats(&sum6);
2017 break;
2019 case MIB2_TCP: {
2020 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp;
2022 if (protocol_selected(IPPROTO_TCP) &&
2023 (family_selected(AF_INET) ||
2024 family_selected(AF_INET6))) {
2025 (void) fputs("\nTCP", stdout);
2026 print_tcp_stats(tcp);
2028 break;
2030 case MIB2_UDP: {
2031 mib2_udp_t *udp = (mib2_udp_t *)item->valp;
2033 if (protocol_selected(IPPROTO_UDP) &&
2034 (family_selected(AF_INET) ||
2035 family_selected(AF_INET6))) {
2036 (void) fputs("\nUDP", stdout);
2037 print_udp_stats(udp);
2039 break;
2041 case MIB2_SCTP: {
2042 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp;
2044 if (protocol_selected(IPPROTO_SCTP) &&
2045 (family_selected(AF_INET) ||
2046 family_selected(AF_INET6))) {
2047 (void) fputs("\nSCTP", stdout);
2048 print_sctp_stats(sctp);
2050 break;
2052 case EXPER_RAWIP: {
2053 mib2_rawip_t *rawip =
2054 (mib2_rawip_t *)item->valp;
2056 if (protocol_selected(IPPROTO_RAW) &&
2057 (family_selected(AF_INET) ||
2058 family_selected(AF_INET6))) {
2059 (void) fputs("\nRAWIP", stdout);
2060 print_rawip_stats(rawip);
2062 break;
2064 case EXPER_IGMP: {
2065 struct igmpstat *igps =
2066 (struct igmpstat *)item->valp;
2068 if (protocol_selected(IPPROTO_IGMP) &&
2069 (family_selected(AF_INET))) {
2070 (void) fputs("\nIGMP:\n", stdout);
2071 print_igmp_stats(igps);
2073 break;
2076 } /* 'for' loop 1 ends */
2077 (void) putchar('\n');
2078 (void) fflush(stdout);
2081 static void
2082 print_ip_stats(mib2_ip_t *ip)
2084 prval_init();
2085 pr_int_val("ipForwarding", ip->ipForwarding);
2086 pr_int_val("ipDefaultTTL", ip->ipDefaultTTL);
2087 prval("ipInReceives", ip->ipInReceives);
2088 prval("ipInHdrErrors", ip->ipInHdrErrors);
2089 prval("ipInAddrErrors", ip->ipInAddrErrors);
2090 prval("ipInCksumErrs", ip->ipInCksumErrs);
2091 prval("ipForwDatagrams", ip->ipForwDatagrams);
2092 prval("ipForwProhibits", ip->ipForwProhibits);
2093 prval("ipInUnknownProtos", ip->ipInUnknownProtos);
2094 prval("ipInDiscards", ip->ipInDiscards);
2095 prval("ipInDelivers", ip->ipInDelivers);
2096 prval("ipOutRequests", ip->ipOutRequests);
2097 prval("ipOutDiscards", ip->ipOutDiscards);
2098 prval("ipOutNoRoutes", ip->ipOutNoRoutes);
2099 pr_int_val("ipReasmTimeout", ip->ipReasmTimeout);
2100 prval("ipReasmReqds", ip->ipReasmReqds);
2101 prval("ipReasmOKs", ip->ipReasmOKs);
2102 prval("ipReasmFails", ip->ipReasmFails);
2103 prval("ipReasmDuplicates", ip->ipReasmDuplicates);
2104 prval("ipReasmPartDups", ip->ipReasmPartDups);
2105 prval("ipFragOKs", ip->ipFragOKs);
2106 prval("ipFragFails", ip->ipFragFails);
2107 prval("ipFragCreates", ip->ipFragCreates);
2108 prval("ipRoutingDiscards", ip->ipRoutingDiscards);
2110 prval("tcpInErrs", ip->tcpInErrs);
2111 prval("udpNoPorts", ip->udpNoPorts);
2112 prval("udpInCksumErrs", ip->udpInCksumErrs);
2113 prval("udpInOverflows", ip->udpInOverflows);
2114 prval("rawipInOverflows", ip->rawipInOverflows);
2115 prval("ipsecInSucceeded", ip->ipsecInSucceeded);
2116 prval("ipsecInFailed", ip->ipsecInFailed);
2117 prval("ipInIPv6", ip->ipInIPv6);
2118 prval("ipOutIPv6", ip->ipOutIPv6);
2119 prval("ipOutSwitchIPv6", ip->ipOutSwitchIPv6);
2120 prval_end();
2123 static void
2124 print_icmp_stats(mib2_icmp_t *icmp)
2126 prval_init();
2127 prval("icmpInMsgs", icmp->icmpInMsgs);
2128 prval("icmpInErrors", icmp->icmpInErrors);
2129 prval("icmpInCksumErrs", icmp->icmpInCksumErrs);
2130 prval("icmpInUnknowns", icmp->icmpInUnknowns);
2131 prval("icmpInDestUnreachs", icmp->icmpInDestUnreachs);
2132 prval("icmpInTimeExcds", icmp->icmpInTimeExcds);
2133 prval("icmpInParmProbs", icmp->icmpInParmProbs);
2134 prval("icmpInSrcQuenchs", icmp->icmpInSrcQuenchs);
2135 prval("icmpInRedirects", icmp->icmpInRedirects);
2136 prval("icmpInBadRedirects", icmp->icmpInBadRedirects);
2137 prval("icmpInEchos", icmp->icmpInEchos);
2138 prval("icmpInEchoReps", icmp->icmpInEchoReps);
2139 prval("icmpInTimestamps", icmp->icmpInTimestamps);
2140 prval("icmpInTimestampReps", icmp->icmpInTimestampReps);
2141 prval("icmpInAddrMasks", icmp->icmpInAddrMasks);
2142 prval("icmpInAddrMaskReps", icmp->icmpInAddrMaskReps);
2143 prval("icmpInFragNeeded", icmp->icmpInFragNeeded);
2144 prval("icmpOutMsgs", icmp->icmpOutMsgs);
2145 prval("icmpOutDrops", icmp->icmpOutDrops);
2146 prval("icmpOutErrors", icmp->icmpOutErrors);
2147 prval("icmpOutDestUnreachs", icmp->icmpOutDestUnreachs);
2148 prval("icmpOutTimeExcds", icmp->icmpOutTimeExcds);
2149 prval("icmpOutParmProbs", icmp->icmpOutParmProbs);
2150 prval("icmpOutSrcQuenchs", icmp->icmpOutSrcQuenchs);
2151 prval("icmpOutRedirects", icmp->icmpOutRedirects);
2152 prval("icmpOutEchos", icmp->icmpOutEchos);
2153 prval("icmpOutEchoReps", icmp->icmpOutEchoReps);
2154 prval("icmpOutTimestamps", icmp->icmpOutTimestamps);
2155 prval("icmpOutTimestampReps", icmp->icmpOutTimestampReps);
2156 prval("icmpOutAddrMasks", icmp->icmpOutAddrMasks);
2157 prval("icmpOutAddrMaskReps", icmp->icmpOutAddrMaskReps);
2158 prval("icmpOutFragNeeded", icmp->icmpOutFragNeeded);
2159 prval("icmpInOverflows", icmp->icmpInOverflows);
2160 prval_end();
2163 static void
2164 print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6)
2166 prval_init();
2167 prval("ipv6Forwarding", ip6->ipv6Forwarding);
2168 prval("ipv6DefaultHopLimit", ip6->ipv6DefaultHopLimit);
2170 prval("ipv6InReceives", ip6->ipv6InReceives);
2171 prval("ipv6InHdrErrors", ip6->ipv6InHdrErrors);
2172 prval("ipv6InTooBigErrors", ip6->ipv6InTooBigErrors);
2173 prval("ipv6InNoRoutes", ip6->ipv6InNoRoutes);
2174 prval("ipv6InAddrErrors", ip6->ipv6InAddrErrors);
2175 prval("ipv6InUnknownProtos", ip6->ipv6InUnknownProtos);
2176 prval("ipv6InTruncatedPkts", ip6->ipv6InTruncatedPkts);
2177 prval("ipv6InDiscards", ip6->ipv6InDiscards);
2178 prval("ipv6InDelivers", ip6->ipv6InDelivers);
2179 prval("ipv6OutForwDatagrams", ip6->ipv6OutForwDatagrams);
2180 prval("ipv6OutRequests", ip6->ipv6OutRequests);
2181 prval("ipv6OutDiscards", ip6->ipv6OutDiscards);
2182 prval("ipv6OutNoRoutes", ip6->ipv6OutNoRoutes);
2183 prval("ipv6OutFragOKs", ip6->ipv6OutFragOKs);
2184 prval("ipv6OutFragFails", ip6->ipv6OutFragFails);
2185 prval("ipv6OutFragCreates", ip6->ipv6OutFragCreates);
2186 prval("ipv6ReasmReqds", ip6->ipv6ReasmReqds);
2187 prval("ipv6ReasmOKs", ip6->ipv6ReasmOKs);
2188 prval("ipv6ReasmFails", ip6->ipv6ReasmFails);
2189 prval("ipv6InMcastPkts", ip6->ipv6InMcastPkts);
2190 prval("ipv6OutMcastPkts", ip6->ipv6OutMcastPkts);
2191 prval("ipv6ReasmDuplicates", ip6->ipv6ReasmDuplicates);
2192 prval("ipv6ReasmPartDups", ip6->ipv6ReasmPartDups);
2193 prval("ipv6ForwProhibits", ip6->ipv6ForwProhibits);
2194 prval("udpInCksumErrs", ip6->udpInCksumErrs);
2195 prval("udpInOverflows", ip6->udpInOverflows);
2196 prval("rawipInOverflows", ip6->rawipInOverflows);
2197 prval("ipv6InIPv4", ip6->ipv6InIPv4);
2198 prval("ipv6OutIPv4", ip6->ipv6OutIPv4);
2199 prval("ipv6OutSwitchIPv4", ip6->ipv6OutSwitchIPv4);
2200 prval_end();
2203 static void
2204 print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6)
2206 prval_init();
2207 prval("icmp6InMsgs", icmp6->ipv6IfIcmpInMsgs);
2208 prval("icmp6InErrors", icmp6->ipv6IfIcmpInErrors);
2209 prval("icmp6InDestUnreachs", icmp6->ipv6IfIcmpInDestUnreachs);
2210 prval("icmp6InAdminProhibs", icmp6->ipv6IfIcmpInAdminProhibs);
2211 prval("icmp6InTimeExcds", icmp6->ipv6IfIcmpInTimeExcds);
2212 prval("icmp6InParmProblems", icmp6->ipv6IfIcmpInParmProblems);
2213 prval("icmp6InPktTooBigs", icmp6->ipv6IfIcmpInPktTooBigs);
2214 prval("icmp6InEchos", icmp6->ipv6IfIcmpInEchos);
2215 prval("icmp6InEchoReplies", icmp6->ipv6IfIcmpInEchoReplies);
2216 prval("icmp6InRouterSols", icmp6->ipv6IfIcmpInRouterSolicits);
2217 prval("icmp6InRouterAds",
2218 icmp6->ipv6IfIcmpInRouterAdvertisements);
2219 prval("icmp6InNeighborSols", icmp6->ipv6IfIcmpInNeighborSolicits);
2220 prval("icmp6InNeighborAds",
2221 icmp6->ipv6IfIcmpInNeighborAdvertisements);
2222 prval("icmp6InRedirects", icmp6->ipv6IfIcmpInRedirects);
2223 prval("icmp6InBadRedirects", icmp6->ipv6IfIcmpInBadRedirects);
2224 prval("icmp6InGroupQueries", icmp6->ipv6IfIcmpInGroupMembQueries);
2225 prval("icmp6InGroupResps", icmp6->ipv6IfIcmpInGroupMembResponses);
2226 prval("icmp6InGroupReds", icmp6->ipv6IfIcmpInGroupMembReductions);
2227 prval("icmp6InOverflows", icmp6->ipv6IfIcmpInOverflows);
2228 prval_end();
2229 prval_init();
2230 prval("icmp6OutMsgs", icmp6->ipv6IfIcmpOutMsgs);
2231 prval("icmp6OutErrors", icmp6->ipv6IfIcmpOutErrors);
2232 prval("icmp6OutDestUnreachs", icmp6->ipv6IfIcmpOutDestUnreachs);
2233 prval("icmp6OutAdminProhibs", icmp6->ipv6IfIcmpOutAdminProhibs);
2234 prval("icmp6OutTimeExcds", icmp6->ipv6IfIcmpOutTimeExcds);
2235 prval("icmp6OutParmProblems", icmp6->ipv6IfIcmpOutParmProblems);
2236 prval("icmp6OutPktTooBigs", icmp6->ipv6IfIcmpOutPktTooBigs);
2237 prval("icmp6OutEchos", icmp6->ipv6IfIcmpOutEchos);
2238 prval("icmp6OutEchoReplies", icmp6->ipv6IfIcmpOutEchoReplies);
2239 prval("icmp6OutRouterSols", icmp6->ipv6IfIcmpOutRouterSolicits);
2240 prval("icmp6OutRouterAds",
2241 icmp6->ipv6IfIcmpOutRouterAdvertisements);
2242 prval("icmp6OutNeighborSols", icmp6->ipv6IfIcmpOutNeighborSolicits);
2243 prval("icmp6OutNeighborAds",
2244 icmp6->ipv6IfIcmpOutNeighborAdvertisements);
2245 prval("icmp6OutRedirects", icmp6->ipv6IfIcmpOutRedirects);
2246 prval("icmp6OutGroupQueries", icmp6->ipv6IfIcmpOutGroupMembQueries);
2247 prval("icmp6OutGroupResps",
2248 icmp6->ipv6IfIcmpOutGroupMembResponses);
2249 prval("icmp6OutGroupReds",
2250 icmp6->ipv6IfIcmpOutGroupMembReductions);
2251 prval_end();
2254 static void
2255 print_sctp_stats(mib2_sctp_t *sctp)
2257 prval_init();
2258 pr_sctp_rtoalgo("sctpRtoAlgorithm", sctp->sctpRtoAlgorithm);
2259 prval("sctpRtoMin", sctp->sctpRtoMin);
2260 prval("sctpRtoMax", sctp->sctpRtoMax);
2261 prval("sctpRtoInitial", sctp->sctpRtoInitial);
2262 pr_int_val("sctpMaxAssocs", sctp->sctpMaxAssocs);
2263 prval("sctpValCookieLife", sctp->sctpValCookieLife);
2264 prval("sctpMaxInitRetr", sctp->sctpMaxInitRetr);
2265 prval("sctpCurrEstab", sctp->sctpCurrEstab);
2266 prval("sctpActiveEstab", sctp->sctpActiveEstab);
2267 prval("sctpPassiveEstab", sctp->sctpPassiveEstab);
2268 prval("sctpAborted", sctp->sctpAborted);
2269 prval("sctpShutdowns", sctp->sctpShutdowns);
2270 prval("sctpOutOfBlue", sctp->sctpOutOfBlue);
2271 prval("sctpChecksumError", sctp->sctpChecksumError);
2272 prval64("sctpOutCtrlChunks", sctp->sctpOutCtrlChunks);
2273 prval64("sctpOutOrderChunks", sctp->sctpOutOrderChunks);
2274 prval64("sctpOutUnorderChunks", sctp->sctpOutUnorderChunks);
2275 prval64("sctpRetransChunks", sctp->sctpRetransChunks);
2276 prval("sctpOutAck", sctp->sctpOutAck);
2277 prval("sctpOutAckDelayed", sctp->sctpOutAckDelayed);
2278 prval("sctpOutWinUpdate", sctp->sctpOutWinUpdate);
2279 prval("sctpOutFastRetrans", sctp->sctpOutFastRetrans);
2280 prval("sctpOutWinProbe", sctp->sctpOutWinProbe);
2281 prval64("sctpInCtrlChunks", sctp->sctpInCtrlChunks);
2282 prval64("sctpInOrderChunks", sctp->sctpInOrderChunks);
2283 prval64("sctpInUnorderChunks", sctp->sctpInUnorderChunks);
2284 prval("sctpInAck", sctp->sctpInAck);
2285 prval("sctpInDupAck", sctp->sctpInDupAck);
2286 prval("sctpInAckUnsent", sctp->sctpInAckUnsent);
2287 prval64("sctpFragUsrMsgs", sctp->sctpFragUsrMsgs);
2288 prval64("sctpReasmUsrMsgs", sctp->sctpReasmUsrMsgs);
2289 prval64("sctpOutSCTPPkts", sctp->sctpOutSCTPPkts);
2290 prval64("sctpInSCTPPkts", sctp->sctpInSCTPPkts);
2291 prval("sctpInInvalidCookie", sctp->sctpInInvalidCookie);
2292 prval("sctpTimRetrans", sctp->sctpTimRetrans);
2293 prval("sctpTimRetransDrop", sctp->sctpTimRetransDrop);
2294 prval("sctpTimHearBeatProbe", sctp->sctpTimHeartBeatProbe);
2295 prval("sctpTimHearBeatDrop", sctp->sctpTimHeartBeatDrop);
2296 prval("sctpListenDrop", sctp->sctpListenDrop);
2297 prval("sctpInClosed", sctp->sctpInClosed);
2298 prval_end();
2301 static void
2302 print_tcp_stats(mib2_tcp_t *tcp)
2304 prval_init();
2305 pr_int_val("tcpRtoAlgorithm", tcp->tcpRtoAlgorithm);
2306 pr_int_val("tcpRtoMin", tcp->tcpRtoMin);
2307 pr_int_val("tcpRtoMax", tcp->tcpRtoMax);
2308 pr_int_val("tcpMaxConn", tcp->tcpMaxConn);
2309 prval("tcpActiveOpens", tcp->tcpActiveOpens);
2310 prval("tcpPassiveOpens", tcp->tcpPassiveOpens);
2311 prval("tcpAttemptFails", tcp->tcpAttemptFails);
2312 prval("tcpEstabResets", tcp->tcpEstabResets);
2313 prval("tcpCurrEstab", tcp->tcpCurrEstab);
2314 prval64("tcpOutSegs", tcp->tcpHCOutSegs);
2315 prval("tcpOutDataSegs", tcp->tcpOutDataSegs);
2316 prval("tcpOutDataBytes", tcp->tcpOutDataBytes);
2317 prval("tcpRetransSegs", tcp->tcpRetransSegs);
2318 prval("tcpRetransBytes", tcp->tcpRetransBytes);
2319 prval("tcpOutAck", tcp->tcpOutAck);
2320 prval("tcpOutAckDelayed", tcp->tcpOutAckDelayed);
2321 prval("tcpOutUrg", tcp->tcpOutUrg);
2322 prval("tcpOutWinUpdate", tcp->tcpOutWinUpdate);
2323 prval("tcpOutWinProbe", tcp->tcpOutWinProbe);
2324 prval("tcpOutControl", tcp->tcpOutControl);
2325 prval("tcpOutRsts", tcp->tcpOutRsts);
2326 prval("tcpOutFastRetrans", tcp->tcpOutFastRetrans);
2327 prval64("tcpInSegs", tcp->tcpHCInSegs);
2328 prval_end();
2329 prval("tcpInAckSegs", tcp->tcpInAckSegs);
2330 prval("tcpInAckBytes", tcp->tcpInAckBytes);
2331 prval("tcpInDupAck", tcp->tcpInDupAck);
2332 prval("tcpInAckUnsent", tcp->tcpInAckUnsent);
2333 prval("tcpInInorderSegs", tcp->tcpInDataInorderSegs);
2334 prval("tcpInInorderBytes", tcp->tcpInDataInorderBytes);
2335 prval("tcpInUnorderSegs", tcp->tcpInDataUnorderSegs);
2336 prval("tcpInUnorderBytes", tcp->tcpInDataUnorderBytes);
2337 prval("tcpInDupSegs", tcp->tcpInDataDupSegs);
2338 prval("tcpInDupBytes", tcp->tcpInDataDupBytes);
2339 prval("tcpInPartDupSegs", tcp->tcpInDataPartDupSegs);
2340 prval("tcpInPartDupBytes", tcp->tcpInDataPartDupBytes);
2341 prval("tcpInPastWinSegs", tcp->tcpInDataPastWinSegs);
2342 prval("tcpInPastWinBytes", tcp->tcpInDataPastWinBytes);
2343 prval("tcpInWinProbe", tcp->tcpInWinProbe);
2344 prval("tcpInWinUpdate", tcp->tcpInWinUpdate);
2345 prval("tcpInClosed", tcp->tcpInClosed);
2346 prval("tcpRttNoUpdate", tcp->tcpRttNoUpdate);
2347 prval("tcpRttUpdate", tcp->tcpRttUpdate);
2348 prval("tcpTimRetrans", tcp->tcpTimRetrans);
2349 prval("tcpTimRetransDrop", tcp->tcpTimRetransDrop);
2350 prval("tcpTimKeepalive", tcp->tcpTimKeepalive);
2351 prval("tcpTimKeepaliveProbe", tcp->tcpTimKeepaliveProbe);
2352 prval("tcpTimKeepaliveDrop", tcp->tcpTimKeepaliveDrop);
2353 prval("tcpListenDrop", tcp->tcpListenDrop);
2354 prval("tcpListenDropQ0", tcp->tcpListenDropQ0);
2355 prval("tcpHalfOpenDrop", tcp->tcpHalfOpenDrop);
2356 prval("tcpOutSackRetrans", tcp->tcpOutSackRetransSegs);
2357 prval_end();
2361 static void
2362 print_udp_stats(mib2_udp_t *udp)
2364 prval_init();
2365 prval64("udpInDatagrams", udp->udpHCInDatagrams);
2366 prval("udpInErrors", udp->udpInErrors);
2367 prval64("udpOutDatagrams", udp->udpHCOutDatagrams);
2368 prval("udpOutErrors", udp->udpOutErrors);
2369 prval_end();
2372 static void
2373 print_rawip_stats(mib2_rawip_t *rawip)
2375 prval_init();
2376 prval("rawipInDatagrams", rawip->rawipInDatagrams);
2377 prval("rawipInErrors", rawip->rawipInErrors);
2378 prval("rawipInCksumErrs", rawip->rawipInCksumErrs);
2379 prval("rawipOutDatagrams", rawip->rawipOutDatagrams);
2380 prval("rawipOutErrors", rawip->rawipOutErrors);
2381 prval_end();
2384 void
2385 print_igmp_stats(struct igmpstat *igps)
2387 (void) printf(" %10u message%s received\n",
2388 igps->igps_rcv_total, PLURAL(igps->igps_rcv_total));
2389 (void) printf(" %10u message%s received with too few bytes\n",
2390 igps->igps_rcv_tooshort, PLURAL(igps->igps_rcv_tooshort));
2391 (void) printf(" %10u message%s received with bad checksum\n",
2392 igps->igps_rcv_badsum, PLURAL(igps->igps_rcv_badsum));
2393 (void) printf(" %10u membership quer%s received\n",
2394 igps->igps_rcv_queries, PLURALY(igps->igps_rcv_queries));
2395 (void) printf(" %10u membership quer%s received with invalid "
2396 "field(s)\n",
2397 igps->igps_rcv_badqueries, PLURALY(igps->igps_rcv_badqueries));
2398 (void) printf(" %10u membership report%s received\n",
2399 igps->igps_rcv_reports, PLURAL(igps->igps_rcv_reports));
2400 (void) printf(" %10u membership report%s received with invalid "
2401 "field(s)\n",
2402 igps->igps_rcv_badreports, PLURAL(igps->igps_rcv_badreports));
2403 (void) printf(" %10u membership report%s received for groups to "
2404 "which we belong\n",
2405 igps->igps_rcv_ourreports, PLURAL(igps->igps_rcv_ourreports));
2406 (void) printf(" %10u membership report%s sent\n",
2407 igps->igps_snd_reports, PLURAL(igps->igps_snd_reports));
2410 static void
2411 print_mrt_stats(struct mrtstat *mrts)
2413 (void) puts("DVMRP multicast routing:");
2414 (void) printf(" %10u hit%s - kernel forwarding cache hits\n",
2415 mrts->mrts_mfc_hits, PLURAL(mrts->mrts_mfc_hits));
2416 (void) printf(" %10u miss%s - kernel forwarding cache misses\n",
2417 mrts->mrts_mfc_misses, PLURALES(mrts->mrts_mfc_misses));
2418 (void) printf(" %10u packet%s potentially forwarded\n",
2419 mrts->mrts_fwd_in, PLURAL(mrts->mrts_fwd_in));
2420 (void) printf(" %10u packet%s actually sent out\n",
2421 mrts->mrts_fwd_out, PLURAL(mrts->mrts_fwd_out));
2422 (void) printf(" %10u upcall%s - upcalls made to mrouted\n",
2423 mrts->mrts_upcalls, PLURAL(mrts->mrts_upcalls));
2424 (void) printf(" %10u packet%s not sent out due to lack of resources\n",
2425 mrts->mrts_fwd_drop, PLURAL(mrts->mrts_fwd_drop));
2426 (void) printf(" %10u datagram%s with malformed tunnel options\n",
2427 mrts->mrts_bad_tunnel, PLURAL(mrts->mrts_bad_tunnel));
2428 (void) printf(" %10u datagram%s with no room for tunnel options\n",
2429 mrts->mrts_cant_tunnel, PLURAL(mrts->mrts_cant_tunnel));
2430 (void) printf(" %10u datagram%s arrived on wrong interface\n",
2431 mrts->mrts_wrong_if, PLURAL(mrts->mrts_wrong_if));
2432 (void) printf(" %10u datagram%s dropped due to upcall Q overflow\n",
2433 mrts->mrts_upq_ovflw, PLURAL(mrts->mrts_upq_ovflw));
2434 (void) printf(" %10u datagram%s cleaned up by the cache\n",
2435 mrts->mrts_cache_cleanups, PLURAL(mrts->mrts_cache_cleanups));
2436 (void) printf(" %10u datagram%s dropped selectively by ratelimiter\n",
2437 mrts->mrts_drop_sel, PLURAL(mrts->mrts_drop_sel));
2438 (void) printf(" %10u datagram%s dropped - bucket Q overflow\n",
2439 mrts->mrts_q_overflow, PLURAL(mrts->mrts_q_overflow));
2440 (void) printf(" %10u datagram%s dropped - larger than bkt size\n",
2441 mrts->mrts_pkt2large, PLURAL(mrts->mrts_pkt2large));
2442 (void) printf("\nPIM multicast routing:\n");
2443 (void) printf(" %10u datagram%s dropped - bad version number\n",
2444 mrts->mrts_pim_badversion, PLURAL(mrts->mrts_pim_badversion));
2445 (void) printf(" %10u datagram%s dropped - bad checksum\n",
2446 mrts->mrts_pim_rcv_badcsum, PLURAL(mrts->mrts_pim_rcv_badcsum));
2447 (void) printf(" %10u datagram%s dropped - bad register packets\n",
2448 mrts->mrts_pim_badregisters, PLURAL(mrts->mrts_pim_badregisters));
2449 (void) printf(
2450 " %10u datagram%s potentially forwarded - register packets\n",
2451 mrts->mrts_pim_regforwards, PLURAL(mrts->mrts_pim_regforwards));
2452 (void) printf(" %10u datagram%s dropped - register send drops\n",
2453 mrts->mrts_pim_regsend_drops, PLURAL(mrts->mrts_pim_regsend_drops));
2454 (void) printf(" %10u datagram%s dropped - packet malformed\n",
2455 mrts->mrts_pim_malformed, PLURAL(mrts->mrts_pim_malformed));
2456 (void) printf(" %10u datagram%s dropped - no memory to forward\n",
2457 mrts->mrts_pim_nomemory, PLURAL(mrts->mrts_pim_nomemory));
2460 static void
2461 sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6, mib2_ipv6IfStatsEntry_t *sum6)
2463 /* First few are not additive */
2464 sum6->ipv6Forwarding = ip6->ipv6Forwarding;
2465 sum6->ipv6DefaultHopLimit = ip6->ipv6DefaultHopLimit;
2467 sum6->ipv6InReceives += ip6->ipv6InReceives;
2468 sum6->ipv6InHdrErrors += ip6->ipv6InHdrErrors;
2469 sum6->ipv6InTooBigErrors += ip6->ipv6InTooBigErrors;
2470 sum6->ipv6InNoRoutes += ip6->ipv6InNoRoutes;
2471 sum6->ipv6InAddrErrors += ip6->ipv6InAddrErrors;
2472 sum6->ipv6InUnknownProtos += ip6->ipv6InUnknownProtos;
2473 sum6->ipv6InTruncatedPkts += ip6->ipv6InTruncatedPkts;
2474 sum6->ipv6InDiscards += ip6->ipv6InDiscards;
2475 sum6->ipv6InDelivers += ip6->ipv6InDelivers;
2476 sum6->ipv6OutForwDatagrams += ip6->ipv6OutForwDatagrams;
2477 sum6->ipv6OutRequests += ip6->ipv6OutRequests;
2478 sum6->ipv6OutDiscards += ip6->ipv6OutDiscards;
2479 sum6->ipv6OutFragOKs += ip6->ipv6OutFragOKs;
2480 sum6->ipv6OutFragFails += ip6->ipv6OutFragFails;
2481 sum6->ipv6OutFragCreates += ip6->ipv6OutFragCreates;
2482 sum6->ipv6ReasmReqds += ip6->ipv6ReasmReqds;
2483 sum6->ipv6ReasmOKs += ip6->ipv6ReasmOKs;
2484 sum6->ipv6ReasmFails += ip6->ipv6ReasmFails;
2485 sum6->ipv6InMcastPkts += ip6->ipv6InMcastPkts;
2486 sum6->ipv6OutMcastPkts += ip6->ipv6OutMcastPkts;
2487 sum6->ipv6OutNoRoutes += ip6->ipv6OutNoRoutes;
2488 sum6->ipv6ReasmDuplicates += ip6->ipv6ReasmDuplicates;
2489 sum6->ipv6ReasmPartDups += ip6->ipv6ReasmPartDups;
2490 sum6->ipv6ForwProhibits += ip6->ipv6ForwProhibits;
2491 sum6->udpInCksumErrs += ip6->udpInCksumErrs;
2492 sum6->udpInOverflows += ip6->udpInOverflows;
2493 sum6->rawipInOverflows += ip6->rawipInOverflows;
2496 static void
2497 sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6, mib2_ipv6IfIcmpEntry_t *sum6)
2499 sum6->ipv6IfIcmpInMsgs += icmp6->ipv6IfIcmpInMsgs;
2500 sum6->ipv6IfIcmpInErrors += icmp6->ipv6IfIcmpInErrors;
2501 sum6->ipv6IfIcmpInDestUnreachs += icmp6->ipv6IfIcmpInDestUnreachs;
2502 sum6->ipv6IfIcmpInAdminProhibs += icmp6->ipv6IfIcmpInAdminProhibs;
2503 sum6->ipv6IfIcmpInTimeExcds += icmp6->ipv6IfIcmpInTimeExcds;
2504 sum6->ipv6IfIcmpInParmProblems += icmp6->ipv6IfIcmpInParmProblems;
2505 sum6->ipv6IfIcmpInPktTooBigs += icmp6->ipv6IfIcmpInPktTooBigs;
2506 sum6->ipv6IfIcmpInEchos += icmp6->ipv6IfIcmpInEchos;
2507 sum6->ipv6IfIcmpInEchoReplies += icmp6->ipv6IfIcmpInEchoReplies;
2508 sum6->ipv6IfIcmpInRouterSolicits += icmp6->ipv6IfIcmpInRouterSolicits;
2509 sum6->ipv6IfIcmpInRouterAdvertisements +=
2510 icmp6->ipv6IfIcmpInRouterAdvertisements;
2511 sum6->ipv6IfIcmpInNeighborSolicits +=
2512 icmp6->ipv6IfIcmpInNeighborSolicits;
2513 sum6->ipv6IfIcmpInNeighborAdvertisements +=
2514 icmp6->ipv6IfIcmpInNeighborAdvertisements;
2515 sum6->ipv6IfIcmpInRedirects += icmp6->ipv6IfIcmpInRedirects;
2516 sum6->ipv6IfIcmpInGroupMembQueries +=
2517 icmp6->ipv6IfIcmpInGroupMembQueries;
2518 sum6->ipv6IfIcmpInGroupMembResponses +=
2519 icmp6->ipv6IfIcmpInGroupMembResponses;
2520 sum6->ipv6IfIcmpInGroupMembReductions +=
2521 icmp6->ipv6IfIcmpInGroupMembReductions;
2522 sum6->ipv6IfIcmpOutMsgs += icmp6->ipv6IfIcmpOutMsgs;
2523 sum6->ipv6IfIcmpOutErrors += icmp6->ipv6IfIcmpOutErrors;
2524 sum6->ipv6IfIcmpOutDestUnreachs += icmp6->ipv6IfIcmpOutDestUnreachs;
2525 sum6->ipv6IfIcmpOutAdminProhibs += icmp6->ipv6IfIcmpOutAdminProhibs;
2526 sum6->ipv6IfIcmpOutTimeExcds += icmp6->ipv6IfIcmpOutTimeExcds;
2527 sum6->ipv6IfIcmpOutParmProblems += icmp6->ipv6IfIcmpOutParmProblems;
2528 sum6->ipv6IfIcmpOutPktTooBigs += icmp6->ipv6IfIcmpOutPktTooBigs;
2529 sum6->ipv6IfIcmpOutEchos += icmp6->ipv6IfIcmpOutEchos;
2530 sum6->ipv6IfIcmpOutEchoReplies += icmp6->ipv6IfIcmpOutEchoReplies;
2531 sum6->ipv6IfIcmpOutRouterSolicits +=
2532 icmp6->ipv6IfIcmpOutRouterSolicits;
2533 sum6->ipv6IfIcmpOutRouterAdvertisements +=
2534 icmp6->ipv6IfIcmpOutRouterAdvertisements;
2535 sum6->ipv6IfIcmpOutNeighborSolicits +=
2536 icmp6->ipv6IfIcmpOutNeighborSolicits;
2537 sum6->ipv6IfIcmpOutNeighborAdvertisements +=
2538 icmp6->ipv6IfIcmpOutNeighborAdvertisements;
2539 sum6->ipv6IfIcmpOutRedirects += icmp6->ipv6IfIcmpOutRedirects;
2540 sum6->ipv6IfIcmpOutGroupMembQueries +=
2541 icmp6->ipv6IfIcmpOutGroupMembQueries;
2542 sum6->ipv6IfIcmpOutGroupMembResponses +=
2543 icmp6->ipv6IfIcmpOutGroupMembResponses;
2544 sum6->ipv6IfIcmpOutGroupMembReductions +=
2545 icmp6->ipv6IfIcmpOutGroupMembReductions;
2546 sum6->ipv6IfIcmpInOverflows += icmp6->ipv6IfIcmpInOverflows;
2549 /* ----------------------------- MRT_STAT_REPORT --------------------------- */
2551 static void
2552 mrt_stat_report(mib_item_t *curritem)
2554 int jtemp = 0;
2555 mib_item_t *tempitem;
2557 if (!(family_selected(AF_INET)))
2558 return;
2560 (void) putchar('\n');
2561 /* 'for' loop 1: */
2562 for (tempitem = curritem;
2563 tempitem;
2564 tempitem = tempitem->next_item) {
2565 if (Xflag) {
2566 (void) printf("\n--- Entry %d ---\n", ++jtemp);
2567 (void) printf("Group = %d, mib_id = %d, "
2568 "length = %d, valp = 0x%p\n",
2569 tempitem->group, tempitem->mib_id,
2570 tempitem->length, tempitem->valp);
2573 if (tempitem->mib_id == 0) {
2574 switch (tempitem->group) {
2575 case EXPER_DVMRP: {
2576 struct mrtstat *mrts;
2577 mrts = (struct mrtstat *)tempitem->valp;
2579 if (!(family_selected(AF_INET)))
2580 continue; /* 'for' loop 1 */
2582 print_mrt_stats(mrts);
2583 break;
2587 } /* 'for' loop 1 ends */
2588 (void) putchar('\n');
2589 (void) fflush(stdout);
2593 * if_stat_total() - Computes totals for interface statistics
2594 * and returns result by updating sumstats.
2596 static void
2597 if_stat_total(struct ifstat *oldstats, struct ifstat *newstats,
2598 struct ifstat *sumstats)
2600 sumstats->ipackets += newstats->ipackets - oldstats->ipackets;
2601 sumstats->opackets += newstats->opackets - oldstats->opackets;
2602 sumstats->ierrors += newstats->ierrors - oldstats->ierrors;
2603 sumstats->oerrors += newstats->oerrors - oldstats->oerrors;
2604 sumstats->collisions += newstats->collisions - oldstats->collisions;
2607 /* --------------------- IF_REPORT (netstat -i) -------------------------- */
2609 static struct ifstat zerostat = {
2610 0LL, 0LL, 0LL, 0LL, 0LL
2613 static void
2614 if_report(mib_item_t *item, char *matchname,
2615 int Iflag_only, boolean_t once_only)
2617 static boolean_t reentry = B_FALSE;
2618 boolean_t alreadydone = B_FALSE;
2619 int jtemp = 0;
2620 uint32_t ifindex_v4 = 0;
2621 uint32_t ifindex_v6 = 0;
2622 boolean_t first_header = B_TRUE;
2624 /* 'for' loop 1: */
2625 for (; item; item = item->next_item) {
2626 if (Xflag) {
2627 (void) printf("\n--- Entry %d ---\n", ++jtemp);
2628 (void) printf("Group = %d, mib_id = %d, "
2629 "length = %d, valp = 0x%p\n",
2630 item->group, item->mib_id, item->length,
2631 item->valp);
2634 switch (item->group) {
2635 case MIB2_IP:
2636 if (item->mib_id != MIB2_IP_ADDR ||
2637 !family_selected(AF_INET))
2638 continue; /* 'for' loop 1 */
2640 static struct ifstat old = {0L, 0L, 0L, 0L, 0L};
2641 static struct ifstat new = {0L, 0L, 0L, 0L, 0L};
2642 struct ifstat sum;
2643 struct iflist *newlist = NULL;
2644 static struct iflist *oldlist = NULL;
2645 kstat_t *ksp;
2647 if (once_only) {
2648 char ifname[LIFNAMSIZ + 1];
2649 char logintname[LIFNAMSIZ + 1];
2650 mib2_ipAddrEntry_t *ap;
2651 struct ifstat stat = {0L, 0L, 0L, 0L, 0L};
2652 boolean_t first = B_TRUE;
2653 uint32_t new_ifindex;
2655 if (Xflag)
2656 (void) printf("if_report: %d items\n",
2657 (item->length)
2658 / sizeof (mib2_ipAddrEntry_t));
2660 /* 'for' loop 2a: */
2661 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2662 (char *)ap < (char *)item->valp
2663 + item->length;
2664 ap++) {
2665 (void) octetstr(&ap->ipAdEntIfIndex,
2666 'a', logintname,
2667 sizeof (logintname));
2668 (void) strcpy(ifname, logintname);
2669 (void) strtok(ifname, ":");
2670 if (matchname != NULL &&
2671 strcmp(matchname, ifname) != 0 &&
2672 strcmp(matchname, logintname) != 0)
2673 continue; /* 'for' loop 2a */
2674 new_ifindex =
2675 if_nametoindex(logintname);
2677 * First lookup the "link" kstats in
2678 * case the link is renamed. Then
2679 * fallback to the legacy kstats for
2680 * those non-GLDv3 links.
2682 if (new_ifindex != ifindex_v4 &&
2683 (((ksp = kstat_lookup(kc, "link", 0,
2684 ifname)) != NULL) ||
2685 ((ksp = kstat_lookup(kc, NULL, -1,
2686 ifname)) != NULL))) {
2687 (void) safe_kstat_read(kc, ksp,
2688 NULL);
2689 stat.ipackets =
2690 kstat_named_value(ksp,
2691 "ipackets");
2692 stat.ierrors =
2693 kstat_named_value(ksp,
2694 "ierrors");
2695 stat.opackets =
2696 kstat_named_value(ksp,
2697 "opackets");
2698 stat.oerrors =
2699 kstat_named_value(ksp,
2700 "oerrors");
2701 stat.collisions =
2702 kstat_named_value(ksp,
2703 "collisions");
2704 if (first) {
2705 if (!first_header)
2706 (void) putchar('\n');
2707 first_header = B_FALSE;
2708 (void) printf(
2709 "%-5.5s %-5.5s%-13.13s "
2710 "%-14.14s %-6.6s %-5.5s "
2711 "%-6.6s %-5.5s %-6.6s "
2712 "%-6.6s\n",
2713 "Name", "Mtu", "Net/Dest",
2714 "Address", "Ipkts",
2715 "Ierrs", "Opkts", "Oerrs",
2716 "Collis", "Queue");
2718 first = B_FALSE;
2720 if_report_ip4(ap, ifname,
2721 logintname, &stat, B_TRUE);
2722 ifindex_v4 = new_ifindex;
2723 } else {
2724 if_report_ip4(ap, ifname,
2725 logintname, &stat, B_FALSE);
2727 } /* 'for' loop 2a ends */
2728 } else if (!alreadydone) {
2729 char ifname[LIFNAMSIZ + 1];
2730 char buf[LIFNAMSIZ + 1];
2731 mib2_ipAddrEntry_t *ap;
2732 struct ifstat t;
2733 struct iflist *tlp = NULL;
2734 struct iflist **nextnew = &newlist;
2735 struct iflist *walkold;
2736 struct iflist *cleanlist;
2737 boolean_t found_if = B_FALSE;
2739 alreadydone = B_TRUE; /* ignore other case */
2742 * Check if there is anything to do.
2744 if (item->length <
2745 sizeof (mib2_ipAddrEntry_t)) {
2746 fail(0, "No compatible interfaces");
2750 * 'for' loop 2b: find the "right" entry:
2751 * If an interface name to match has been
2752 * supplied then try and find it, otherwise
2753 * match the first non-loopback interface found.
2754 * Use lo0 if all else fails.
2756 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2757 (char *)ap < (char *)item->valp
2758 + item->length;
2759 ap++) {
2760 (void) octetstr(&ap->ipAdEntIfIndex,
2761 'a', ifname, sizeof (ifname));
2762 (void) strtok(ifname, ":");
2764 if (matchname) {
2765 if (strcmp(matchname,
2766 ifname) == 0) {
2767 /* 'for' loop 2b */
2768 found_if = B_TRUE;
2769 break;
2771 } else if (strcmp(ifname, "lo0") != 0)
2772 break; /* 'for' loop 2b */
2773 } /* 'for' loop 2b ends */
2775 if (matchname == NULL) {
2776 matchname = ifname;
2777 } else {
2778 if (!found_if)
2779 fail(0, "-I: %s no such "
2780 "interface.", matchname);
2783 if (Iflag_only == 0 || !reentry) {
2784 (void) printf(" input %-6.6s "
2785 "output ",
2786 matchname);
2787 (void) printf(" input (Total) "
2788 "output\n");
2789 (void) printf("%-7.7s %-5.5s %-7.7s "
2790 "%-5.5s %-6.6s ",
2791 "packets", "errs", "packets",
2792 "errs", "colls");
2793 (void) printf("%-7.7s %-5.5s %-7.7s "
2794 "%-5.5s %-6.6s\n",
2795 "packets", "errs", "packets",
2796 "errs", "colls");
2799 sum = zerostat;
2801 /* 'for' loop 2c: */
2802 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2803 (char *)ap < (char *)item->valp
2804 + item->length;
2805 ap++) {
2806 (void) octetstr(&ap->ipAdEntIfIndex,
2807 'a', buf, sizeof (buf));
2808 (void) strtok(buf, ":");
2811 * We have reduced the IP interface
2812 * name, which could have been a
2813 * logical, down to a name suitable
2814 * for use with kstats.
2815 * We treat this name as unique and
2816 * only collate statistics for it once
2817 * per pass. This is to avoid falsely
2818 * amplifying these statistics by the
2819 * the number of logical instances.
2821 if ((tlp != NULL) &&
2822 ((strcmp(buf, tlp->ifname) == 0))) {
2823 continue;
2827 * First lookup the "link" kstats in
2828 * case the link is renamed. Then
2829 * fallback to the legacy kstats for
2830 * those non-GLDv3 links.
2832 if (((ksp = kstat_lookup(kc, "link",
2833 0, buf)) != NULL ||
2834 (ksp = kstat_lookup(kc, NULL, -1,
2835 buf)) != NULL) && (ksp->ks_type ==
2836 KSTAT_TYPE_NAMED)) {
2837 (void) safe_kstat_read(kc, ksp,
2838 NULL);
2841 t.ipackets = kstat_named_value(ksp,
2842 "ipackets");
2843 t.ierrors = kstat_named_value(ksp,
2844 "ierrors");
2845 t.opackets = kstat_named_value(ksp,
2846 "opackets");
2847 t.oerrors = kstat_named_value(ksp,
2848 "oerrors");
2849 t.collisions = kstat_named_value(ksp,
2850 "collisions");
2852 if (strcmp(buf, matchname) == 0)
2853 new = t;
2855 /* Build the interface list */
2857 tlp = malloc(sizeof (struct iflist));
2858 (void) strlcpy(tlp->ifname, buf,
2859 sizeof (tlp->ifname));
2860 tlp->tot = t;
2861 *nextnew = tlp;
2862 nextnew = &tlp->next_if;
2865 * First time through.
2866 * Just add up the interface stats.
2869 if (oldlist == NULL) {
2870 if_stat_total(&zerostat,
2871 &t, &sum);
2872 continue;
2876 * Walk old list for the interface.
2878 * If found, add difference to total.
2880 * If not, an interface has been plumbed
2881 * up. In this case, we will simply
2882 * ignore the new interface until the
2883 * next interval; as there's no easy way
2884 * to acquire statistics between time
2885 * of the plumb and the next interval
2886 * boundary. This results in inaccurate
2887 * total values for current interval.
2889 * Note the case when an interface is
2890 * unplumbed; as similar problems exist.
2891 * The unplumbed interface is not in the
2892 * current list, and there's no easy way
2893 * to account for the statistics between
2894 * the previous interval and time of the
2895 * unplumb. Therefore, we (in a sense)
2896 * ignore the removed interface by only
2897 * involving "current" interfaces when
2898 * computing the total statistics.
2899 * Unfortunately, this also results in
2900 * inaccurate values for interval total.
2903 for (walkold = oldlist;
2904 walkold != NULL;
2905 walkold = walkold->next_if) {
2906 if (strcmp(walkold->ifname,
2907 buf) == 0) {
2908 if_stat_total(
2909 &walkold->tot,
2910 &t, &sum);
2911 break;
2915 } /* 'for' loop 2c ends */
2917 *nextnew = NULL;
2919 (void) printf("%-7llu %-5llu %-7llu "
2920 "%-5llu %-6llu ",
2921 new.ipackets - old.ipackets,
2922 new.ierrors - old.ierrors,
2923 new.opackets - old.opackets,
2924 new.oerrors - old.oerrors,
2925 new.collisions - old.collisions);
2927 (void) printf("%-7llu %-5llu %-7llu "
2928 "%-5llu %-6llu\n", sum.ipackets,
2929 sum.ierrors, sum.opackets,
2930 sum.oerrors, sum.collisions);
2933 * Tidy things up once finished.
2936 old = new;
2937 cleanlist = oldlist;
2938 oldlist = newlist;
2939 while (cleanlist != NULL) {
2940 tlp = cleanlist->next_if;
2941 free(cleanlist);
2942 cleanlist = tlp;
2945 break;
2947 case MIB2_IP6:
2948 if (item->mib_id != MIB2_IP6_ADDR ||
2949 !family_selected(AF_INET6))
2950 continue; /* 'for' loop 1 */
2952 static struct ifstat old6 = {0L, 0L, 0L, 0L, 0L};
2953 static struct ifstat new6 = {0L, 0L, 0L, 0L, 0L};
2954 struct ifstat sum6;
2955 struct iflist *newlist6 = NULL;
2956 static struct iflist *oldlist6 = NULL;
2957 kstat_t *ksp;
2959 if (once_only) {
2960 char ifname[LIFNAMSIZ + 1];
2961 char logintname[LIFNAMSIZ + 1];
2962 mib2_ipv6AddrEntry_t *ap6;
2963 struct ifstat stat = {0L, 0L, 0L, 0L, 0L};
2964 boolean_t first = B_TRUE;
2965 uint32_t new_ifindex;
2967 if (Xflag)
2968 (void) printf("if_report: %d items\n",
2969 (item->length)
2970 / sizeof (mib2_ipv6AddrEntry_t));
2971 /* 'for' loop 2d: */
2972 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
2973 (char *)ap6 < (char *)item->valp
2974 + item->length;
2975 ap6++) {
2976 (void) octetstr(&ap6->ipv6AddrIfIndex,
2977 'a', logintname,
2978 sizeof (logintname));
2979 (void) strcpy(ifname, logintname);
2980 (void) strtok(ifname, ":");
2981 if (matchname != NULL &&
2982 strcmp(matchname, ifname) != 0 &&
2983 strcmp(matchname, logintname) != 0)
2984 continue; /* 'for' loop 2d */
2985 new_ifindex =
2986 if_nametoindex(logintname);
2989 * First lookup the "link" kstats in
2990 * case the link is renamed. Then
2991 * fallback to the legacy kstats for
2992 * those non-GLDv3 links.
2994 if (new_ifindex != ifindex_v6 &&
2995 ((ksp = kstat_lookup(kc, "link", 0,
2996 ifname)) != NULL ||
2997 (ksp = kstat_lookup(kc, NULL, -1,
2998 ifname)) != NULL)) {
2999 (void) safe_kstat_read(kc, ksp,
3000 NULL);
3001 stat.ipackets =
3002 kstat_named_value(ksp,
3003 "ipackets");
3004 stat.ierrors =
3005 kstat_named_value(ksp,
3006 "ierrors");
3007 stat.opackets =
3008 kstat_named_value(ksp,
3009 "opackets");
3010 stat.oerrors =
3011 kstat_named_value(ksp,
3012 "oerrors");
3013 stat.collisions =
3014 kstat_named_value(ksp,
3015 "collisions");
3016 if (first) {
3017 if (!first_header)
3018 (void) putchar('\n');
3019 first_header = B_FALSE;
3020 (void) printf(
3021 "%-5.5s %-5.5s%"
3022 "-27.27s %-27.27s "
3023 "%-6.6s %-5.5s "
3024 "%-6.6s %-5.5s "
3025 "%-6.6s\n",
3026 "Name", "Mtu",
3027 "Net/Dest",
3028 "Address", "Ipkts",
3029 "Ierrs", "Opkts",
3030 "Oerrs", "Collis");
3031 first = B_FALSE;
3033 if_report_ip6(ap6, ifname,
3034 logintname, &stat, B_TRUE);
3035 ifindex_v6 = new_ifindex;
3036 } else {
3037 if_report_ip6(ap6, ifname,
3038 logintname, &stat, B_FALSE);
3040 } /* 'for' loop 2d ends */
3041 } else if (!alreadydone) {
3042 char ifname[LIFNAMSIZ + 1];
3043 char buf[IFNAMSIZ + 1];
3044 mib2_ipv6AddrEntry_t *ap6;
3045 struct ifstat t;
3046 struct iflist *tlp = NULL;
3047 struct iflist **nextnew = &newlist6;
3048 struct iflist *walkold;
3049 struct iflist *cleanlist;
3050 boolean_t found_if = B_FALSE;
3052 alreadydone = B_TRUE; /* ignore other case */
3055 * Check if there is anything to do.
3057 if (item->length <
3058 sizeof (mib2_ipv6AddrEntry_t)) {
3059 fail(0, "No compatible interfaces");
3063 * 'for' loop 2e: find the "right" entry:
3064 * If an interface name to match has been
3065 * supplied then try and find it, otherwise
3066 * match the first non-loopback interface found.
3067 * Use lo0 if all else fails.
3069 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
3070 (char *)ap6 < (char *)item->valp
3071 + item->length;
3072 ap6++) {
3073 (void) octetstr(&ap6->ipv6AddrIfIndex,
3074 'a', ifname, sizeof (ifname));
3075 (void) strtok(ifname, ":");
3077 if (matchname) {
3078 if (strcmp(matchname,
3079 ifname) == 0) {
3080 /* 'for' loop 2e */
3081 found_if = B_TRUE;
3082 break;
3084 } else if (strcmp(ifname, "lo0") != 0)
3085 break; /* 'for' loop 2e */
3086 } /* 'for' loop 2e ends */
3088 if (matchname == NULL) {
3089 matchname = ifname;
3090 } else {
3091 if (!found_if)
3092 fail(0, "-I: %s no such "
3093 "interface.", matchname);
3096 if (Iflag_only == 0 || !reentry) {
3097 (void) printf(
3098 " input %-6.6s"
3099 " output ",
3100 matchname);
3101 (void) printf(" input (Total)"
3102 " output\n");
3103 (void) printf("%-7.7s %-5.5s %-7.7s "
3104 "%-5.5s %-6.6s ",
3105 "packets", "errs", "packets",
3106 "errs", "colls");
3107 (void) printf("%-7.7s %-5.5s %-7.7s "
3108 "%-5.5s %-6.6s\n",
3109 "packets", "errs", "packets",
3110 "errs", "colls");
3113 sum6 = zerostat;
3115 /* 'for' loop 2f: */
3116 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
3117 (char *)ap6 < (char *)item->valp
3118 + item->length;
3119 ap6++) {
3120 (void) octetstr(&ap6->ipv6AddrIfIndex,
3121 'a', buf, sizeof (buf));
3122 (void) strtok(buf, ":");
3125 * We have reduced the IP interface
3126 * name, which could have been a
3127 * logical, down to a name suitable
3128 * for use with kstats.
3129 * We treat this name as unique and
3130 * only collate statistics for it once
3131 * per pass. This is to avoid falsely
3132 * amplifying these statistics by the
3133 * the number of logical instances.
3136 if ((tlp != NULL) &&
3137 ((strcmp(buf, tlp->ifname) == 0))) {
3138 continue;
3142 * First lookup the "link" kstats in
3143 * case the link is renamed. Then
3144 * fallback to the legacy kstats for
3145 * those non-GLDv3 links.
3147 if (((ksp = kstat_lookup(kc, "link",
3148 0, buf)) != NULL ||
3149 (ksp = kstat_lookup(kc, NULL, -1,
3150 buf)) != NULL) && (ksp->ks_type ==
3151 KSTAT_TYPE_NAMED)) {
3152 (void) safe_kstat_read(kc,
3153 ksp, NULL);
3156 t.ipackets = kstat_named_value(ksp,
3157 "ipackets");
3158 t.ierrors = kstat_named_value(ksp,
3159 "ierrors");
3160 t.opackets = kstat_named_value(ksp,
3161 "opackets");
3162 t.oerrors = kstat_named_value(ksp,
3163 "oerrors");
3164 t.collisions = kstat_named_value(ksp,
3165 "collisions");
3167 if (strcmp(buf, matchname) == 0)
3168 new6 = t;
3170 /* Build the interface list */
3172 tlp = malloc(sizeof (struct iflist));
3173 (void) strlcpy(tlp->ifname, buf,
3174 sizeof (tlp->ifname));
3175 tlp->tot = t;
3176 *nextnew = tlp;
3177 nextnew = &tlp->next_if;
3180 * First time through.
3181 * Just add up the interface stats.
3184 if (oldlist6 == NULL) {
3185 if_stat_total(&zerostat,
3186 &t, &sum6);
3187 continue;
3191 * Walk old list for the interface.
3193 * If found, add difference to total.
3195 * If not, an interface has been plumbed
3196 * up. In this case, we will simply
3197 * ignore the new interface until the
3198 * next interval; as there's no easy way
3199 * to acquire statistics between time
3200 * of the plumb and the next interval
3201 * boundary. This results in inaccurate
3202 * total values for current interval.
3204 * Note the case when an interface is
3205 * unplumbed; as similar problems exist.
3206 * The unplumbed interface is not in the
3207 * current list, and there's no easy way
3208 * to account for the statistics between
3209 * the previous interval and time of the
3210 * unplumb. Therefore, we (in a sense)
3211 * ignore the removed interface by only
3212 * involving "current" interfaces when
3213 * computing the total statistics.
3214 * Unfortunately, this also results in
3215 * inaccurate values for interval total.
3218 for (walkold = oldlist6;
3219 walkold != NULL;
3220 walkold = walkold->next_if) {
3221 if (strcmp(walkold->ifname,
3222 buf) == 0) {
3223 if_stat_total(
3224 &walkold->tot,
3225 &t, &sum6);
3226 break;
3230 } /* 'for' loop 2f ends */
3232 *nextnew = NULL;
3234 (void) printf("%-7llu %-5llu %-7llu "
3235 "%-5llu %-6llu ",
3236 new6.ipackets - old6.ipackets,
3237 new6.ierrors - old6.ierrors,
3238 new6.opackets - old6.opackets,
3239 new6.oerrors - old6.oerrors,
3240 new6.collisions - old6.collisions);
3242 (void) printf("%-7llu %-5llu %-7llu "
3243 "%-5llu %-6llu\n", sum6.ipackets,
3244 sum6.ierrors, sum6.opackets,
3245 sum6.oerrors, sum6.collisions);
3248 * Tidy things up once finished.
3251 old6 = new6;
3252 cleanlist = oldlist6;
3253 oldlist6 = newlist6;
3254 while (cleanlist != NULL) {
3255 tlp = cleanlist->next_if;
3256 free(cleanlist);
3257 cleanlist = tlp;
3260 break;
3263 (void) fflush(stdout);
3264 } /* 'for' loop 1 ends */
3265 if ((Iflag_only == 0) && (!once_only))
3266 (void) putchar('\n');
3267 reentry = B_TRUE;
3270 static void
3271 if_report_ip4(mib2_ipAddrEntry_t *ap,
3272 char ifname[], char logintname[], struct ifstat *statptr,
3273 boolean_t ksp_not_null)
3276 char abuf[MAXHOSTNAMELEN + 4]; /* Include /<num> for CIDR-printing. */
3277 char dstbuf[MAXHOSTNAMELEN + 1];
3279 if (ksp_not_null) {
3280 (void) printf("%-5s %-4u ",
3281 ifname, ap->ipAdEntInfo.ae_mtu);
3282 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3283 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3284 abuf, sizeof (abuf));
3285 else
3286 (void) pr_netaddr(ap->ipAdEntAddr,
3287 ap->ipAdEntNetMask, abuf, sizeof (abuf));
3288 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3289 "%-6llu %-6llu\n",
3290 abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3291 statptr->ipackets, statptr->ierrors,
3292 statptr->opackets, statptr->oerrors,
3293 statptr->collisions, 0LL);
3296 * Print logical interface info if Aflag set (including logical unit 0)
3298 if (Aflag) {
3299 *statptr = zerostat;
3300 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3301 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3303 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3304 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3305 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3306 sizeof (abuf));
3307 else
3308 (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3309 abuf, sizeof (abuf));
3311 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3312 "%-5s %-6s %-6llu\n", abuf,
3313 pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3314 statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3315 0LL);
3319 static void
3320 if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
3321 char ifname[], char logintname[], struct ifstat *statptr,
3322 boolean_t ksp_not_null)
3325 char abuf[MAXHOSTNAMELEN + 1];
3326 char dstbuf[MAXHOSTNAMELEN + 1];
3328 if (ksp_not_null) {
3329 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3330 if (ap6->ipv6AddrInfo.ae_flags &
3331 IFF_POINTOPOINT) {
3332 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3333 abuf, sizeof (abuf));
3334 } else {
3335 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3336 ap6->ipv6AddrPfxLength, abuf,
3337 sizeof (abuf));
3339 (void) printf("%-27s %-27s %-6llu %-5llu "
3340 "%-6llu %-5llu %-6llu\n",
3341 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3342 sizeof (dstbuf)),
3343 statptr->ipackets, statptr->ierrors, statptr->opackets,
3344 statptr->oerrors, statptr->collisions);
3347 * Print logical interface info if Aflag set (including logical unit 0)
3349 if (Aflag) {
3350 *statptr = zerostat;
3351 statptr->ipackets = ap6->ipv6AddrInfo.ae_ibcnt;
3352 statptr->opackets = ap6->ipv6AddrInfo.ae_obcnt;
3354 (void) printf("%-5s %-4u ", logintname,
3355 ap6->ipv6AddrInfo.ae_mtu);
3356 if (ap6->ipv6AddrInfo.ae_flags & IFF_POINTOPOINT)
3357 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3358 abuf, sizeof (abuf));
3359 else
3360 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3361 ap6->ipv6AddrPfxLength, abuf, sizeof (abuf));
3362 (void) printf("%-27s %-27s %-6llu %-5s %-6s %-5s %-6s\n",
3363 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3364 sizeof (dstbuf)),
3365 statptr->ipackets, "N/A", "N/A", "N/A", "N/A");
3369 /* --------------------- DHCP_REPORT (netstat -D) ------------------------- */
3371 static boolean_t
3372 dhcp_do_ipc(dhcp_ipc_type_t type, const char *ifname, boolean_t printed_one)
3374 dhcp_ipc_request_t *request;
3375 dhcp_ipc_reply_t *reply;
3376 int error;
3378 request = dhcp_ipc_alloc_request(type, ifname, NULL, 0, DHCP_TYPE_NONE);
3379 if (request == NULL)
3380 fail(0, "dhcp_do_ipc: out of memory");
3382 error = dhcp_ipc_make_request(request, &reply, DHCP_IPC_WAIT_DEFAULT);
3383 if (error != 0) {
3384 free(request);
3385 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error));
3388 free(request);
3389 error = reply->return_code;
3390 if (error == DHCP_IPC_E_UNKIF) {
3391 free(reply);
3392 return (printed_one);
3394 if (error != 0) {
3395 free(reply);
3396 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error));
3399 if (timestamp_fmt != NODATE)
3400 print_timestamp(timestamp_fmt);
3402 if (!printed_one)
3403 (void) printf("%s", dhcp_status_hdr_string());
3405 (void) printf("%s", dhcp_status_reply_to_string(reply));
3406 free(reply);
3407 return (B_TRUE);
3411 * dhcp_walk_interfaces: walk the list of interfaces for a given address
3412 * family (af). For each, print out the DHCP status using dhcp_do_ipc.
3414 static boolean_t
3415 dhcp_walk_interfaces(int af, boolean_t printed_one)
3417 struct lifnum lifn;
3418 struct lifconf lifc;
3419 int n_ifs, i, sock_fd;
3421 sock_fd = socket(af, SOCK_DGRAM, 0);
3422 if (sock_fd == -1)
3423 return (printed_one);
3426 * SIOCGLIFNUM is just an estimate. If the ioctl fails, we don't care;
3427 * just drive on and use SIOCGLIFCONF with increasing buffer sizes, as
3428 * is traditional.
3430 (void) memset(&lifn, 0, sizeof (lifn));
3431 lifn.lifn_family = af;
3432 lifn.lifn_flags = LIFC_ALLZONES | LIFC_NOXMIT | LIFC_UNDER_IPMP;
3433 if (ioctl(sock_fd, SIOCGLIFNUM, &lifn) == -1)
3434 n_ifs = LIFN_GUARD_VALUE;
3435 else
3436 n_ifs = lifn.lifn_count + LIFN_GUARD_VALUE;
3438 (void) memset(&lifc, 0, sizeof (lifc));
3439 lifc.lifc_family = af;
3440 lifc.lifc_flags = lifn.lifn_flags;
3441 lifc.lifc_len = n_ifs * sizeof (struct lifreq);
3442 lifc.lifc_buf = malloc(lifc.lifc_len);
3443 if (lifc.lifc_buf != NULL) {
3445 if (ioctl(sock_fd, SIOCGLIFCONF, &lifc) == -1) {
3446 (void) close(sock_fd);
3447 free(lifc.lifc_buf);
3448 return (B_FALSE);
3451 n_ifs = lifc.lifc_len / sizeof (struct lifreq);
3453 for (i = 0; i < n_ifs; i++) {
3454 printed_one = dhcp_do_ipc(DHCP_STATUS |
3455 (af == AF_INET6 ? DHCP_V6 : 0),
3456 lifc.lifc_req[i].lifr_name, printed_one);
3459 (void) close(sock_fd);
3460 free(lifc.lifc_buf);
3461 return (printed_one);
3464 static void
3465 dhcp_report(char *ifname)
3467 boolean_t printed_one;
3469 if (!family_selected(AF_INET) && !family_selected(AF_INET6))
3470 return;
3472 printed_one = B_FALSE;
3473 if (ifname != NULL) {
3474 if (family_selected(AF_INET)) {
3475 printed_one = dhcp_do_ipc(DHCP_STATUS, ifname,
3476 printed_one);
3478 if (family_selected(AF_INET6)) {
3479 printed_one = dhcp_do_ipc(DHCP_STATUS | DHCP_V6,
3480 ifname, printed_one);
3482 if (!printed_one) {
3483 fail(0, "%s: %s", ifname,
3484 dhcp_ipc_strerror(DHCP_IPC_E_UNKIF));
3486 } else {
3487 if (family_selected(AF_INET)) {
3488 printed_one = dhcp_walk_interfaces(AF_INET,
3489 printed_one);
3491 if (family_selected(AF_INET6))
3492 (void) dhcp_walk_interfaces(AF_INET6, printed_one);
3496 /* --------------------- GROUP_REPORT (netstat -g) ------------------------- */
3498 static void
3499 group_report(mib_item_t *item)
3501 mib_item_t *v4grp = NULL, *v4src = NULL;
3502 mib_item_t *v6grp = NULL, *v6src = NULL;
3503 int jtemp = 0;
3504 char ifname[LIFNAMSIZ + 1];
3505 char abuf[MAXHOSTNAMELEN + 1];
3506 ip_member_t *ipmp;
3507 ip_grpsrc_t *ips;
3508 ipv6_member_t *ipmp6;
3509 ipv6_grpsrc_t *ips6;
3510 boolean_t first, first_src;
3512 /* 'for' loop 1: */
3513 for (; item; item = item->next_item) {
3514 if (Xflag) {
3515 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3516 (void) printf("Group = %d, mib_id = %d, "
3517 "length = %d, valp = 0x%p\n",
3518 item->group, item->mib_id, item->length,
3519 item->valp);
3521 if (item->group == MIB2_IP && family_selected(AF_INET)) {
3522 switch (item->mib_id) {
3523 case EXPER_IP_GROUP_MEMBERSHIP:
3524 v4grp = item;
3525 if (Xflag)
3526 (void) printf("item is v4grp info\n");
3527 break;
3528 case EXPER_IP_GROUP_SOURCES:
3529 v4src = item;
3530 if (Xflag)
3531 (void) printf("item is v4src info\n");
3532 break;
3533 default:
3534 continue;
3536 continue;
3538 if (item->group == MIB2_IP6 && family_selected(AF_INET6)) {
3539 switch (item->mib_id) {
3540 case EXPER_IP6_GROUP_MEMBERSHIP:
3541 v6grp = item;
3542 if (Xflag)
3543 (void) printf("item is v6grp info\n");
3544 break;
3545 case EXPER_IP6_GROUP_SOURCES:
3546 v6src = item;
3547 if (Xflag)
3548 (void) printf("item is v6src info\n");
3549 break;
3550 default:
3551 continue;
3556 if (family_selected(AF_INET) && v4grp != NULL) {
3557 if (Xflag)
3558 (void) printf("%u records for ipGroupMember:\n",
3559 v4grp->length / sizeof (ip_member_t));
3561 first = B_TRUE;
3562 for (ipmp = (ip_member_t *)v4grp->valp;
3563 (char *)ipmp < (char *)v4grp->valp + v4grp->length;
3564 /* LINTED: (note 1) */
3565 ipmp = (ip_member_t *)((char *)ipmp + ipMemberEntrySize)) {
3566 if (first) {
3567 (void) puts(v4compat ?
3568 "Group Memberships" :
3569 "Group Memberships: IPv4");
3570 (void) puts("Interface "
3571 "Group RefCnt");
3572 (void) puts("--------- "
3573 "-------------------- ------");
3574 first = B_FALSE;
3577 (void) printf("%-9s %-20s %6u\n",
3578 octetstr(&ipmp->ipGroupMemberIfIndex, 'a',
3579 ifname, sizeof (ifname)),
3580 pr_addr(ipmp->ipGroupMemberAddress,
3581 abuf, sizeof (abuf)),
3582 ipmp->ipGroupMemberRefCnt);
3585 if (!Vflag || v4src == NULL)
3586 continue;
3588 if (Xflag)
3589 (void) printf("scanning %u ipGroupSource "
3590 "records...\n",
3591 v4src->length/sizeof (ip_grpsrc_t));
3593 first_src = B_TRUE;
3594 for (ips = (ip_grpsrc_t *)v4src->valp;
3595 (char *)ips < (char *)v4src->valp + v4src->length;
3596 /* LINTED: (note 1) */
3597 ips = (ip_grpsrc_t *)((char *)ips +
3598 ipGroupSourceEntrySize)) {
3600 * We assume that all source addrs for a given
3601 * interface/group pair are contiguous, so on
3602 * the first non-match after we've found at
3603 * least one, we bail.
3605 if ((ipmp->ipGroupMemberAddress !=
3606 ips->ipGroupSourceGroup) ||
3607 (!octetstrmatch(&ipmp->ipGroupMemberIfIndex,
3608 &ips->ipGroupSourceIfIndex))) {
3609 if (first_src)
3610 continue;
3611 else
3612 break;
3614 if (first_src) {
3615 (void) printf("\t%s: %s\n",
3616 fmodestr(
3617 ipmp->ipGroupMemberFilterMode),
3618 pr_addr(ips->ipGroupSourceAddress,
3619 abuf, sizeof (abuf)));
3620 first_src = B_FALSE;
3621 continue;
3624 (void) printf("\t %s\n",
3625 pr_addr(ips->ipGroupSourceAddress, abuf,
3626 sizeof (abuf)));
3629 (void) putchar('\n');
3632 if (family_selected(AF_INET6) && v6grp != NULL) {
3633 if (Xflag)
3634 (void) printf("%u records for ipv6GroupMember:\n",
3635 v6grp->length / sizeof (ipv6_member_t));
3637 first = B_TRUE;
3638 for (ipmp6 = (ipv6_member_t *)v6grp->valp;
3639 (char *)ipmp6 < (char *)v6grp->valp + v6grp->length;
3640 /* LINTED: (note 1) */
3641 ipmp6 = (ipv6_member_t *)((char *)ipmp6 +
3642 ipv6MemberEntrySize)) {
3643 if (first) {
3644 (void) puts("Group Memberships: "
3645 "IPv6");
3646 (void) puts(" If "
3647 "Group RefCnt");
3648 (void) puts("----- "
3649 "--------------------------- ------");
3650 first = B_FALSE;
3653 (void) printf("%-5s %-27s %5u\n",
3654 ifindex2str(ipmp6->ipv6GroupMemberIfIndex, ifname),
3655 pr_addr6(&ipmp6->ipv6GroupMemberAddress,
3656 abuf, sizeof (abuf)),
3657 ipmp6->ipv6GroupMemberRefCnt);
3659 if (!Vflag || v6src == NULL)
3660 continue;
3662 if (Xflag)
3663 (void) printf("scanning %u ipv6GroupSource "
3664 "records...\n",
3665 v6src->length/sizeof (ipv6_grpsrc_t));
3667 first_src = B_TRUE;
3668 for (ips6 = (ipv6_grpsrc_t *)v6src->valp;
3669 (char *)ips6 < (char *)v6src->valp + v6src->length;
3670 /* LINTED: (note 1) */
3671 ips6 = (ipv6_grpsrc_t *)((char *)ips6 +
3672 ipv6GroupSourceEntrySize)) {
3673 /* same assumption as in the v4 case above */
3674 if ((ipmp6->ipv6GroupMemberIfIndex !=
3675 ips6->ipv6GroupSourceIfIndex) ||
3676 (!IN6_ARE_ADDR_EQUAL(
3677 &ipmp6->ipv6GroupMemberAddress,
3678 &ips6->ipv6GroupSourceGroup))) {
3679 if (first_src)
3680 continue;
3681 else
3682 break;
3684 if (first_src) {
3685 (void) printf("\t%s: %s\n",
3686 fmodestr(
3687 ipmp6->ipv6GroupMemberFilterMode),
3688 pr_addr6(
3689 &ips6->ipv6GroupSourceAddress,
3690 abuf, sizeof (abuf)));
3691 first_src = B_FALSE;
3692 continue;
3695 (void) printf("\t %s\n",
3696 pr_addr6(&ips6->ipv6GroupSourceAddress,
3697 abuf, sizeof (abuf)));
3700 (void) putchar('\n');
3703 (void) putchar('\n');
3704 (void) fflush(stdout);
3707 /* --------------------- DCE_REPORT (netstat -d) ------------------------- */
3709 #define FLBUFSIZE 8
3711 /* Assumes flbuf is at least 5 characters; callers use FLBUFSIZE */
3712 static char *
3713 dceflags2str(uint32_t flags, char *flbuf)
3715 char *str = flbuf;
3717 if (flags & DCEF_DEFAULT)
3718 *str++ = 'D';
3719 if (flags & DCEF_PMTU)
3720 *str++ = 'P';
3721 if (flags & DCEF_UINFO)
3722 *str++ = 'U';
3723 if (flags & DCEF_TOO_SMALL_PMTU)
3724 *str++ = 'S';
3725 *str++ = '\0';
3726 return (flbuf);
3729 static void
3730 dce_report(mib_item_t *item)
3732 mib_item_t *v4dce = NULL;
3733 mib_item_t *v6dce = NULL;
3734 int jtemp = 0;
3735 char ifname[LIFNAMSIZ + 1];
3736 char abuf[MAXHOSTNAMELEN + 1];
3737 char flbuf[FLBUFSIZE];
3738 boolean_t first;
3739 dest_cache_entry_t *dce;
3741 /* 'for' loop 1: */
3742 for (; item; item = item->next_item) {
3743 if (Xflag) {
3744 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3745 (void) printf("Group = %d, mib_id = %d, "
3746 "length = %d, valp = 0x%p\n",
3747 item->group, item->mib_id, item->length,
3748 item->valp);
3750 if (item->group == MIB2_IP && family_selected(AF_INET) &&
3751 item->mib_id == EXPER_IP_DCE) {
3752 v4dce = item;
3753 if (Xflag)
3754 (void) printf("item is v4dce info\n");
3756 if (item->group == MIB2_IP6 && family_selected(AF_INET6) &&
3757 item->mib_id == EXPER_IP_DCE) {
3758 v6dce = item;
3759 if (Xflag)
3760 (void) printf("item is v6dce info\n");
3764 if (family_selected(AF_INET) && v4dce != NULL) {
3765 if (Xflag)
3766 (void) printf("%u records for DestCacheEntry:\n",
3767 v4dce->length / ipDestEntrySize);
3769 first = B_TRUE;
3770 for (dce = (dest_cache_entry_t *)v4dce->valp;
3771 (char *)dce < (char *)v4dce->valp + v4dce->length;
3772 /* LINTED: (note 1) */
3773 dce = (dest_cache_entry_t *)((char *)dce +
3774 ipDestEntrySize)) {
3775 if (first) {
3776 (void) putchar('\n');
3777 (void) puts("Destination Cache Entries: IPv4");
3778 (void) puts(
3779 "Address PMTU Age Flags");
3780 (void) puts(
3781 "-------------------- ------ ----- -----");
3782 first = B_FALSE;
3785 (void) printf("%-20s %6u %5u %-5s\n",
3786 pr_addr(dce->DestIpv4Address, abuf, sizeof (abuf)),
3787 dce->DestPmtu, dce->DestAge,
3788 dceflags2str(dce->DestFlags, flbuf));
3792 if (family_selected(AF_INET6) && v6dce != NULL) {
3793 if (Xflag)
3794 (void) printf("%u records for DestCacheEntry:\n",
3795 v6dce->length / ipDestEntrySize);
3797 first = B_TRUE;
3798 for (dce = (dest_cache_entry_t *)v6dce->valp;
3799 (char *)dce < (char *)v6dce->valp + v6dce->length;
3800 /* LINTED: (note 1) */
3801 dce = (dest_cache_entry_t *)((char *)dce +
3802 ipDestEntrySize)) {
3803 if (first) {
3804 (void) putchar('\n');
3805 (void) puts("Destination Cache Entries: IPv6");
3806 (void) puts(
3807 "Address PMTU "
3808 " Age Flags If ");
3809 (void) puts(
3810 "--------------------------- ------ "
3811 "----- ----- ---");
3812 first = B_FALSE;
3815 (void) printf("%-27s %6u %5u %-5s %s\n",
3816 pr_addr6(&dce->DestIpv6Address, abuf,
3817 sizeof (abuf)),
3818 dce->DestPmtu, dce->DestAge,
3819 dceflags2str(dce->DestFlags, flbuf),
3820 dce->DestIfindex == 0 ? "" :
3821 ifindex2str(dce->DestIfindex, ifname));
3824 (void) fflush(stdout);
3827 /* --------------------- ARP_REPORT (netstat -p) -------------------------- */
3829 static void
3830 arp_report(mib_item_t *item)
3832 int jtemp = 0;
3833 char ifname[LIFNAMSIZ + 1];
3834 char abuf[MAXHOSTNAMELEN + 1];
3835 char maskbuf[STR_EXPAND * OCTET_LENGTH + 1];
3836 char flbuf[32]; /* ACE_F_ flags */
3837 char xbuf[STR_EXPAND * OCTET_LENGTH + 1];
3838 mib2_ipNetToMediaEntry_t *np;
3839 int flags;
3840 boolean_t first;
3842 if (!(family_selected(AF_INET)))
3843 return;
3845 /* 'for' loop 1: */
3846 for (; item; item = item->next_item) {
3847 if (Xflag) {
3848 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3849 (void) printf("Group = %d, mib_id = %d, "
3850 "length = %d, valp = 0x%p\n",
3851 item->group, item->mib_id, item->length,
3852 item->valp);
3854 if (!(item->group == MIB2_IP && item->mib_id == MIB2_IP_MEDIA))
3855 continue; /* 'for' loop 1 */
3857 if (Xflag)
3858 (void) printf("%u records for "
3859 "ipNetToMediaEntryTable:\n",
3860 item->length/sizeof (mib2_ipNetToMediaEntry_t));
3862 first = B_TRUE;
3863 /* 'for' loop 2: */
3864 for (np = (mib2_ipNetToMediaEntry_t *)item->valp;
3865 (char *)np < (char *)item->valp + item->length;
3866 /* LINTED: (note 1) */
3867 np = (mib2_ipNetToMediaEntry_t *)((char *)np +
3868 ipNetToMediaEntrySize)) {
3869 if (first) {
3870 (void) puts(v4compat ?
3871 "Net to Media Table" :
3872 "Net to Media Table: IPv4");
3873 (void) puts("Device "
3874 " IP Address Mask "
3875 "Flags Phys Addr");
3876 (void) puts("------ "
3877 "-------------------- --------------- "
3878 "-------- ---------------");
3879 first = B_FALSE;
3882 flbuf[0] = '\0';
3883 flags = np->ipNetToMediaInfo.ntm_flags;
3885 * Note that not all flags are possible at the same
3886 * time. Patterns: SPLAy DUo
3888 if (flags & ACE_F_PERMANENT)
3889 (void) strcat(flbuf, "S");
3890 if (flags & ACE_F_PUBLISH)
3891 (void) strcat(flbuf, "P");
3892 if (flags & ACE_F_DYING)
3893 (void) strcat(flbuf, "D");
3894 if (!(flags & ACE_F_RESOLVED))
3895 (void) strcat(flbuf, "U");
3896 if (flags & ACE_F_MAPPING)
3897 (void) strcat(flbuf, "M");
3898 if (flags & ACE_F_MYADDR)
3899 (void) strcat(flbuf, "L");
3900 if (flags & ACE_F_UNVERIFIED)
3901 (void) strcat(flbuf, "d");
3902 if (flags & ACE_F_AUTHORITY)
3903 (void) strcat(flbuf, "A");
3904 if (flags & ACE_F_OLD)
3905 (void) strcat(flbuf, "o");
3906 if (flags & ACE_F_DELAYED)
3907 (void) strcat(flbuf, "y");
3908 (void) printf("%-6s %-20s %-15s %-8s %s\n",
3909 octetstr(&np->ipNetToMediaIfIndex, 'a',
3910 ifname, sizeof (ifname)),
3911 pr_addr(np->ipNetToMediaNetAddress,
3912 abuf, sizeof (abuf)),
3913 octetstr(&np->ipNetToMediaInfo.ntm_mask, 'd',
3914 maskbuf, sizeof (maskbuf)),
3915 flbuf,
3916 octetstr(&np->ipNetToMediaPhysAddress, 'h',
3917 xbuf, sizeof (xbuf)));
3918 } /* 'for' loop 2 ends */
3919 } /* 'for' loop 1 ends */
3920 (void) fflush(stdout);
3923 /* --------------------- NDP_REPORT (netstat -p) -------------------------- */
3925 static void
3926 ndp_report(mib_item_t *item)
3928 int jtemp = 0;
3929 char abuf[MAXHOSTNAMELEN + 1];
3930 char *state;
3931 char *type;
3932 char xbuf[STR_EXPAND * OCTET_LENGTH + 1];
3933 mib2_ipv6NetToMediaEntry_t *np6;
3934 char ifname[LIFNAMSIZ + 1];
3935 boolean_t first;
3937 if (!(family_selected(AF_INET6)))
3938 return;
3940 /* 'for' loop 1: */
3941 for (; item; item = item->next_item) {
3942 if (Xflag) {
3943 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3944 (void) printf("Group = %d, mib_id = %d, "
3945 "length = %d, valp = 0x%p\n",
3946 item->group, item->mib_id, item->length,
3947 item->valp);
3949 if (!(item->group == MIB2_IP6 &&
3950 item->mib_id == MIB2_IP6_MEDIA))
3951 continue; /* 'for' loop 1 */
3953 first = B_TRUE;
3954 /* 'for' loop 2: */
3955 for (np6 = (mib2_ipv6NetToMediaEntry_t *)item->valp;
3956 (char *)np6 < (char *)item->valp + item->length;
3957 /* LINTED: (note 1) */
3958 np6 = (mib2_ipv6NetToMediaEntry_t *)((char *)np6 +
3959 ipv6NetToMediaEntrySize)) {
3960 if (first) {
3961 (void) puts("\nNet to Media Table: IPv6");
3962 (void) puts(" If Physical Address "
3963 " Type State Destination/Mask");
3964 (void) puts("----- ----------------- "
3965 "------- ------------ "
3966 "---------------------------");
3967 first = B_FALSE;
3970 switch (np6->ipv6NetToMediaState) {
3971 case ND_INCOMPLETE:
3972 state = "INCOMPLETE";
3973 break;
3974 case ND_REACHABLE:
3975 state = "REACHABLE";
3976 break;
3977 case ND_STALE:
3978 state = "STALE";
3979 break;
3980 case ND_DELAY:
3981 state = "DELAY";
3982 break;
3983 case ND_PROBE:
3984 state = "PROBE";
3985 break;
3986 case ND_UNREACHABLE:
3987 state = "UNREACHABLE";
3988 break;
3989 default:
3990 state = "UNKNOWN";
3993 switch (np6->ipv6NetToMediaType) {
3994 case 1:
3995 type = "other";
3996 break;
3997 case 2:
3998 type = "dynamic";
3999 break;
4000 case 3:
4001 type = "static";
4002 break;
4003 case 4:
4004 type = "local";
4005 break;
4007 (void) printf("%-5s %-17s %-7s %-12s %-27s\n",
4008 ifindex2str(np6->ipv6NetToMediaIfIndex, ifname),
4009 octetstr(&np6->ipv6NetToMediaPhysAddress, 'h',
4010 xbuf, sizeof (xbuf)),
4011 type,
4012 state,
4013 pr_addr6(&np6->ipv6NetToMediaNetAddress,
4014 abuf, sizeof (abuf)));
4015 } /* 'for' loop 2 ends */
4016 } /* 'for' loop 1 ends */
4017 (void) putchar('\n');
4018 (void) fflush(stdout);
4021 /* ------------------------- ire_report (netstat -r) ------------------------ */
4023 static boolean_t ire_report_item_v4(const mib2_ipRouteEntry_t *, boolean_t);
4024 static boolean_t ire_report_item_v6(const mib2_ipv6RouteEntry_t *, boolean_t);
4026 static void
4027 ire_report(const mib_item_t *item)
4029 int jtemp = 0;
4030 boolean_t print_hdr_once_v4 = B_TRUE;
4031 boolean_t print_hdr_once_v6 = B_TRUE;
4032 mib2_ipRouteEntry_t *rp;
4033 mib2_ipv6RouteEntry_t *rp6;
4035 for (; item != NULL; item = item->next_item) {
4036 if (Xflag) {
4037 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4038 (void) printf("Group = %d, mib_id = %d, "
4039 "length = %d, valp = 0x%p\n",
4040 item->group, item->mib_id,
4041 item->length, item->valp);
4043 if (!((item->group == MIB2_IP &&
4044 item->mib_id == MIB2_IP_ROUTE) ||
4045 (item->group == MIB2_IP6 &&
4046 item->mib_id == MIB2_IP6_ROUTE)))
4047 continue; /* 'for' loop 1 */
4049 if (item->group == MIB2_IP && !family_selected(AF_INET))
4050 continue; /* 'for' loop 1 */
4051 else if (item->group == MIB2_IP6 && !family_selected(AF_INET6))
4052 continue; /* 'for' loop 1 */
4054 if (Xflag) {
4055 if (item->group == MIB2_IP) {
4056 (void) printf("%u records for "
4057 "ipRouteEntryTable:\n",
4058 item->length/sizeof (mib2_ipRouteEntry_t));
4059 } else {
4060 (void) printf("%u records for "
4061 "ipv6RouteEntryTable:\n",
4062 item->length/
4063 sizeof (mib2_ipv6RouteEntry_t));
4067 if (item->group == MIB2_IP) {
4068 for (rp = (mib2_ipRouteEntry_t *)item->valp;
4069 (char *)rp < (char *)item->valp + item->length;
4070 /* LINTED: (note 1) */
4071 rp = (mib2_ipRouteEntry_t *)((char *)rp +
4072 ipRouteEntrySize)) {
4073 print_hdr_once_v4 = ire_report_item_v4(rp,
4074 print_hdr_once_v4);
4076 } else {
4077 for (rp6 = (mib2_ipv6RouteEntry_t *)item->valp;
4078 (char *)rp6 < (char *)item->valp + item->length;
4079 /* LINTED: (note 1) */
4080 rp6 = (mib2_ipv6RouteEntry_t *)((char *)rp6 +
4081 ipv6RouteEntrySize)) {
4082 print_hdr_once_v6 = ire_report_item_v6(rp6,
4083 print_hdr_once_v6);
4086 } /* 'for' loop 1 ends */
4087 (void) fflush(stdout);
4091 * Match a user-supplied device name. We do this by string because
4092 * the MIB2 interface gives us interface name strings rather than
4093 * ifIndex numbers. The "none" rule matches only routes with no
4094 * interface. The "any" rule matches routes with any non-blank
4095 * interface. A base name ("hme0") matches all aliases as well
4096 * ("hme0:1").
4098 static boolean_t
4099 dev_name_match(const DeviceName *devnam, const char *ifname)
4101 int iflen;
4103 if (ifname == NULL)
4104 return (devnam->o_length == 0); /* "none" */
4105 if (*ifname == '\0')
4106 return (devnam->o_length != 0); /* "any" */
4107 iflen = strlen(ifname);
4108 /* The check for ':' here supports interface aliases. */
4109 if (iflen > devnam->o_length ||
4110 (iflen < devnam->o_length && devnam->o_bytes[iflen] != ':'))
4111 return (B_FALSE);
4112 return (strncmp(ifname, devnam->o_bytes, iflen) == 0);
4116 * Match a user-supplied IP address list. The "any" rule matches any
4117 * non-zero address. The "none" rule matches only the zero address.
4118 * IPv6 addresses supplied by the user are ignored. If the user
4119 * supplies a subnet mask, then match routes that are at least that
4120 * specific (use the user's mask). If the user supplies only an
4121 * address, then select any routes that would match (use the route's
4122 * mask).
4124 static boolean_t
4125 v4_addr_match(IpAddress addr, IpAddress mask, const filter_t *fp)
4127 char **app;
4128 char *aptr;
4129 in_addr_t faddr, fmask;
4131 if (fp->u.a.f_address == NULL) {
4132 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask))
4133 return (addr != INADDR_ANY); /* "any" */
4134 else
4135 return (addr == INADDR_ANY); /* "none" */
4137 if (!IN6_IS_V4MASK(fp->u.a.f_mask))
4138 return (B_FALSE);
4139 IN6_V4MAPPED_TO_IPADDR(&fp->u.a.f_mask, fmask);
4140 if (fmask != IP_HOST_MASK) {
4141 if (fmask > mask)
4142 return (B_FALSE);
4143 mask = fmask;
4145 for (app = fp->u.a.f_address->h_addr_list; (aptr = *app) != NULL; app++)
4146 /* LINTED: (note 1) */
4147 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) {
4148 /* LINTED: (note 1) */
4149 IN6_V4MAPPED_TO_IPADDR((in6_addr_t *)aptr, faddr);
4150 if (((faddr ^ addr) & mask) == 0)
4151 return (B_TRUE);
4153 return (B_FALSE);
4157 * Run through the filter list for an IPv4 MIB2 route entry. If all
4158 * filters of a given type fail to match, then the route is filtered
4159 * out (not displayed). If no filter is given or at least one filter
4160 * of each type matches, then display the route.
4162 static boolean_t
4163 ire_filter_match_v4(const mib2_ipRouteEntry_t *rp, uint_t flag_b)
4165 filter_t *fp;
4166 int idx;
4168 /* 'for' loop 1: */
4169 for (idx = 0; idx < NFILTERKEYS; idx++)
4170 if ((fp = filters[idx]) != NULL) {
4171 /* 'for' loop 2: */
4172 for (; fp != NULL; fp = fp->f_next) {
4173 switch (idx) {
4174 case FK_AF:
4175 if (fp->u.f_family != AF_INET)
4176 continue; /* 'for' loop 2 */
4177 break;
4178 case FK_OUTIF:
4179 if (!dev_name_match(&rp->ipRouteIfIndex,
4180 fp->u.f_ifname))
4181 continue; /* 'for' loop 2 */
4182 break;
4183 case FK_DST:
4184 if (!v4_addr_match(rp->ipRouteDest,
4185 rp->ipRouteMask, fp))
4186 continue; /* 'for' loop 2 */
4187 break;
4188 case FK_FLAGS:
4189 if ((flag_b & fp->u.f.f_flagset) !=
4190 fp->u.f.f_flagset ||
4191 (flag_b & fp->u.f.f_flagclear))
4192 continue; /* 'for' loop 2 */
4193 break;
4195 break;
4196 } /* 'for' loop 2 ends */
4197 if (fp == NULL)
4198 return (B_FALSE);
4200 /* 'for' loop 1 ends */
4201 return (B_TRUE);
4205 * Given an IPv4 MIB2 route entry, form the list of flags for the
4206 * route.
4208 static uint_t
4209 form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags)
4211 uint_t flag_b;
4213 flag_b = FLF_U;
4214 (void) strcpy(flags, "U");
4215 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */
4216 if (rp->ipRouteInfo.re_flags & RTF_INDIRECT) {
4217 (void) strcat(flags, "I");
4218 flag_b |= FLF_I;
4219 } else if (rp->ipRouteInfo.re_ire_type & IRE_OFFLINK) {
4220 (void) strcat(flags, "G");
4221 flag_b |= FLF_G;
4223 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */
4224 if (rp->ipRouteInfo.re_ire_type & IRE_IF_CLONE) {
4225 (void) strcat(flags, "C");
4226 flag_b |= FLF_C;
4227 } else if (rp->ipRouteMask == IP_HOST_MASK) {
4228 (void) strcat(flags, "H");
4229 flag_b |= FLF_H;
4231 if (rp->ipRouteInfo.re_flags & RTF_DYNAMIC) {
4232 (void) strcat(flags, "D");
4233 flag_b |= FLF_D;
4235 if (rp->ipRouteInfo.re_ire_type == IRE_BROADCAST) { /* Broadcast */
4236 (void) strcat(flags, "b");
4237 flag_b |= FLF_b;
4239 if (rp->ipRouteInfo.re_ire_type == IRE_LOCAL) { /* Local */
4240 (void) strcat(flags, "L");
4241 flag_b |= FLF_L;
4243 if (rp->ipRouteInfo.re_flags & RTF_SETSRC) {
4244 (void) strcat(flags, "S"); /* Setsrc */
4245 flag_b |= FLF_S;
4247 if (rp->ipRouteInfo.re_flags & RTF_REJECT) {
4248 (void) strcat(flags, "R");
4249 flag_b |= FLF_R;
4251 if (rp->ipRouteInfo.re_flags & RTF_BLACKHOLE) {
4252 (void) strcat(flags, "B");
4253 flag_b |= FLF_B;
4255 if (rp->ipRouteInfo.re_flags & RTF_ZONE) {
4256 (void) strcat(flags, "Z");
4257 flag_b |= FLF_Z;
4259 return (flag_b);
4262 static const char ire_hdr_v4[] =
4263 "\n%s Table: IPv4\n";
4264 static const char ire_hdr_v4_compat[] =
4265 "\n%s Table:\n";
4266 static const char ire_hdr_v4_verbose[] =
4267 " Destination Mask Gateway Device "
4268 " MTU Ref Flg Out In/Fwd\n"
4269 "-------------------- --------------- -------------------- ------ "
4270 "----- --- --- ----- ------\n";
4272 static const char ire_hdr_v4_normal[] =
4273 " Destination Gateway Flags Ref Use Interface"
4274 "\n-------------------- -------------------- ----- ----- ---------- "
4275 "---------\n";
4277 static boolean_t
4278 ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first)
4280 char dstbuf[MAXHOSTNAMELEN + 4]; /* + "/<num>" */
4281 char maskbuf[MAXHOSTNAMELEN + 1];
4282 char gwbuf[MAXHOSTNAMELEN + 1];
4283 char ifname[LIFNAMSIZ + 1];
4284 char flags[10]; /* RTF_ flags */
4285 uint_t flag_b;
4287 if (!(Aflag || (rp->ipRouteInfo.re_ire_type != IRE_IF_CLONE &&
4288 rp->ipRouteInfo.re_ire_type != IRE_BROADCAST &&
4289 rp->ipRouteInfo.re_ire_type != IRE_MULTICAST &&
4290 rp->ipRouteInfo.re_ire_type != IRE_NOROUTE &&
4291 rp->ipRouteInfo.re_ire_type != IRE_LOCAL))) {
4292 return (first);
4295 flag_b = form_v4_route_flags(rp, flags);
4297 if (!ire_filter_match_v4(rp, flag_b))
4298 return (first);
4300 if (first) {
4301 (void) printf(v4compat ? ire_hdr_v4_compat : ire_hdr_v4,
4302 Vflag ? "IRE" : "Routing");
4303 (void) printf(Vflag ? ire_hdr_v4_verbose : ire_hdr_v4_normal);
4304 first = B_FALSE;
4307 if (flag_b & FLF_H) {
4308 (void) pr_addr(rp->ipRouteDest, dstbuf, sizeof (dstbuf));
4309 } else {
4310 (void) pr_net(rp->ipRouteDest, rp->ipRouteMask,
4311 dstbuf, sizeof (dstbuf));
4313 if (Vflag) {
4314 (void) printf("%-20s %-15s %-20s %-6s %5u %3u "
4315 "%-4s%6u %6u\n",
4316 dstbuf,
4317 pr_mask(rp->ipRouteMask, maskbuf, sizeof (maskbuf)),
4318 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
4319 octetstr(&rp->ipRouteIfIndex, 'a', ifname, sizeof (ifname)),
4320 rp->ipRouteInfo.re_max_frag,
4321 rp->ipRouteInfo.re_ref,
4322 flags,
4323 rp->ipRouteInfo.re_obpkt,
4324 rp->ipRouteInfo.re_ibpkt);
4325 } else {
4326 (void) printf("%-20s %-20s %-5s %4u %10u %-9s\n",
4327 dstbuf,
4328 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
4329 flags,
4330 rp->ipRouteInfo.re_ref,
4331 rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt,
4332 octetstr(&rp->ipRouteIfIndex, 'a',
4333 ifname, sizeof (ifname)));
4335 return (first);
4339 * Match a user-supplied IP address list against an IPv6 route entry.
4340 * If the user specified "any," then any non-zero address matches. If
4341 * the user specified "none," then only the zero address matches. If
4342 * the user specified a subnet mask length, then use that in matching
4343 * routes (select routes that are at least as specific). If the user
4344 * specified only an address, then use the route's mask (select routes
4345 * that would match that address). IPv4 addresses are ignored.
4347 static boolean_t
4348 v6_addr_match(const Ip6Address *addr, int masklen, const filter_t *fp)
4350 const uint8_t *ucp;
4351 int fmasklen;
4352 int i;
4353 char **app;
4354 const uint8_t *aptr;
4356 if (fp->u.a.f_address == NULL) {
4357 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask)) /* any */
4358 return (!IN6_IS_ADDR_UNSPECIFIED(addr));
4359 return (IN6_IS_ADDR_UNSPECIFIED(addr)); /* "none" */
4361 fmasklen = 0;
4362 /* 'for' loop 1a: */
4363 for (ucp = fp->u.a.f_mask.s6_addr;
4364 ucp < fp->u.a.f_mask.s6_addr + sizeof (fp->u.a.f_mask.s6_addr);
4365 ucp++) {
4366 if (*ucp != 0xff) {
4367 if (*ucp != 0)
4368 fmasklen += 9 - ffs(*ucp);
4369 break; /* 'for' loop 1a */
4371 fmasklen += 8;
4372 } /* 'for' loop 1a ends */
4373 if (fmasklen != IPV6_ABITS) {
4374 if (fmasklen > masklen)
4375 return (B_FALSE);
4376 masklen = fmasklen;
4378 /* 'for' loop 1b: */
4379 for (app = fp->u.a.f_address->h_addr_list;
4380 (aptr = (uint8_t *)*app) != NULL; app++) {
4381 /* LINTED: (note 1) */
4382 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr))
4383 continue; /* 'for' loop 1b */
4384 ucp = addr->s6_addr;
4385 for (i = masklen; i >= 8; i -= 8)
4386 if (*ucp++ != *aptr++)
4387 break; /* 'for' loop 1b */
4388 if (i == 0 ||
4389 (i < 8 && ((*ucp ^ *aptr) & ~(0xff >> i)) == 0))
4390 return (B_TRUE);
4391 } /* 'for' loop 1b ends */
4392 return (B_FALSE);
4396 * Run through the filter list for an IPv6 MIB2 IRE. For a given
4397 * type, if there's at least one filter and all filters of that type
4398 * fail to match, then the route doesn't match and isn't displayed.
4399 * If at least one matches, or none are specified, for each of the
4400 * types, then the route is selected and displayed.
4402 static boolean_t
4403 ire_filter_match_v6(const mib2_ipv6RouteEntry_t *rp6, uint_t flag_b)
4405 filter_t *fp;
4406 int idx;
4408 /* 'for' loop 1: */
4409 for (idx = 0; idx < NFILTERKEYS; idx++)
4410 if ((fp = filters[idx]) != NULL) {
4411 /* 'for' loop 2: */
4412 for (; fp != NULL; fp = fp->f_next) {
4413 switch (idx) {
4414 case FK_AF:
4415 if (fp->u.f_family != AF_INET6)
4416 /* 'for' loop 2 */
4417 continue;
4418 break;
4419 case FK_OUTIF:
4420 if (!dev_name_match(&rp6->
4421 ipv6RouteIfIndex, fp->u.f_ifname))
4422 /* 'for' loop 2 */
4423 continue;
4424 break;
4425 case FK_DST:
4426 if (!v6_addr_match(&rp6->ipv6RouteDest,
4427 rp6->ipv6RoutePfxLength, fp))
4428 /* 'for' loop 2 */
4429 continue;
4430 break;
4431 case FK_FLAGS:
4432 if ((flag_b & fp->u.f.f_flagset) !=
4433 fp->u.f.f_flagset ||
4434 (flag_b & fp->u.f.f_flagclear))
4435 /* 'for' loop 2 */
4436 continue;
4437 break;
4439 break;
4440 } /* 'for' loop 2 ends */
4441 if (fp == NULL)
4442 return (B_FALSE);
4444 /* 'for' loop 1 ends */
4445 return (B_TRUE);
4449 * Given an IPv6 MIB2 route entry, form the list of flags for the
4450 * route.
4452 static uint_t
4453 form_v6_route_flags(const mib2_ipv6RouteEntry_t *rp6, char *flags)
4455 uint_t flag_b;
4457 flag_b = FLF_U;
4458 (void) strcpy(flags, "U");
4459 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */
4460 if (rp6->ipv6RouteInfo.re_flags & RTF_INDIRECT) {
4461 (void) strcat(flags, "I");
4462 flag_b |= FLF_I;
4463 } else if (rp6->ipv6RouteInfo.re_ire_type & IRE_OFFLINK) {
4464 (void) strcat(flags, "G");
4465 flag_b |= FLF_G;
4468 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */
4469 if (rp6->ipv6RouteInfo.re_ire_type & IRE_IF_CLONE) {
4470 (void) strcat(flags, "C");
4471 flag_b |= FLF_C;
4472 } else if (rp6->ipv6RoutePfxLength == IPV6_ABITS) {
4473 (void) strcat(flags, "H");
4474 flag_b |= FLF_H;
4477 if (rp6->ipv6RouteInfo.re_flags & RTF_DYNAMIC) {
4478 (void) strcat(flags, "D");
4479 flag_b |= FLF_D;
4481 if (rp6->ipv6RouteInfo.re_ire_type == IRE_LOCAL) { /* Local */
4482 (void) strcat(flags, "L");
4483 flag_b |= FLF_L;
4485 if (rp6->ipv6RouteInfo.re_flags & RTF_SETSRC) {
4486 (void) strcat(flags, "S"); /* Setsrc */
4487 flag_b |= FLF_S;
4489 if (rp6->ipv6RouteInfo.re_flags & RTF_REJECT) {
4490 (void) strcat(flags, "R");
4491 flag_b |= FLF_R;
4493 if (rp6->ipv6RouteInfo.re_flags & RTF_BLACKHOLE) {
4494 (void) strcat(flags, "B");
4495 flag_b |= FLF_B;
4497 if (rp6->ipv6RouteInfo.re_flags & RTF_ZONE) {
4498 (void) strcat(flags, "Z");
4499 flag_b |= FLF_Z;
4501 return (flag_b);
4504 static const char ire_hdr_v6[] =
4505 "\n%s Table: IPv6\n";
4506 static const char ire_hdr_v6_verbose[] =
4507 " Destination/Mask Gateway If MTU "
4508 "Ref Flags Out In/Fwd\n"
4509 "--------------------------- --------------------------- ----- ----- "
4510 "--- ----- ------ ------\n";
4511 static const char ire_hdr_v6_normal[] =
4512 " Destination/Mask Gateway Flags Ref Use "
4513 " If \n"
4514 "--------------------------- --------------------------- ----- --- ------- "
4515 "-----\n";
4517 static boolean_t
4518 ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first)
4520 char dstbuf[MAXHOSTNAMELEN + 1];
4521 char gwbuf[MAXHOSTNAMELEN + 1];
4522 char ifname[LIFNAMSIZ + 1];
4523 char flags[10]; /* RTF_ flags */
4524 uint_t flag_b;
4526 if (!(Aflag || (rp6->ipv6RouteInfo.re_ire_type != IRE_IF_CLONE &&
4527 rp6->ipv6RouteInfo.re_ire_type != IRE_MULTICAST &&
4528 rp6->ipv6RouteInfo.re_ire_type != IRE_NOROUTE &&
4529 rp6->ipv6RouteInfo.re_ire_type != IRE_LOCAL))) {
4530 return (first);
4533 flag_b = form_v6_route_flags(rp6, flags);
4535 if (!ire_filter_match_v6(rp6, flag_b))
4536 return (first);
4538 if (first) {
4539 (void) printf(ire_hdr_v6, Vflag ? "IRE" : "Routing");
4540 (void) printf(Vflag ? ire_hdr_v6_verbose : ire_hdr_v6_normal);
4541 first = B_FALSE;
4544 if (Vflag) {
4545 (void) printf("%-27s %-27s %-5s %5u %3u "
4546 "%-5s %6u %6u\n",
4547 pr_prefix6(&rp6->ipv6RouteDest,
4548 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
4549 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
4550 " --" :
4551 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)),
4552 octetstr(&rp6->ipv6RouteIfIndex, 'a',
4553 ifname, sizeof (ifname)),
4554 rp6->ipv6RouteInfo.re_max_frag,
4555 rp6->ipv6RouteInfo.re_ref,
4556 flags,
4557 rp6->ipv6RouteInfo.re_obpkt,
4558 rp6->ipv6RouteInfo.re_ibpkt);
4559 } else {
4560 (void) printf("%-27s %-27s %-5s %3u %7u %-5s\n",
4561 pr_prefix6(&rp6->ipv6RouteDest,
4562 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
4563 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
4564 " --" :
4565 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)),
4566 flags,
4567 rp6->ipv6RouteInfo.re_ref,
4568 rp6->ipv6RouteInfo.re_obpkt + rp6->ipv6RouteInfo.re_ibpkt,
4569 octetstr(&rp6->ipv6RouteIfIndex, 'a',
4570 ifname, sizeof (ifname)));
4572 return (first);
4575 /* ------------------------------ TCP_REPORT------------------------------- */
4577 static const char tcp_hdr_v4[] =
4578 "\nTCP: IPv4\n";
4579 static const char tcp_hdr_v4_compat[] =
4580 "\nTCP\n";
4581 static const char tcp_hdr_v4_verbose[] =
4582 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack "
4583 " Rto Mss State\n"
4584 "-------------------- ----- -------- -------- ----- -------- -------- "
4585 "----- ----- -----------\n";
4586 static const char tcp_hdr_v4_normal[] =
4587 " Local Address Remote Address Swind Send-Q Rwind Recv-Q "
4588 " State\n"
4589 "-------------------- -------------------- ----- ------ ----- ------ "
4590 "-----------\n";
4592 static const char tcp_hdr_v6[] =
4593 "\nTCP: IPv6\n";
4594 static const char tcp_hdr_v6_verbose[] =
4595 "Local/Remote Address Swind Snext Suna Rwind Rnext "
4596 " Rack Rto Mss State If\n"
4597 "--------------------------------- ----- -------- -------- ----- -------- "
4598 "-------- ----- ----- ----------- -----\n";
4599 static const char tcp_hdr_v6_normal[] =
4600 " Local Address Remote Address "
4601 "Swind Send-Q Rwind Recv-Q State If\n"
4602 "--------------------------------- --------------------------------- "
4603 "----- ------ ----- ------ ----------- -----\n";
4605 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4606 boolean_t first);
4607 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4608 boolean_t first);
4610 static void
4611 tcp_report(const mib_item_t *item)
4613 int jtemp = 0;
4614 boolean_t print_hdr_once_v4 = B_TRUE;
4615 boolean_t print_hdr_once_v6 = B_TRUE;
4616 mib2_tcpConnEntry_t *tp;
4617 mib2_tcp6ConnEntry_t *tp6;
4619 if (!protocol_selected(IPPROTO_TCP))
4620 return;
4622 for (; item != NULL; item = item->next_item) {
4623 if (Xflag) {
4624 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4625 (void) printf("Group = %d, mib_id = %d, "
4626 "length = %d, valp = 0x%p\n",
4627 item->group, item->mib_id,
4628 item->length, item->valp);
4631 if (!((item->group == MIB2_TCP &&
4632 item->mib_id == MIB2_TCP_CONN) ||
4633 (item->group == MIB2_TCP6 &&
4634 item->mib_id == MIB2_TCP6_CONN)))
4635 continue; /* 'for' loop 1 */
4637 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4638 continue; /* 'for' loop 1 */
4639 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4640 continue; /* 'for' loop 1 */
4642 if (item->group == MIB2_TCP) {
4643 for (tp = (mib2_tcpConnEntry_t *)item->valp;
4644 (char *)tp < (char *)item->valp + item->length;
4645 /* LINTED: (note 1) */
4646 tp = (mib2_tcpConnEntry_t *)((char *)tp +
4647 tcpConnEntrySize)) {
4648 print_hdr_once_v4 = tcp_report_item_v4(tp,
4649 print_hdr_once_v4);
4651 } else {
4652 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4653 (char *)tp6 < (char *)item->valp + item->length;
4654 /* LINTED: (note 1) */
4655 tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4656 tcp6ConnEntrySize)) {
4657 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4658 print_hdr_once_v6);
4661 } /* 'for' loop 1 ends */
4662 (void) fflush(stdout);
4666 static boolean_t
4667 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first)
4670 * lname and fname below are for the hostname as well as the portname
4671 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4672 * as the limit
4674 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4675 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4677 if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4678 return (first); /* Nothing to print */
4680 if (first) {
4681 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4682 (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);
4685 if (Vflag) {
4686 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4687 "%5u %5u\n",
4688 pr_ap(tp->tcpConnLocalAddress,
4689 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4690 pr_ap(tp->tcpConnRemAddress,
4691 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4692 tp->tcpConnEntryInfo.ce_swnd,
4693 tp->tcpConnEntryInfo.ce_snxt,
4694 tp->tcpConnEntryInfo.ce_suna,
4695 tp->tcpConnEntryInfo.ce_rwnd,
4696 tp->tcpConnEntryInfo.ce_rnxt,
4697 tp->tcpConnEntryInfo.ce_rack,
4698 tp->tcpConnEntryInfo.ce_rto,
4699 tp->tcpConnEntryInfo.ce_mss,
4700 mitcp_state(tp->tcpConnEntryInfo.ce_state));
4701 } else {
4702 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4703 (int)tp->tcpConnEntryInfo.ce_suna - 1;
4704 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4705 (int)tp->tcpConnEntryInfo.ce_rack;
4707 (void) printf("%-20s %-20s %5u %6d %5u %6d\n",
4708 pr_ap(tp->tcpConnLocalAddress,
4709 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4710 pr_ap(tp->tcpConnRemAddress,
4711 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4712 tp->tcpConnEntryInfo.ce_swnd,
4713 (sq >= 0) ? sq : 0,
4714 tp->tcpConnEntryInfo.ce_rwnd,
4715 (rq >= 0) ? rq : 0,
4716 mitcp_state(tp->tcpConnEntryInfo.ce_state));
4719 return (B_FALSE);
4722 static boolean_t
4723 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first)
4726 * lname and fname below are for the hostname as well as the portname
4727 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4728 * as the limit
4730 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4731 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4732 char ifname[LIFNAMSIZ + 1];
4733 char *ifnamep;
4735 if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4736 return (first); /* Nothing to print */
4738 if (first) {
4739 (void) printf(tcp_hdr_v6);
4740 (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);
4743 ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
4744 if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
4745 if (ifnamep == NULL)
4746 ifnamep = "";
4748 if (Vflag) {
4749 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
4750 "%5u %5u %-11s %s\n",
4751 pr_ap6(&tp6->tcp6ConnLocalAddress,
4752 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4753 pr_ap6(&tp6->tcp6ConnRemAddress,
4754 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4755 tp6->tcp6ConnEntryInfo.ce_swnd,
4756 tp6->tcp6ConnEntryInfo.ce_snxt,
4757 tp6->tcp6ConnEntryInfo.ce_suna,
4758 tp6->tcp6ConnEntryInfo.ce_rwnd,
4759 tp6->tcp6ConnEntryInfo.ce_rnxt,
4760 tp6->tcp6ConnEntryInfo.ce_rack,
4761 tp6->tcp6ConnEntryInfo.ce_rto,
4762 tp6->tcp6ConnEntryInfo.ce_mss,
4763 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
4764 ifnamep);
4765 } else {
4766 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
4767 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
4768 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
4769 (int)tp6->tcp6ConnEntryInfo.ce_rack;
4771 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
4772 pr_ap6(&tp6->tcp6ConnLocalAddress,
4773 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4774 pr_ap6(&tp6->tcp6ConnRemAddress,
4775 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4776 tp6->tcp6ConnEntryInfo.ce_swnd,
4777 (sq >= 0) ? sq : 0,
4778 tp6->tcp6ConnEntryInfo.ce_rwnd,
4779 (rq >= 0) ? rq : 0,
4780 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
4781 ifnamep);
4784 return (B_FALSE);
4787 /* ------------------------------- UDP_REPORT------------------------------- */
4789 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
4790 boolean_t first);
4791 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
4792 boolean_t first);
4794 static const char udp_hdr_v4[] =
4795 " Local Address Remote Address State\n"
4796 "-------------------- -------------------- ----------\n";
4798 static const char udp_hdr_v6[] =
4799 " Local Address Remote Address "
4800 " State If\n"
4801 "--------------------------------- --------------------------------- "
4802 "---------- -----\n";
4804 static void
4805 udp_report(const mib_item_t *item)
4807 int jtemp = 0;
4808 boolean_t print_hdr_once_v4 = B_TRUE;
4809 boolean_t print_hdr_once_v6 = B_TRUE;
4810 mib2_udpEntry_t *ude;
4811 mib2_udp6Entry_t *ude6;
4813 if (!protocol_selected(IPPROTO_UDP))
4814 return;
4816 /* 'for' loop 1: */
4817 for (; item; item = item->next_item) {
4818 if (Xflag) {
4819 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4820 (void) printf("Group = %d, mib_id = %d, "
4821 "length = %d, valp = 0x%p\n",
4822 item->group, item->mib_id,
4823 item->length, item->valp);
4825 if (!((item->group == MIB2_UDP &&
4826 item->mib_id == MIB2_UDP_ENTRY) ||
4827 (item->group == MIB2_UDP6 &&
4828 item->mib_id == MIB2_UDP6_ENTRY)))
4829 continue; /* 'for' loop 1 */
4831 if (item->group == MIB2_UDP && !family_selected(AF_INET))
4832 continue; /* 'for' loop 1 */
4833 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
4834 continue; /* 'for' loop 1 */
4836 /* xxx.xxx.xxx.xxx,pppp sss... */
4837 if (item->group == MIB2_UDP) {
4838 for (ude = (mib2_udpEntry_t *)item->valp;
4839 (char *)ude < (char *)item->valp + item->length;
4840 /* LINTED: (note 1) */
4841 ude = (mib2_udpEntry_t *)((char *)ude +
4842 udpEntrySize)) {
4843 print_hdr_once_v4 = udp_report_item_v4(ude,
4844 print_hdr_once_v4);
4846 } else {
4847 for (ude6 = (mib2_udp6Entry_t *)item->valp;
4848 (char *)ude6 < (char *)item->valp + item->length;
4849 /* LINTED: (note 1) */
4850 ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
4851 udp6EntrySize)) {
4852 print_hdr_once_v6 = udp_report_item_v6(ude6,
4853 print_hdr_once_v6);
4856 } /* 'for' loop 1 ends */
4857 (void) fflush(stdout);
4860 static boolean_t
4861 udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first)
4863 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4864 /* hostname + portname */
4866 if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
4867 return (first); /* Nothing to print */
4869 if (first) {
4870 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
4871 (void) printf(udp_hdr_v4);
4872 first = B_FALSE;
4875 (void) printf("%-20s ",
4876 pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
4877 lname, sizeof (lname)));
4878 (void) printf("%-20s %s\n",
4879 ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
4880 pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
4881 ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
4883 miudp_state(ude->udpEntryInfo.ue_state));
4885 return (first);
4888 static boolean_t
4889 udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first)
4891 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4892 /* hostname + portname */
4893 char ifname[LIFNAMSIZ + 1];
4894 const char *ifnamep;
4896 if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
4897 return (first); /* Nothing to print */
4899 if (first) {
4900 (void) printf("\nUDP: IPv6\n");
4901 (void) printf(udp_hdr_v6);
4902 first = B_FALSE;
4905 ifnamep = (ude6->udp6IfIndex != 0) ?
4906 if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
4908 (void) printf("%-33s ",
4909 pr_ap6(&ude6->udp6LocalAddress,
4910 ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
4911 (void) printf("%-33s %-10s %s\n",
4912 ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
4913 pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
4914 ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
4916 miudp_state(ude6->udp6EntryInfo.ue_state),
4917 ifnamep == NULL ? "" : ifnamep);
4919 return (first);
4922 /* ------------------------------ SCTP_REPORT------------------------------- */
4924 static const char sctp_hdr[] =
4925 "\nSCTP:";
4926 static const char sctp_hdr_normal[] =
4927 " Local Address Remote Address "
4928 "Swind Send-Q Rwind Recv-Q StrsI/O State\n"
4929 "------------------------------- ------------------------------- "
4930 "------ ------ ------ ------ ------- -----------";
4932 static const char *
4933 nssctp_state(int state)
4935 static char sctpsbuf[50];
4936 const char *cp;
4938 switch (state) {
4939 case MIB2_SCTP_closed:
4940 cp = "CLOSED";
4941 break;
4942 case MIB2_SCTP_cookieWait:
4943 cp = "COOKIE_WAIT";
4944 break;
4945 case MIB2_SCTP_cookieEchoed:
4946 cp = "COOKIE_ECHOED";
4947 break;
4948 case MIB2_SCTP_established:
4949 cp = "ESTABLISHED";
4950 break;
4951 case MIB2_SCTP_shutdownPending:
4952 cp = "SHUTDOWN_PENDING";
4953 break;
4954 case MIB2_SCTP_shutdownSent:
4955 cp = "SHUTDOWN_SENT";
4956 break;
4957 case MIB2_SCTP_shutdownReceived:
4958 cp = "SHUTDOWN_RECEIVED";
4959 break;
4960 case MIB2_SCTP_shutdownAckSent:
4961 cp = "SHUTDOWN_ACK_SENT";
4962 break;
4963 case MIB2_SCTP_listen:
4964 cp = "LISTEN";
4965 break;
4966 default:
4967 (void) snprintf(sctpsbuf, sizeof (sctpsbuf),
4968 "UNKNOWN STATE(%d)", state);
4969 cp = sctpsbuf;
4970 break;
4973 return (cp);
4976 static const mib2_sctpConnRemoteEntry_t *
4977 sctp_getnext_rem(const mib_item_t **itemp,
4978 const mib2_sctpConnRemoteEntry_t *current, uint32_t associd)
4980 const mib_item_t *item = *itemp;
4981 const mib2_sctpConnRemoteEntry_t *sre;
4983 for (; item != NULL; item = item->next_item, current = NULL) {
4984 if (!(item->group == MIB2_SCTP &&
4985 item->mib_id == MIB2_SCTP_CONN_REMOTE)) {
4986 continue;
4989 if (current != NULL) {
4990 /* LINTED: (note 1) */
4991 sre = (const mib2_sctpConnRemoteEntry_t *)
4992 ((const char *)current + sctpRemoteEntrySize);
4993 } else {
4994 sre = item->valp;
4996 for (; (char *)sre < (char *)item->valp + item->length;
4997 /* LINTED: (note 1) */
4998 sre = (const mib2_sctpConnRemoteEntry_t *)
4999 ((const char *)sre + sctpRemoteEntrySize)) {
5000 if (sre->sctpAssocId != associd) {
5001 continue;
5003 *itemp = item;
5004 return (sre);
5007 *itemp = NULL;
5008 return (NULL);
5011 static const mib2_sctpConnLocalEntry_t *
5012 sctp_getnext_local(const mib_item_t **itemp,
5013 const mib2_sctpConnLocalEntry_t *current, uint32_t associd)
5015 const mib_item_t *item = *itemp;
5016 const mib2_sctpConnLocalEntry_t *sle;
5018 for (; item != NULL; item = item->next_item, current = NULL) {
5019 if (!(item->group == MIB2_SCTP &&
5020 item->mib_id == MIB2_SCTP_CONN_LOCAL)) {
5021 continue;
5024 if (current != NULL) {
5025 /* LINTED: (note 1) */
5026 sle = (const mib2_sctpConnLocalEntry_t *)
5027 ((const char *)current + sctpLocalEntrySize);
5028 } else {
5029 sle = item->valp;
5031 for (; (char *)sle < (char *)item->valp + item->length;
5032 /* LINTED: (note 1) */
5033 sle = (const mib2_sctpConnLocalEntry_t *)
5034 ((const char *)sle + sctpLocalEntrySize)) {
5035 if (sle->sctpAssocId != associd) {
5036 continue;
5038 *itemp = item;
5039 return (sle);
5042 *itemp = NULL;
5043 return (NULL);
5046 static void
5047 sctp_pr_addr(int type, char *name, int namelen, const in6_addr_t *addr,
5048 int port)
5050 ipaddr_t v4addr;
5051 in6_addr_t v6addr;
5054 * Address is either a v4 mapped or v6 addr. If
5055 * it's a v4 mapped, convert to v4 before
5056 * displaying.
5058 switch (type) {
5059 case MIB2_SCTP_ADDR_V4:
5060 /* v4 */
5061 v6addr = *addr;
5063 IN6_V4MAPPED_TO_IPADDR(&v6addr, v4addr);
5064 if (port > 0) {
5065 (void) pr_ap(v4addr, port, "sctp", name, namelen);
5066 } else {
5067 (void) pr_addr(v4addr, name, namelen);
5069 break;
5071 case MIB2_SCTP_ADDR_V6:
5072 /* v6 */
5073 if (port > 0) {
5074 (void) pr_ap6(addr, port, "sctp", name, namelen);
5075 } else {
5076 (void) pr_addr6(addr, name, namelen);
5078 break;
5080 default:
5081 (void) snprintf(name, namelen, "<unknown addr type>");
5082 break;
5086 static void
5087 sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp)
5089 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5090 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5091 const mib2_sctpConnRemoteEntry_t *sre = NULL;
5092 const mib2_sctpConnLocalEntry_t *sle = NULL;
5093 const mib_item_t *local = head;
5094 const mib_item_t *remote = head;
5095 uint32_t id = sp->sctpAssocId;
5096 boolean_t printfirst = B_TRUE;
5098 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5099 &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5100 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5101 &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5103 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5104 lname, fname,
5105 sp->sctpConnEntryInfo.ce_swnd,
5106 sp->sctpConnEntryInfo.ce_sendq,
5107 sp->sctpConnEntryInfo.ce_rwnd,
5108 sp->sctpConnEntryInfo.ce_recvq,
5109 sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5110 nssctp_state(sp->sctpAssocState));
5112 if (!Vflag) {
5113 return;
5116 /* Print remote addresses/local addresses on following lines */
5117 while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5118 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5119 &sp->sctpAssocRemPrimAddr)) {
5120 if (printfirst == B_TRUE) {
5121 (void) fputs("\t<Remote: ", stdout);
5122 printfirst = B_FALSE;
5123 } else {
5124 (void) fputs(", ", stdout);
5126 sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5127 sizeof (fname), &sre->sctpAssocRemAddr, -1);
5128 if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5129 (void) fputs(fname, stdout);
5130 } else {
5131 (void) printf("(%s)", fname);
5135 if (printfirst == B_FALSE) {
5136 (void) puts(">");
5137 printfirst = B_TRUE;
5139 while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5140 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5141 &sp->sctpAssocLocPrimAddr)) {
5142 if (printfirst == B_TRUE) {
5143 (void) fputs("\t<Local: ", stdout);
5144 printfirst = B_FALSE;
5145 } else {
5146 (void) fputs(", ", stdout);
5148 sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5149 sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5150 (void) fputs(lname, stdout);
5153 if (printfirst == B_FALSE) {
5154 (void) puts(">");
5158 static void
5159 sctp_report(const mib_item_t *item)
5161 const mib_item_t *head;
5162 const mib2_sctpConnEntry_t *sp;
5163 boolean_t first = B_TRUE;
5165 head = item;
5166 for (; item != NULL; item = item->next_item) {
5168 if (!(item->group == MIB2_SCTP &&
5169 item->mib_id == MIB2_SCTP_CONN))
5170 continue;
5172 for (sp = item->valp;
5173 (char *)sp < (char *)item->valp + item->length;
5174 /* LINTED: (note 1) */
5175 sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
5176 if (Aflag ||
5177 sp->sctpAssocState >= MIB2_SCTP_established) {
5178 if (first == B_TRUE) {
5179 (void) puts(sctp_hdr);
5180 (void) puts(sctp_hdr_normal);
5181 first = B_FALSE;
5183 sctp_conn_report_item(head, sp);
5189 static char *
5190 plural(int n)
5192 return (n != 1 ? "s" : "");
5195 static char *
5196 pluraly(int n)
5198 return (n != 1 ? "ies" : "y");
5201 static char *
5202 plurales(int n)
5204 return (n != 1 ? "es" : "");
5207 static char *
5208 pktscale(int n)
5210 static char buf[6];
5211 char t;
5213 if (n < 1024) {
5214 t = ' ';
5215 } else if (n < 1024 * 1024) {
5216 t = 'k';
5217 n /= 1024;
5218 } else if (n < 1024 * 1024 * 1024) {
5219 t = 'm';
5220 n /= 1024 * 1024;
5221 } else {
5222 t = 'g';
5223 n /= 1024 * 1024 * 1024;
5226 (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5227 return (buf);
5230 /* --------------------- mrt_report (netstat -m) -------------------------- */
5232 static void
5233 mrt_report(mib_item_t *item)
5235 int jtemp = 0;
5236 struct vifctl *vip;
5237 vifi_t vifi;
5238 struct mfcctl *mfccp;
5239 int numvifs = 0;
5240 int nmfc = 0;
5241 char abuf[MAXHOSTNAMELEN + 4]; /* Include CIDR /<num>. */
5243 if (!(family_selected(AF_INET)))
5244 return;
5246 /* 'for' loop 1: */
5247 for (; item; item = item->next_item) {
5248 if (Xflag) {
5249 (void) printf("\n--- Entry %d ---\n", ++jtemp);
5250 (void) printf("Group = %d, mib_id = %d, "
5251 "length = %d, valp = 0x%p\n",
5252 item->group, item->mib_id, item->length,
5253 item->valp);
5255 if (item->group != EXPER_DVMRP)
5256 continue; /* 'for' loop 1 */
5258 switch (item->mib_id) {
5260 case EXPER_DVMRP_VIF:
5261 if (Xflag)
5262 (void) printf("%u records for ipVifTable:\n",
5263 item->length/sizeof (struct vifctl));
5264 if (item->length/sizeof (struct vifctl) == 0) {
5265 (void) puts("\nVirtual Interface Table is "
5266 "empty");
5267 break;
5270 (void) puts("\nVirtual Interface Table\n"
5271 " Vif Threshold Rate_Limit Local-Address"
5272 " Remote-Address Pkt_in Pkt_out");
5274 /* 'for' loop 2: */
5275 for (vip = (struct vifctl *)item->valp;
5276 (char *)vip < (char *)item->valp + item->length;
5277 /* LINTED: (note 1) */
5278 vip = (struct vifctl *)((char *)vip +
5279 vifctlSize)) {
5280 if (vip->vifc_lcl_addr.s_addr == 0)
5281 continue; /* 'for' loop 2 */
5282 /* numvifs = vip->vifc_vifi; */
5284 numvifs++;
5285 (void) printf(" %2u %3u "
5286 "%4u %-15.15s",
5287 vip->vifc_vifi,
5288 vip->vifc_threshold,
5289 vip->vifc_rate_limit,
5290 pr_addr(vip->vifc_lcl_addr.s_addr,
5291 abuf, sizeof (abuf)));
5292 (void) printf(" %-15.15s %8u %8u\n",
5293 (vip->vifc_flags & VIFF_TUNNEL) ?
5294 pr_addr(vip->vifc_rmt_addr.s_addr,
5295 abuf, sizeof (abuf)) : "",
5296 vip->vifc_pkt_in,
5297 vip->vifc_pkt_out);
5298 } /* 'for' loop 2 ends */
5300 (void) printf("Numvifs: %d\n", numvifs);
5301 break;
5303 case EXPER_DVMRP_MRT:
5304 if (Xflag)
5305 (void) printf("%u records for ipMfcTable:\n",
5306 item->length/sizeof (struct vifctl));
5307 if (item->length/sizeof (struct vifctl) == 0) {
5308 (void) puts("\nMulticast Forwarding Cache is "
5309 "empty");
5310 break;
5313 (void) puts("\nMulticast Forwarding Cache\n"
5314 " Origin-Subnet Mcastgroup "
5315 "# Pkts In-Vif Out-vifs/Forw-ttl");
5317 for (mfccp = (struct mfcctl *)item->valp;
5318 (char *)mfccp < (char *)item->valp + item->length;
5319 /* LINTED: (note 1) */
5320 mfccp = (struct mfcctl *)((char *)mfccp +
5321 mfcctlSize)) {
5323 nmfc++;
5324 (void) printf(" %-30.15s",
5325 pr_addr(mfccp->mfcc_origin.s_addr,
5326 abuf, sizeof (abuf)));
5327 (void) printf("%-15.15s %6s %3u ",
5328 pr_net(mfccp->mfcc_mcastgrp.s_addr,
5329 mfccp->mfcc_mcastgrp.s_addr,
5330 abuf, sizeof (abuf)),
5331 pktscale((int)mfccp->mfcc_pkt_cnt),
5332 mfccp->mfcc_parent);
5334 for (vifi = 0; vifi < MAXVIFS; ++vifi) {
5335 if (mfccp->mfcc_ttls[vifi]) {
5336 (void) printf(" %u (%u)",
5337 vifi,
5338 mfccp->mfcc_ttls[vifi]);
5342 (void) putchar('\n');
5344 (void) printf("\nTotal no. of entries in cache: %d\n",
5345 nmfc);
5346 break;
5348 } /* 'for' loop 1 ends */
5349 (void) putchar('\n');
5350 (void) fflush(stdout);
5354 * Get the stats for the cache named 'name'. If prefix != 0, then
5355 * interpret the name as a prefix, and sum up stats for all caches
5356 * named 'name*'.
5358 static void
5359 kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes)
5361 int len;
5362 int alloc;
5363 int64_t total_alloc = 0;
5364 int alloc_fail, total_alloc_fail = 0;
5365 int buf_size = 0;
5366 int buf_avail;
5367 int buf_total;
5368 int buf_max, total_buf_max = 0;
5369 int buf_inuse, total_buf_inuse = 0;
5370 kstat_t *ksp;
5371 char buf[256];
5373 len = prefix ? strlen(name) : 256;
5375 /* 'for' loop 1: */
5376 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
5378 if (strcmp(ksp->ks_class, "kmem_cache") != 0)
5379 continue; /* 'for' loop 1 */
5382 * Hack alert: because of the way streams messages are
5383 * allocated, every constructed free dblk has an associated
5384 * mblk. From the allocator's viewpoint those mblks are
5385 * allocated (because they haven't been freed), but from
5386 * our viewpoint they're actually free (because they're
5387 * not currently in use). To account for this caching
5388 * effect we subtract the total constructed free dblks
5389 * from the total allocated mblks to derive mblks in use.
5391 if (strcmp(name, "streams_mblk") == 0 &&
5392 strncmp(ksp->ks_name, "streams_dblk", 12) == 0) {
5393 (void) safe_kstat_read(kc, ksp, NULL);
5394 total_buf_inuse -=
5395 kstat_named_value(ksp, "buf_constructed");
5396 continue; /* 'for' loop 1 */
5399 if (strncmp(ksp->ks_name, name, len) != 0)
5400 continue; /* 'for' loop 1 */
5402 (void) safe_kstat_read(kc, ksp, NULL);
5404 alloc = kstat_named_value(ksp, "alloc");
5405 alloc_fail = kstat_named_value(ksp, "alloc_fail");
5406 buf_size = kstat_named_value(ksp, "buf_size");
5407 buf_avail = kstat_named_value(ksp, "buf_avail");
5408 buf_total = kstat_named_value(ksp, "buf_total");
5409 buf_max = kstat_named_value(ksp, "buf_max");
5410 buf_inuse = buf_total - buf_avail;
5412 if (Vflag && prefix) {
5413 (void) snprintf(buf, sizeof (buf), "%s%s", title,
5414 ksp->ks_name + len);
5415 (void) printf(" %-18s %6u %9u %11u %11u\n",
5416 buf, buf_inuse, buf_max, alloc, alloc_fail);
5419 total_alloc += alloc;
5420 total_alloc_fail += alloc_fail;
5421 total_buf_max += buf_max;
5422 total_buf_inuse += buf_inuse;
5423 *total_bytes += (int64_t)buf_inuse * buf_size;
5424 } /* 'for' loop 1 ends */
5426 if (buf_size == 0) {
5427 (void) printf("%-22s [couldn't find statistics for %s]\n",
5428 title, name);
5429 return;
5432 if (Vflag && prefix)
5433 (void) snprintf(buf, sizeof (buf), "%s_total", title);
5434 else
5435 (void) snprintf(buf, sizeof (buf), "%s", title);
5437 (void) printf("%-22s %6d %9d %11lld %11d\n", buf,
5438 total_buf_inuse, total_buf_max, total_alloc, total_alloc_fail);
5441 static void
5442 m_report(void)
5444 int64_t total_bytes = 0;
5446 (void) puts("streams allocation:");
5447 (void) printf("%63s\n", "cumulative allocation");
5448 (void) printf("%63s\n",
5449 "current maximum total failures");
5451 kmem_cache_stats("streams",
5452 "stream_head_cache", 0, &total_bytes);
5453 kmem_cache_stats("queues", "queue_cache", 0, &total_bytes);
5454 kmem_cache_stats("mblk", "streams_mblk", 0, &total_bytes);
5455 kmem_cache_stats("dblk", "streams_dblk", 1, &total_bytes);
5456 kmem_cache_stats("linkblk", "linkinfo_cache", 0, &total_bytes);
5457 kmem_cache_stats("syncq", "syncq_cache", 0, &total_bytes);
5458 kmem_cache_stats("qband", "qband_cache", 0, &total_bytes);
5460 (void) printf("\n%lld Kbytes allocated for streams data\n",
5461 total_bytes / 1024);
5463 (void) putchar('\n');
5464 (void) fflush(stdout);
5467 /* --------------------------------- */
5470 * Print an IPv4 address. Remove the matching part of the domain name
5471 * from the returned name.
5473 static char *
5474 pr_addr(uint_t addr, char *dst, uint_t dstlen)
5476 char *cp;
5477 struct hostent *hp = NULL;
5478 static char domain[MAXHOSTNAMELEN + 1];
5479 static boolean_t first = B_TRUE;
5480 int error_num;
5482 if (first) {
5483 first = B_FALSE;
5484 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 &&
5485 (cp = strchr(domain, '.'))) {
5486 (void) strncpy(domain, cp + 1, sizeof (domain));
5487 } else
5488 domain[0] = 0;
5490 cp = NULL;
5491 if (!Nflag) {
5492 ns_lookup_start();
5493 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t), AF_INET,
5494 &error_num);
5495 ns_lookup_end();
5496 if (hp) {
5497 if ((cp = strchr(hp->h_name, '.')) != NULL &&
5498 strcasecmp(cp + 1, domain) == 0)
5499 *cp = 0;
5500 cp = hp->h_name;
5503 if (cp != NULL) {
5504 (void) strncpy(dst, cp, dstlen);
5505 dst[dstlen - 1] = 0;
5506 } else {
5507 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
5509 if (hp != NULL)
5510 freehostent(hp);
5511 return (dst);
5515 * Print a non-zero IPv4 address. Print " --" if the address is zero.
5517 static char *
5518 pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen)
5520 if (addr == INADDR_ANY) {
5521 (void) strlcpy(dst, " --", dstlen);
5522 return (dst);
5524 return (pr_addr(addr, dst, dstlen));
5528 * Print an IPv6 address. Remove the matching part of the domain name
5529 * from the returned name.
5531 static char *
5532 pr_addr6(const struct in6_addr *addr, char *dst, uint_t dstlen)
5534 char *cp;
5535 struct hostent *hp = NULL;
5536 static char domain[MAXHOSTNAMELEN + 1];
5537 static boolean_t first = B_TRUE;
5538 int error_num;
5540 if (first) {
5541 first = B_FALSE;
5542 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 &&
5543 (cp = strchr(domain, '.'))) {
5544 (void) strncpy(domain, cp + 1, sizeof (domain));
5545 } else
5546 domain[0] = 0;
5548 cp = NULL;
5549 if (!Nflag) {
5550 ns_lookup_start();
5551 hp = getipnodebyaddr((char *)addr,
5552 sizeof (struct in6_addr), AF_INET6, &error_num);
5553 ns_lookup_end();
5554 if (hp) {
5555 if ((cp = strchr(hp->h_name, '.')) != NULL &&
5556 strcasecmp(cp + 1, domain) == 0)
5557 *cp = 0;
5558 cp = hp->h_name;
5561 if (cp != NULL) {
5562 (void) strncpy(dst, cp, dstlen);
5563 dst[dstlen - 1] = 0;
5564 } else {
5565 (void) inet_ntop(AF_INET6, (void *)addr, dst, dstlen);
5567 if (hp != NULL)
5568 freehostent(hp);
5569 return (dst);
5572 /* For IPv4 masks */
5573 static char *
5574 pr_mask(uint_t addr, char *dst, uint_t dstlen)
5576 uint8_t *ip_addr = (uint8_t *)&addr;
5578 (void) snprintf(dst, dstlen, "%d.%d.%d.%d",
5579 ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
5580 return (dst);
5584 * For ipv6 masks format is : dest/mask
5585 * Does not print /128 to save space in printout. H flag carries this notion.
5587 static char *
5588 pr_prefix6(const struct in6_addr *addr, uint_t prefixlen, char *dst,
5589 uint_t dstlen)
5591 char *cp;
5593 if (IN6_IS_ADDR_UNSPECIFIED(addr) && prefixlen == 0) {
5594 (void) strncpy(dst, "default", dstlen);
5595 dst[dstlen - 1] = 0;
5596 return (dst);
5599 (void) pr_addr6(addr, dst, dstlen);
5600 if (prefixlen != IPV6_ABITS) {
5601 /* How much room is left? */
5602 cp = strchr(dst, '\0');
5603 if (dst + dstlen > cp) {
5604 dstlen -= (cp - dst);
5605 (void) snprintf(cp, dstlen, "/%d", prefixlen);
5608 return (dst);
5611 /* Print IPv4 address and port */
5612 static char *
5613 pr_ap(uint_t addr, uint_t port, char *proto,
5614 char *dst, uint_t dstlen)
5616 char *cp;
5618 if (addr == INADDR_ANY) {
5619 (void) strncpy(dst, " *", dstlen);
5620 dst[dstlen - 1] = 0;
5621 } else {
5622 (void) pr_addr(addr, dst, dstlen);
5624 /* How much room is left? */
5625 cp = strchr(dst, '\0');
5626 if (dst + dstlen > cp + 1) {
5627 *cp++ = '.';
5628 dstlen -= (cp - dst);
5629 dstlen--;
5630 (void) portname(port, proto, cp, dstlen);
5632 return (dst);
5635 /* Print IPv6 address and port */
5636 static char *
5637 pr_ap6(const in6_addr_t *addr, uint_t port, char *proto,
5638 char *dst, uint_t dstlen)
5640 char *cp;
5642 if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
5643 (void) strncpy(dst, " *", dstlen);
5644 dst[dstlen - 1] = 0;
5645 } else {
5646 (void) pr_addr6(addr, dst, dstlen);
5648 /* How much room is left? */
5649 cp = strchr(dst, '\0');
5650 if (dst + dstlen + 1 > cp) {
5651 *cp++ = '.';
5652 dstlen -= (cp - dst);
5653 dstlen--;
5654 (void) portname(port, proto, cp, dstlen);
5656 return (dst);
5660 * Returns -2 to indicate a discontiguous mask. Otherwise returns between
5661 * 0 and 32.
5663 static int
5664 v4_cidr_len(uint_t mask)
5666 int rc = 0;
5667 int i;
5669 for (i = 0; i < 32; i++) {
5670 if (mask & 0x1)
5671 rc++;
5672 else if (rc > 0)
5673 return (-2); /* Discontiguous IPv4 netmask. */
5675 mask >>= 1;
5678 return (rc);
5681 static void
5682 append_v4_cidr_len(char *dst, uint_t dstlen, int prefixlen)
5684 char *prefixptr;
5686 /* 4 bytes leaves room for '/' 'N' 'N' '\0' */
5687 if (strlen(dst) <= dstlen - 4) {
5688 prefixptr = dst + strlen(dst);
5689 } else {
5691 * Cut off last 3 chars of very-long DNS name. All callers
5692 * should give us enough room, but name services COULD give us
5693 * a way-too-big name (see above).
5695 prefixptr = dst + strlen(dst) - 3;
5697 /* At this point "prefixptr" is guaranteed to point to 4 bytes. */
5699 if (prefixlen >= 0) {
5700 if (prefixlen > 32) /* Shouldn't happen, but... */
5701 prefixlen = 32;
5702 (void) snprintf(prefixptr, 4, "/%d", prefixlen);
5703 } else if (prefixlen == -2) {
5704 /* "/NM" == Noncontiguous Mask. */
5705 (void) strcat(prefixptr, "/NM");
5707 /* Else print nothing extra. */
5711 * Return the name of the network whose address is given. The address is
5712 * assumed to be that of a net or subnet, not a host.
5714 static char *
5715 pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
5717 char *cp = NULL;
5718 struct netent *np = NULL;
5719 struct hostent *hp = NULL;
5720 uint_t net;
5721 int subnetshift;
5722 int error_num;
5723 int prefixlen = -1; /* -1 == Don't print prefix! */
5724 /* -2 == Noncontiguous mask... */
5726 if (addr == INADDR_ANY && mask == INADDR_ANY) {
5727 (void) strlcpy(dst, "default", dstlen);
5728 return (dst);
5731 if (CIDRflag)
5732 prefixlen = v4_cidr_len(ntohl(mask));
5734 if (!Nflag && addr) {
5735 if (mask == 0) {
5736 if (IN_CLASSA(addr)) {
5737 mask = (uint_t)IN_CLASSA_NET;
5738 subnetshift = 8;
5739 } else if (IN_CLASSB(addr)) {
5740 mask = (uint_t)IN_CLASSB_NET;
5741 subnetshift = 8;
5742 } else {
5743 mask = (uint_t)IN_CLASSC_NET;
5744 subnetshift = 4;
5747 * If there are more bits than the standard mask
5748 * would suggest, subnets must be in use. Guess at
5749 * the subnet mask, assuming reasonable width subnet
5750 * fields.
5752 while (addr & ~mask)
5753 /* compiler doesn't sign extend! */
5754 mask = (mask | ((int)mask >> subnetshift));
5755 if (CIDRflag)
5756 prefixlen = v4_cidr_len(mask);
5758 net = addr & mask;
5759 while ((mask & 1) == 0)
5760 mask >>= 1, net >>= 1;
5761 ns_lookup_start();
5762 np = getnetbyaddr(net, AF_INET);
5763 ns_lookup_end();
5764 if (np && np->n_net == net)
5765 cp = np->n_name;
5766 else {
5768 * Look for subnets in hosts map.
5770 ns_lookup_start();
5771 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t),
5772 AF_INET, &error_num);
5773 ns_lookup_end();
5774 if (hp)
5775 cp = hp->h_name;
5778 if (cp != NULL) {
5779 (void) strlcpy(dst, cp, dstlen);
5780 } else {
5781 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
5784 append_v4_cidr_len(dst, dstlen, prefixlen);
5786 if (hp != NULL)
5787 freehostent(hp);
5788 return (dst);
5792 * Return the name of the network whose address is given.
5793 * The address is assumed to be a host address.
5795 static char *
5796 pr_netaddr(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
5798 char *cp = NULL;
5799 struct netent *np = NULL;
5800 struct hostent *hp = NULL;
5801 uint_t net;
5802 uint_t netshifted;
5803 int subnetshift;
5804 struct in_addr in;
5805 int error_num;
5806 uint_t nbo_addr = addr; /* network byte order */
5807 int prefixlen = -1; /* -1 == Don't print prefix! */
5808 /* -2 == Noncontiguous mask... */
5810 addr = ntohl(addr);
5811 mask = ntohl(mask);
5812 if (addr == INADDR_ANY && mask == INADDR_ANY) {
5813 (void) strlcpy(dst, "default", dstlen);
5814 return (dst);
5817 if (CIDRflag)
5818 prefixlen = v4_cidr_len(mask);
5820 /* Figure out network portion of address (with host portion = 0) */
5821 if (addr) {
5822 /* Try figuring out mask if unknown (all 0s). */
5823 if (mask == 0) {
5824 if (IN_CLASSA(addr)) {
5825 mask = (uint_t)IN_CLASSA_NET;
5826 subnetshift = 8;
5827 } else if (IN_CLASSB(addr)) {
5828 mask = (uint_t)IN_CLASSB_NET;
5829 subnetshift = 8;
5830 } else {
5831 mask = (uint_t)IN_CLASSC_NET;
5832 subnetshift = 4;
5835 * If there are more bits than the standard mask
5836 * would suggest, subnets must be in use. Guess at
5837 * the subnet mask, assuming reasonable width subnet
5838 * fields.
5840 while (addr & ~mask)
5841 /* compiler doesn't sign extend! */
5842 mask = (mask | ((int)mask >> subnetshift));
5843 if (CIDRflag)
5844 prefixlen = v4_cidr_len(mask);
5846 net = netshifted = addr & mask;
5847 while ((mask & 1) == 0)
5848 mask >>= 1, netshifted >>= 1;
5850 else
5851 net = netshifted = 0;
5853 /* Try looking up name unless -n was specified. */
5854 if (!Nflag) {
5855 ns_lookup_start();
5856 np = getnetbyaddr(netshifted, AF_INET);
5857 ns_lookup_end();
5858 if (np && np->n_net == netshifted)
5859 cp = np->n_name;
5860 else {
5862 * Look for subnets in hosts map.
5864 ns_lookup_start();
5865 hp = getipnodebyaddr((char *)&nbo_addr, sizeof (uint_t),
5866 AF_INET, &error_num);
5867 ns_lookup_end();
5868 if (hp)
5869 cp = hp->h_name;
5872 if (cp != NULL) {
5873 (void) strlcpy(dst, cp, dstlen);
5874 append_v4_cidr_len(dst, dstlen, prefixlen);
5875 if (hp != NULL)
5876 freehostent(hp);
5877 return (dst);
5880 * No name found for net: fallthru and return in decimal
5881 * dot notation.
5885 in.s_addr = htonl(net);
5886 (void) inet_ntop(AF_INET, (char *)&in, dst, dstlen);
5887 append_v4_cidr_len(dst, dstlen, prefixlen);
5888 if (hp != NULL)
5889 freehostent(hp);
5890 return (dst);
5894 * Return the filter mode as a string:
5895 * 1 => "INCLUDE"
5896 * 2 => "EXCLUDE"
5897 * otherwise "<unknown>"
5899 static char *
5900 fmodestr(uint_t fmode)
5902 switch (fmode) {
5903 case 1:
5904 return ("INCLUDE");
5905 case 2:
5906 return ("EXCLUDE");
5907 default:
5908 return ("<unknown>");
5912 #define MAX_STRING_SIZE 256
5915 * Pretty print a port number. If the Nflag was
5916 * specified, use numbers instead of names.
5918 static char *
5919 portname(uint_t port, char *proto, char *dst, uint_t dstlen)
5921 struct servent *sp = NULL;
5923 if (!Nflag && port) {
5924 ns_lookup_start();
5925 sp = getservbyport(htons(port), proto);
5926 ns_lookup_end();
5928 if (sp || port == 0)
5929 (void) snprintf(dst, dstlen, "%.*s", MAXHOSTNAMELEN,
5930 sp ? sp->s_name : "*");
5931 else
5932 (void) snprintf(dst, dstlen, "%d", port);
5933 dst[dstlen - 1] = 0;
5934 return (dst);
5937 /*PRINTFLIKE2*/
5938 void
5939 fail(int do_perror, char *message, ...)
5941 va_list args;
5943 va_start(args, message);
5944 (void) fputs("netstat: ", stderr);
5945 (void) vfprintf(stderr, message, args);
5946 va_end(args);
5947 if (do_perror)
5948 (void) fprintf(stderr, ": %s", strerror(errno));
5949 (void) fputc('\n', stderr);
5950 exit(2);
5954 * Return value of named statistic for given kstat_named kstat;
5955 * return 0LL if named statistic is not in list (use "ll" as a
5956 * type qualifier when printing 64-bit int's with printf() )
5958 static uint64_t
5959 kstat_named_value(kstat_t *ksp, char *name)
5961 kstat_named_t *knp;
5962 uint64_t value;
5964 if (ksp == NULL)
5965 return (0LL);
5967 knp = kstat_data_lookup(ksp, name);
5968 if (knp == NULL)
5969 return (0LL);
5971 switch (knp->data_type) {
5972 case KSTAT_DATA_INT32:
5973 case KSTAT_DATA_UINT32:
5974 value = (uint64_t)(knp->value.ui32);
5975 break;
5976 case KSTAT_DATA_INT64:
5977 case KSTAT_DATA_UINT64:
5978 value = knp->value.ui64;
5979 break;
5980 default:
5981 value = 0LL;
5982 break;
5985 return (value);
5988 kid_t
5989 safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
5991 kid_t kstat_chain_id = kstat_read(kc, ksp, data);
5993 if (kstat_chain_id == -1)
5994 fail(1, "kstat_read(%p, '%s') failed", (void *)kc,
5995 ksp->ks_name);
5996 return (kstat_chain_id);
6000 * Parse a list of IRE flag characters into a bit field.
6002 static uint_t
6003 flag_bits(const char *arg)
6005 const char *cp;
6006 uint_t val;
6008 if (*arg == '\0')
6009 fatal(1, "missing flag list\n");
6011 val = 0;
6012 while (*arg != '\0') {
6013 if ((cp = strchr(flag_list, *arg)) == NULL)
6014 fatal(1, "%c: illegal flag\n", *arg);
6015 val |= 1 << (cp - flag_list);
6016 arg++;
6018 return (val);
6022 * Handle -f argument. Validate input format, sort by keyword, and
6023 * save off digested results.
6025 static void
6026 process_filter(char *arg)
6028 int idx;
6029 int klen = 0;
6030 char *cp, *cp2;
6031 int val;
6032 filter_t *newf;
6033 struct hostent *hp;
6034 int error_num;
6035 uint8_t *ucp;
6036 int maxv;
6038 /* Look up the keyword first */
6039 if (strchr(arg, ':') == NULL) {
6040 idx = FK_AF;
6041 } else {
6042 for (idx = 0; idx < NFILTERKEYS; idx++) {
6043 klen = strlen(filter_keys[idx]);
6044 if (strncmp(filter_keys[idx], arg, klen) == 0 &&
6045 arg[klen] == ':')
6046 break;
6048 if (idx >= NFILTERKEYS)
6049 fatal(1, "%s: unknown filter keyword\n", arg);
6051 /* Advance past keyword and separator. */
6052 arg += klen + 1;
6055 if ((newf = malloc(sizeof (*newf))) == NULL) {
6056 perror("filter");
6057 exit(1);
6059 switch (idx) {
6060 case FK_AF:
6061 if (strcmp(arg, "inet") == 0) {
6062 newf->u.f_family = AF_INET;
6063 } else if (strcmp(arg, "inet6") == 0) {
6064 newf->u.f_family = AF_INET6;
6065 } else if (strcmp(arg, "unix") == 0) {
6066 newf->u.f_family = AF_UNIX;
6067 } else {
6068 newf->u.f_family = strtol(arg, &cp, 0);
6069 if (arg == cp || *cp != '\0')
6070 fatal(1, "%s: unknown address family.\n", arg);
6072 break;
6074 case FK_OUTIF:
6075 if (strcmp(arg, "none") == 0) {
6076 newf->u.f_ifname = NULL;
6077 break;
6079 if (strcmp(arg, "any") == 0) {
6080 newf->u.f_ifname = "";
6081 break;
6083 val = strtol(arg, &cp, 0);
6084 if (val <= 0 || arg == cp || cp[0] != '\0') {
6085 if ((val = if_nametoindex(arg)) == 0) {
6086 perror(arg);
6087 exit(1);
6090 newf->u.f_ifname = arg;
6091 break;
6093 case FK_DST:
6094 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask);
6095 if (strcmp(arg, "any") == 0) {
6096 /* Special semantics; any address *but* zero */
6097 newf->u.a.f_address = NULL;
6098 (void) memset(&newf->u.a.f_mask, 0,
6099 sizeof (newf->u.a.f_mask));
6100 break;
6102 if (strcmp(arg, "none") == 0) {
6103 newf->u.a.f_address = NULL;
6104 break;
6106 if ((cp = strrchr(arg, '/')) != NULL)
6107 *cp++ = '\0';
6108 hp = getipnodebyname(arg, AF_INET6, AI_V4MAPPED|AI_ALL,
6109 &error_num);
6110 if (hp == NULL)
6111 fatal(1, "%s: invalid or unknown host address\n", arg);
6112 newf->u.a.f_address = hp;
6113 if (cp == NULL) {
6114 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask);
6115 } else {
6116 val = strtol(cp, &cp2, 0);
6117 if (cp != cp2 && cp2[0] == '\0') {
6119 * If decode as "/n" works, then translate
6120 * into a mask.
6122 if (hp->h_addr_list[0] != NULL &&
6123 /* LINTED: (note 1) */
6124 IN6_IS_ADDR_V4MAPPED((in6_addr_t *)
6125 hp->h_addr_list[0])) {
6126 maxv = IP_ABITS;
6127 } else {
6128 maxv = IPV6_ABITS;
6130 if (val < 0 || val >= maxv)
6131 fatal(1, "%d: not in range 0 to %d\n",
6132 val, maxv - 1);
6133 if (maxv == IP_ABITS)
6134 val += IPV6_ABITS - IP_ABITS;
6135 ucp = newf->u.a.f_mask.s6_addr;
6136 while (val >= 8)
6137 *ucp++ = 0xff, val -= 8;
6138 *ucp++ = (0xff << (8 - val)) & 0xff;
6139 while (ucp < newf->u.a.f_mask.s6_addr +
6140 sizeof (newf->u.a.f_mask.s6_addr))
6141 *ucp++ = 0;
6142 /* Otherwise, try as numeric address */
6143 } else if (inet_pton(AF_INET6,
6144 cp, &newf->u.a.f_mask) <= 0) {
6145 fatal(1, "%s: illegal mask format\n", cp);
6148 break;
6150 case FK_FLAGS:
6151 if (*arg == '+') {
6152 newf->u.f.f_flagset = flag_bits(arg + 1);
6153 newf->u.f.f_flagclear = 0;
6154 } else if (*arg == '-') {
6155 newf->u.f.f_flagset = 0;
6156 newf->u.f.f_flagclear = flag_bits(arg + 1);
6157 } else {
6158 newf->u.f.f_flagset = flag_bits(arg);
6159 newf->u.f.f_flagclear = ~newf->u.f.f_flagset;
6161 break;
6163 default:
6164 assert(0);
6166 newf->f_next = filters[idx];
6167 filters[idx] = newf;
6170 /* Determine if user wants this address family printed. */
6171 static boolean_t
6172 family_selected(int family)
6174 const filter_t *fp;
6176 if (v4compat && family == AF_INET6)
6177 return (B_FALSE);
6178 if ((fp = filters[FK_AF]) == NULL)
6179 return (B_TRUE);
6180 while (fp != NULL) {
6181 if (fp->u.f_family == family)
6182 return (B_TRUE);
6183 fp = fp->f_next;
6185 return (B_FALSE);
6189 * Convert the interface index to a string using the buffer `ifname', which
6190 * must be at least LIFNAMSIZ bytes. We first try to map it to name. If that
6191 * fails (e.g., because we're inside a zone and it does not have access to
6192 * interface for the index in question), just return "if#<num>".
6194 static char *
6195 ifindex2str(uint_t ifindex, char *ifname)
6197 if (if_indextoname(ifindex, ifname) == NULL)
6198 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6200 return (ifname);
6204 * print the usage line
6206 static void
6207 usage(char *cmdname)
6209 (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] "
6210 "[-T d|u]\n", cmdname);
6211 (void) fprintf(stderr, " %s [-n] [-f address_family] "
6212 "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6213 cmdname);
6214 (void) fprintf(stderr, " %s -m [-v] [-T d|u] "
6215 "[interval [count]]\n", cmdname);
6216 (void) fprintf(stderr, " %s -i [-I interface] [-an] "
6217 "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6218 (void) fprintf(stderr, " %s -r [-anv] "
6219 "[-f address_family|filter] [-T d|u]\n", cmdname);
6220 (void) fprintf(stderr, " %s -M [-ns] [-f address_family] "
6221 "[-T d|u]\n", cmdname);
6222 (void) fprintf(stderr, " %s -D [-I interface] "
6223 "[-f address_family] [-T d|u]\n", cmdname);
6224 exit(EXIT_FAILURE);
6228 * fatal: print error message to stderr and
6229 * call exit(errcode)
6231 /*PRINTFLIKE2*/
6232 static void
6233 fatal(int errcode, char *format, ...)
6235 va_list argp;
6237 if (format == NULL)
6238 return;
6240 va_start(argp, format);
6241 (void) vfprintf(stderr, format, argp);
6242 va_end(argp);
6244 exit(errcode);