dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / netstat / netstat.c
blobf0ccea89daf0e5ec45567f305f47784e27e23aa0
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
29 * simple netstat based on snmp/mib-2 interface to the TCP/IP stack
31 * NOTES:
32 * 1. A comment "LINTED: (note 1)" appears before certain lines where
33 * lint would have complained, "pointer cast may result in improper
34 * alignment". These are lines where lint had suspected potential
35 * improper alignment of a data structure; in each such situation
36 * we have relied on the kernel guaranteeing proper alignment.
37 * 2. Some 'for' loops have been commented as "'for' loop 1", etc
38 * because they have 'continue' or 'break' statements in their
39 * bodies. 'continue' statements have been used inside some loops
40 * where avoiding them would have led to deep levels of indentation.
42 * TODO:
43 * Add ability to request subsets from kernel (with level = MIB2_IP;
44 * name = 0 meaning everything for compatibility)
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stdarg.h>
50 #include <unistd.h>
51 #include <strings.h>
52 #include <string.h>
53 #include <errno.h>
54 #include <ctype.h>
55 #include <kstat.h>
56 #include <assert.h>
57 #include <locale.h>
59 #include <sys/types.h>
60 #include <sys/stream.h>
61 #include <stropts.h>
62 #include <sys/strstat.h>
63 #include <sys/tihdr.h>
65 #include <sys/socket.h>
66 #include <sys/sockio.h>
67 #include <netinet/in.h>
68 #include <net/if.h>
69 #include <net/route.h>
71 #include <inet/mib2.h>
72 #include <inet/ip.h>
73 #include <inet/arp.h>
74 #include <inet/tcp.h>
75 #include <netinet/igmp_var.h>
76 #include <netinet/ip_mroute.h>
78 #include <arpa/inet.h>
79 #include <netdb.h>
80 #include <fcntl.h>
81 #include <sys/systeminfo.h>
82 #include <arpa/inet.h>
84 #include <netinet/dhcp.h>
85 #include <dhcpagent_ipc.h>
86 #include <dhcpagent_util.h>
87 #include <compat.h>
89 #include "statcommon.h"
91 extern void unixpr(kstat_ctl_t *kc);
93 #define STR_EXPAND 4
95 #define V4MASK_TO_V6(v4, v6) ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
96 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \
97 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \
98 (v6)._S6_un._S6_u32[3] = (v4))
100 #define IN6_IS_V4MASK(v6) ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
101 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \
102 (v6)._S6_un._S6_u32[2] == 0xfffffffful)
105 * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
106 * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
107 * possible for an administrator to plumb new interfaces between those two
108 * calls, resulting in the failure of the latter. This addition makes that
109 * less likely.
111 #define LIFN_GUARD_VALUE 10
113 typedef struct mib_item_s {
114 struct mib_item_s *next_item;
115 int group;
116 int mib_id;
117 int length;
118 void *valp;
119 } mib_item_t;
121 struct ifstat {
122 uint64_t ipackets;
123 uint64_t ierrors;
124 uint64_t opackets;
125 uint64_t oerrors;
126 uint64_t collisions;
129 struct iflist {
130 struct iflist *next_if;
131 char ifname[LIFNAMSIZ];
132 struct ifstat tot;
135 static mib_item_t *mibget(int sd);
136 static void mibfree(mib_item_t *firstitem);
137 static int mibopen(void);
138 static void mib_get_constants(mib_item_t *item);
139 static mib_item_t *mib_item_dup(mib_item_t *item);
140 static mib_item_t *mib_item_diff(mib_item_t *item1,
141 mib_item_t *item2);
142 static void mib_item_destroy(mib_item_t **item);
144 static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b);
145 static char *octetstr(const Octet_t *op, int code,
146 char *dst, uint_t dstlen);
147 static char *pr_addr(uint_t addr,
148 char *dst, uint_t dstlen);
149 static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
150 static char *pr_addr6(const in6_addr_t *addr,
151 char *dst, uint_t dstlen);
152 static char *pr_mask(uint_t addr,
153 char *dst, uint_t dstlen);
154 static char *pr_prefix6(const struct in6_addr *addr,
155 uint_t prefixlen, char *dst, uint_t dstlen);
156 static char *pr_ap(uint_t addr, uint_t port,
157 char *proto, char *dst, uint_t dstlen);
158 static char *pr_ap6(const in6_addr_t *addr, uint_t port,
159 char *proto, char *dst, uint_t dstlen);
160 static char *pr_net(uint_t addr, uint_t mask,
161 char *dst, uint_t dstlen);
162 static char *pr_netaddr(uint_t addr, uint_t mask,
163 char *dst, uint_t dstlen);
164 static char *fmodestr(uint_t fmode);
165 static char *portname(uint_t port, char *proto,
166 char *dst, uint_t dstlen);
168 static const char *mitcp_state(int code);
169 static const char *miudp_state(int code);
171 static void stat_report(mib_item_t *item);
172 static void mrt_stat_report(mib_item_t *item);
173 static void arp_report(mib_item_t *item);
174 static void ndp_report(mib_item_t *item);
175 static void mrt_report(mib_item_t *item);
176 static void if_stat_total(struct ifstat *oldstats,
177 struct ifstat *newstats, struct ifstat *sumstats);
178 static void if_report(mib_item_t *item, char *ifname,
179 int Iflag_only, boolean_t once_only);
180 static void if_report_ip4(mib2_ipAddrEntry_t *ap,
181 char ifname[], char logintname[],
182 struct ifstat *statptr, boolean_t ksp_not_null);
183 static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
184 char ifname[], char logintname[],
185 struct ifstat *statptr, boolean_t ksp_not_null);
186 static void ire_report(const mib_item_t *item);
187 static void tcp_report(const mib_item_t *item);
188 static void udp_report(const mib_item_t *item);
189 static void group_report(mib_item_t *item);
190 static void dce_report(mib_item_t *item);
191 static void print_ip_stats(mib2_ip_t *ip);
192 static void print_icmp_stats(mib2_icmp_t *icmp);
193 static void print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
194 static void print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
195 static void print_sctp_stats(mib2_sctp_t *tcp);
196 static void print_tcp_stats(mib2_tcp_t *tcp);
197 static void print_udp_stats(mib2_udp_t *udp);
198 static void print_rawip_stats(mib2_rawip_t *rawip);
199 static void print_igmp_stats(struct igmpstat *igps);
200 static void print_mrt_stats(struct mrtstat *mrts);
201 static void sctp_report(const mib_item_t *item);
202 static void sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
203 mib2_ipv6IfStatsEntry_t *sum6);
204 static void sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
205 mib2_ipv6IfIcmpEntry_t *sum6);
206 static void m_report(void);
207 static void dhcp_report(char *);
209 static uint64_t kstat_named_value(kstat_t *, char *);
210 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
211 static int isnum(char *);
212 static char *plural(int n);
213 static char *pluraly(int n);
214 static char *plurales(int n);
215 static void process_filter(char *arg);
216 static char *ifindex2str(uint_t, char *);
217 static boolean_t family_selected(int family);
219 static void usage(char *);
220 static void fatal(int errcode, char *str1, ...);
222 #define PLURAL(n) plural((int)n)
223 #define PLURALY(n) pluraly((int)n)
224 #define PLURALES(n) plurales((int)n)
225 #define IFLAGMOD(flg, val1, val2) if (flg == val1) flg = val2
226 #define MDIFF(diff, elem2, elem1, member) (diff)->member = \
227 (elem2)->member - (elem1)->member
230 static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */
231 static boolean_t Dflag = B_FALSE; /* DCE info */
232 static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */
233 static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */
234 static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */
235 static boolean_t Rflag = B_FALSE; /* Routing Tables */
236 static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */
237 static boolean_t Vflag = B_FALSE; /* Verbose */
238 static boolean_t Pflag = B_FALSE; /* Net to Media Tables */
239 static boolean_t Gflag = B_FALSE; /* Multicast group membership */
240 static boolean_t MMflag = B_FALSE; /* Multicast routing table */
241 static boolean_t DHCPflag = B_FALSE; /* DHCP statistics */
242 static boolean_t Xflag = B_FALSE; /* Debug Info */
244 static int v4compat = 0; /* Compatible printing format for status */
246 static int proto = IPPROTO_MAX; /* all protocols */
247 kstat_ctl_t *kc = NULL;
250 * Sizes of data structures extracted from the base mib.
251 * This allows the size of the tables entries to grow while preserving
252 * binary compatibility.
254 static int ipAddrEntrySize;
255 static int ipRouteEntrySize;
256 static int ipNetToMediaEntrySize;
257 static int ipMemberEntrySize;
258 static int ipGroupSourceEntrySize;
259 static int vifctlSize;
260 static int mfcctlSize;
262 static int ipv6IfStatsEntrySize;
263 static int ipv6IfIcmpEntrySize;
264 static int ipv6AddrEntrySize;
265 static int ipv6RouteEntrySize;
266 static int ipv6NetToMediaEntrySize;
267 static int ipv6MemberEntrySize;
268 static int ipv6GroupSourceEntrySize;
270 static int ipDestEntrySize;
272 static int tcpConnEntrySize;
273 static int tcp6ConnEntrySize;
274 static int udpEntrySize;
275 static int udp6EntrySize;
276 static int sctpEntrySize;
277 static int sctpLocalEntrySize;
278 static int sctpRemoteEntrySize;
280 #define protocol_selected(p) (proto == IPPROTO_MAX || proto == (p))
282 /* Machinery used for -f (filter) option */
283 enum { FK_AF = 0, FK_OUTIF, FK_DST, FK_FLAGS, NFILTERKEYS };
285 static const char *filter_keys[NFILTERKEYS] = {
286 "af", "outif", "dst", "flags"
289 /* Flags on routes */
290 #define FLF_A 0x00000001
291 #define FLF_b 0x00000002
292 #define FLF_D 0x00000004
293 #define FLF_G 0x00000008
294 #define FLF_H 0x00000010
295 #define FLF_L 0x00000020
296 #define FLF_U 0x00000040
297 #define FLF_S 0x00000100
298 #define FLF_C 0x00000200 /* IRE_IF_CLONE */
299 #define FLF_I 0x00000400 /* RTF_INDIRECT */
300 #define FLF_R 0x00000800 /* RTF_REJECT */
301 #define FLF_B 0x00001000 /* RTF_BLACKHOLE */
302 #define FLF_Z 0x00100000 /* RTF_ZONE */
304 static const char flag_list[] = "AbDGHLUMSCIRBZ";
306 typedef struct filter_rule filter_t;
308 struct filter_rule {
309 filter_t *f_next;
310 union {
311 int f_family;
312 const char *f_ifname;
313 struct {
314 struct hostent *f_address;
315 in6_addr_t f_mask;
316 } a;
317 struct {
318 uint_t f_flagset;
319 uint_t f_flagclear;
320 } f;
321 } u;
325 * The user-specified filters are linked into lists separated by
326 * keyword (type of filter). Thus, the matching algorithm is:
327 * For each non-empty filter list
328 * If no filters in the list match
329 * then stop here; route doesn't match
330 * If loop above completes, then route does match and will be
331 * displayed.
333 static filter_t *filters[NFILTERKEYS];
335 static uint_t timestamp_fmt = NODATE;
337 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
338 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't */
339 #endif
342 main(int argc, char **argv)
344 char *name;
345 mib_item_t *item = NULL;
346 mib_item_t *previtem = NULL;
347 int sd = -1;
348 char *ifname = NULL;
349 int interval = 0; /* Single time by default */
350 int count = -1; /* Forever */
351 int c;
352 int d;
354 * Possible values of 'Iflag_only':
355 * -1, no feature-flags;
356 * 0, IFlag and other feature-flags enabled
357 * 1, IFlag is the only feature-flag enabled
358 * : trinary variable, modified using IFLAGMOD()
360 int Iflag_only = -1;
361 boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
362 extern char *optarg;
363 extern int optind;
364 char *default_ip_str = NULL;
366 name = argv[0];
368 v4compat = get_compat_flag(&default_ip_str);
369 if (v4compat == DEFAULT_PROT_BAD_VALUE)
370 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
371 default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
372 free(default_ip_str);
374 (void) setlocale(LC_ALL, "");
375 (void) textdomain(TEXT_DOMAIN);
377 while ((c = getopt(argc, argv, "adimnrspMgvxf:P:I:DT:")) != -1) {
378 switch ((char)c) {
379 case 'a': /* all connections */
380 Aflag = B_TRUE;
381 break;
383 case 'd': /* DCE info */
384 Dflag = B_TRUE;
385 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
386 break;
388 case 'i': /* interface (ill/ipif report) */
389 Iflag = B_TRUE;
390 IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
391 break;
393 case 'm': /* streams msg report */
394 Mflag = B_TRUE;
395 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
396 break;
398 case 'n': /* numeric format */
399 Nflag = B_TRUE;
400 break;
402 case 'r': /* route tables */
403 Rflag = B_TRUE;
404 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
405 break;
407 case 's': /* per-protocol statistics */
408 Sflag = B_TRUE;
409 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
410 break;
412 case 'p': /* arp/ndp table */
413 Pflag = B_TRUE;
414 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
415 break;
417 case 'M': /* multicast routing tables */
418 MMflag = B_TRUE;
419 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
420 break;
422 case 'g': /* multicast group membership */
423 Gflag = B_TRUE;
424 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
425 break;
427 case 'v': /* verbose output format */
428 Vflag = B_TRUE;
429 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
430 break;
432 case 'x': /* turn on debugging */
433 Xflag = B_TRUE;
434 break;
436 case 'f':
437 process_filter(optarg);
438 break;
440 case 'P':
441 if (strcmp(optarg, "ip") == 0) {
442 proto = IPPROTO_IP;
443 } else if (strcmp(optarg, "ipv6") == 0 ||
444 strcmp(optarg, "ip6") == 0) {
445 v4compat = 0; /* Overridden */
446 proto = IPPROTO_IPV6;
447 } else if (strcmp(optarg, "icmp") == 0) {
448 proto = IPPROTO_ICMP;
449 } else if (strcmp(optarg, "icmpv6") == 0 ||
450 strcmp(optarg, "icmp6") == 0) {
451 v4compat = 0; /* Overridden */
452 proto = IPPROTO_ICMPV6;
453 } else if (strcmp(optarg, "igmp") == 0) {
454 proto = IPPROTO_IGMP;
455 } else if (strcmp(optarg, "udp") == 0) {
456 proto = IPPROTO_UDP;
457 } else if (strcmp(optarg, "tcp") == 0) {
458 proto = IPPROTO_TCP;
459 } else if (strcmp(optarg, "sctp") == 0) {
460 proto = IPPROTO_SCTP;
461 } else if (strcmp(optarg, "raw") == 0 ||
462 strcmp(optarg, "rawip") == 0) {
463 proto = IPPROTO_RAW;
464 } else {
465 fatal(1, "%s: unknown protocol.\n", optarg);
467 break;
469 case 'I':
470 ifname = optarg;
471 Iflag = B_TRUE;
472 IFLAGMOD(Iflag_only, -1, 1); /* see macro def'n */
473 break;
475 case 'D':
476 DHCPflag = B_TRUE;
477 Iflag_only = 0;
478 break;
480 case 'T':
481 if (optarg) {
482 if (*optarg == 'u')
483 timestamp_fmt = UDATE;
484 else if (*optarg == 'd')
485 timestamp_fmt = DDATE;
486 else
487 usage(name);
488 } else {
489 usage(name);
491 break;
493 case '?':
494 default:
495 usage(name);
500 * Handle other arguments: find interval, count; the
501 * flags that accept 'interval' and 'count' are OR'd
502 * in the outermost 'if'; more flags may be added as
503 * required
505 if (Iflag || Sflag || Mflag) {
506 for (d = optind; d < argc; d++) {
507 if (isnum(argv[d])) {
508 interval = atoi(argv[d]);
509 if (d + 1 < argc &&
510 isnum(argv[d + 1])) {
511 count = atoi(argv[d + 1]);
512 optind++;
514 optind++;
515 if (interval == 0 || count == 0)
516 usage(name);
517 break;
521 if (optind < argc) {
522 if (Iflag && isnum(argv[optind])) {
523 count = atoi(argv[optind]);
524 if (count == 0)
525 usage(name);
526 optind++;
529 if (optind < argc) {
530 (void) fprintf(stderr,
531 "%s: extra arguments\n", name);
532 usage(name);
534 if (interval)
535 setbuf(stdout, NULL);
537 if (DHCPflag) {
538 dhcp_report(Iflag ? ifname : NULL);
539 exit(0);
542 /* Get data structures: priming before iteration */
543 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
544 sd = mibopen();
545 if (sd == -1)
546 fatal(1, "can't open mib stream\n");
547 if ((item = mibget(sd)) == NULL) {
548 (void) close(sd);
549 fatal(1, "mibget() failed\n");
551 /* Extract constant sizes - need do once only */
552 mib_get_constants(item);
554 if ((kc = kstat_open()) == NULL) {
555 mibfree(item);
556 (void) close(sd);
557 fail(1, "kstat_open(): can't open /dev/kstat");
560 if (interval <= 0) {
561 count = 1;
562 once_only = B_TRUE;
564 /* 'for' loop 1: */
565 for (;;) {
566 mib_item_t *curritem = NULL; /* only for -[M]s */
568 if (timestamp_fmt != NODATE)
569 print_timestamp(timestamp_fmt);
571 /* netstat: AF_INET[6] behaviour */
572 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
573 if (Sflag) {
574 curritem = mib_item_diff(previtem, item);
575 if (curritem == NULL)
576 fatal(1, "can't process mib data, "
577 "out of memory\n");
578 mib_item_destroy(&previtem);
581 if (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
582 MMflag || Pflag || Gflag || DHCPflag)) {
583 if (protocol_selected(IPPROTO_UDP))
584 udp_report(item);
585 if (protocol_selected(IPPROTO_TCP))
586 tcp_report(item);
587 if (protocol_selected(IPPROTO_SCTP))
588 sctp_report(item);
590 if (Iflag)
591 if_report(item, ifname, Iflag_only, once_only);
592 if (Mflag)
593 m_report();
594 if (Rflag)
595 ire_report(item);
596 if (Sflag && MMflag) {
597 mrt_stat_report(curritem);
598 } else {
599 if (Sflag)
600 stat_report(curritem);
601 if (MMflag)
602 mrt_report(item);
604 if (Gflag)
605 group_report(item);
606 if (Pflag) {
607 if (family_selected(AF_INET))
608 arp_report(item);
609 if (family_selected(AF_INET6))
610 ndp_report(item);
612 if (Dflag)
613 dce_report(item);
614 mib_item_destroy(&curritem);
617 /* netstat: AF_UNIX behaviour */
618 if (family_selected(AF_UNIX) &&
619 (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
620 MMflag || Pflag || Gflag)))
621 unixpr(kc);
622 (void) kstat_close(kc);
624 /* iteration handling code */
625 if (count > 0 && --count == 0)
626 break;
627 (void) sleep(interval);
629 /* re-populating of data structures */
630 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
631 if (Sflag) {
632 /* previtem is a cut-down list */
633 previtem = mib_item_dup(item);
634 if (previtem == NULL)
635 fatal(1, "can't process mib data, "
636 "out of memory\n");
638 mibfree(item);
639 (void) close(sd);
640 if ((sd = mibopen()) == -1)
641 fatal(1, "can't open mib stream anymore\n");
642 if ((item = mibget(sd)) == NULL) {
643 (void) close(sd);
644 fatal(1, "mibget() failed\n");
647 if ((kc = kstat_open()) == NULL)
648 fail(1, "kstat_open(): can't open /dev/kstat");
650 } /* 'for' loop 1 ends */
651 mibfree(item);
652 (void) close(sd);
653 return (0);
657 static int
658 isnum(char *p)
660 int len;
661 int i;
663 len = strlen(p);
664 for (i = 0; i < len; i++)
665 if (!isdigit(p[i]))
666 return (0);
667 return (1);
671 /* --------------------------------- MIBGET -------------------------------- */
673 static mib_item_t *
674 mibget(int sd)
677 * buf is an automatic for this function, so the
678 * compiler has complete control over its alignment;
679 * it is assumed this alignment is satisfactory for
680 * it to be casted to certain other struct pointers
681 * here, such as struct T_optmgmt_ack * .
683 uintptr_t buf[512 / sizeof (uintptr_t)];
684 int flags;
685 int i, j, getcode;
686 struct strbuf ctlbuf, databuf;
687 struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
688 struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
689 struct T_error_ack *tea = (struct T_error_ack *)buf;
690 struct opthdr *req;
691 mib_item_t *first_item = NULL;
692 mib_item_t *last_item = NULL;
693 mib_item_t *temp;
695 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
696 tor->OPT_offset = sizeof (struct T_optmgmt_req);
697 tor->OPT_length = sizeof (struct opthdr);
698 tor->MGMT_flags = T_CURRENT;
702 * Note: we use the special level value below so that IP will return
703 * us information concerning IRE_MARK_TESTHIDDEN routes.
705 req = (struct opthdr *)&tor[1];
706 req->level = EXPER_IP_AND_ALL_IRES;
707 req->name = 0;
708 req->len = 1;
710 ctlbuf.buf = (char *)buf;
711 ctlbuf.len = tor->OPT_length + tor->OPT_offset;
712 flags = 0;
713 if (putmsg(sd, &ctlbuf, NULL, flags) == -1) {
714 perror("mibget: putmsg(ctl) failed");
715 goto error_exit;
719 * Each reply consists of a ctl part for one fixed structure
720 * or table, as defined in mib2.h. The format is a T_OPTMGMT_ACK,
721 * containing an opthdr structure. level/name identify the entry,
722 * len is the size of the data part of the message.
724 req = (struct opthdr *)&toa[1];
725 ctlbuf.maxlen = sizeof (buf);
726 j = 1;
727 for (;;) {
728 flags = 0;
729 getcode = getmsg(sd, &ctlbuf, NULL, &flags);
730 if (getcode == -1) {
731 perror("mibget getmsg(ctl) failed");
732 if (Xflag) {
733 (void) fputs("# level name len\n",
734 stderr);
735 i = 0;
736 for (last_item = first_item; last_item;
737 last_item = last_item->next_item)
738 (void) printf("%d %4d %5d %d\n",
739 ++i,
740 last_item->group,
741 last_item->mib_id,
742 last_item->length);
744 goto error_exit;
746 if (getcode == 0 &&
747 ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
748 toa->PRIM_type == T_OPTMGMT_ACK &&
749 toa->MGMT_flags == T_SUCCESS &&
750 req->len == 0) {
751 if (Xflag)
752 (void) printf("mibget getmsg() %d returned "
753 "EOD (level %ld, name %ld)\n",
754 j, req->level, req->name);
755 return (first_item); /* this is EOD msg */
758 if (ctlbuf.len >= sizeof (struct T_error_ack) &&
759 tea->PRIM_type == T_ERROR_ACK) {
760 (void) fprintf(stderr,
761 "mibget %d gives T_ERROR_ACK: TLI_error = 0x%lx, "
762 "UNIX_error = 0x%lx\n",
763 j, tea->TLI_error, tea->UNIX_error);
765 errno = (tea->TLI_error == TSYSERR) ?
766 tea->UNIX_error : EPROTO;
767 goto error_exit;
770 if (getcode != MOREDATA ||
771 ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
772 toa->PRIM_type != T_OPTMGMT_ACK ||
773 toa->MGMT_flags != T_SUCCESS) {
774 (void) printf("mibget getmsg(ctl) %d returned %d, "
775 "ctlbuf.len = %d, PRIM_type = %ld\n",
776 j, getcode, ctlbuf.len, toa->PRIM_type);
778 if (toa->PRIM_type == T_OPTMGMT_ACK)
779 (void) printf("T_OPTMGMT_ACK: "
780 "MGMT_flags = 0x%lx, req->len = %ld\n",
781 toa->MGMT_flags, req->len);
782 errno = ENOMSG;
783 goto error_exit;
786 temp = (mib_item_t *)malloc(sizeof (mib_item_t));
787 if (temp == NULL) {
788 perror("mibget malloc failed");
789 goto error_exit;
791 if (last_item != NULL)
792 last_item->next_item = temp;
793 else
794 first_item = temp;
795 last_item = temp;
796 last_item->next_item = NULL;
797 last_item->group = req->level;
798 last_item->mib_id = req->name;
799 last_item->length = req->len;
800 last_item->valp = malloc((int)req->len);
801 if (last_item->valp == NULL)
802 goto error_exit;
803 if (Xflag)
804 (void) printf("msg %d: group = %4d mib_id = %5d"
805 "length = %d\n",
806 j, last_item->group, last_item->mib_id,
807 last_item->length);
809 databuf.maxlen = last_item->length;
810 databuf.buf = (char *)last_item->valp;
811 databuf.len = 0;
812 flags = 0;
813 getcode = getmsg(sd, NULL, &databuf, &flags);
814 if (getcode == -1) {
815 perror("mibget getmsg(data) failed");
816 goto error_exit;
817 } else if (getcode != 0) {
818 (void) printf("mibget getmsg(data) returned %d, "
819 "databuf.maxlen = %d, databuf.len = %d\n",
820 getcode, databuf.maxlen, databuf.len);
821 goto error_exit;
823 j++;
825 /* NOTREACHED */
827 error_exit:;
828 mibfree(first_item);
829 return (NULL);
833 * mibfree: frees a linked list of type (mib_item_t *)
834 * returned by mibget(); this is NOT THE SAME AS
835 * mib_item_destroy(), so should be used for objects
836 * returned by mibget() only
838 static void
839 mibfree(mib_item_t *firstitem)
841 mib_item_t *lastitem;
843 while (firstitem != NULL) {
844 lastitem = firstitem;
845 firstitem = firstitem->next_item;
846 free(lastitem->valp);
847 free(lastitem);
851 static int
852 mibopen(void)
854 int sd;
856 sd = open("/dev/arp", O_RDWR);
857 if (sd == -1) {
858 perror("arp open");
859 return (-1);
861 if (ioctl(sd, I_PUSH, "tcp") == -1) {
862 perror("tcp I_PUSH");
863 (void) close(sd);
864 return (-1);
866 if (ioctl(sd, I_PUSH, "udp") == -1) {
867 perror("udp I_PUSH");
868 (void) close(sd);
869 return (-1);
871 if (ioctl(sd, I_PUSH, "icmp") == -1) {
872 perror("icmp I_PUSH");
873 (void) close(sd);
874 return (-1);
876 return (sd);
880 * mib_item_dup: returns a clean mib_item_t * linked
881 * list, so that for every element item->mib_id is 0;
882 * to deallocate this linked list, use mib_item_destroy
884 static mib_item_t *
885 mib_item_dup(mib_item_t *item)
887 int c = 0;
888 mib_item_t *localp;
889 mib_item_t *tempp;
891 for (tempp = item; tempp; tempp = tempp->next_item)
892 if (tempp->mib_id == 0)
893 c++;
894 tempp = NULL;
896 localp = (mib_item_t *)malloc(c * sizeof (mib_item_t));
897 if (localp == NULL)
898 return (NULL);
899 c = 0;
900 for (; item; item = item->next_item) {
901 if (item->mib_id == 0) {
902 /* Replicate item in localp */
903 (localp[c]).next_item = NULL;
904 (localp[c]).group = item->group;
905 (localp[c]).mib_id = item->mib_id;
906 (localp[c]).length = item->length;
907 (localp[c]).valp = (uintptr_t *)malloc(
908 item->length);
909 if ((localp[c]).valp == NULL) {
910 mib_item_destroy(&localp);
911 return (NULL);
913 (void *) memcpy((localp[c]).valp,
914 item->valp,
915 item->length);
916 tempp = &(localp[c]);
917 if (c > 0)
918 (localp[c - 1]).next_item = tempp;
919 c++;
922 return (localp);
926 * mib_item_diff: takes two (mib_item_t *) linked lists
927 * item1 and item2 and computes the difference between
928 * differentiable values in item2 against item1 for every
929 * given member of item2; returns an mib_item_t * linked
930 * list of diff's, or a copy of item2 if item1 is NULL;
931 * will return NULL if system out of memory; works only
932 * for item->mib_id == 0
934 static mib_item_t *
935 mib_item_diff(mib_item_t *item1, mib_item_t *item2) {
936 int nitems = 0; /* no. of items in item2 */
937 mib_item_t *tempp2; /* walking copy of item2 */
938 mib_item_t *tempp1; /* walking copy of item1 */
939 mib_item_t *diffp;
940 mib_item_t *diffptr; /* walking copy of diffp */
941 mib_item_t *prevp = NULL;
943 if (item1 == NULL) {
944 diffp = mib_item_dup(item2);
945 return (diffp);
948 for (tempp2 = item2;
949 tempp2;
950 tempp2 = tempp2->next_item) {
951 if (tempp2->mib_id == 0)
952 switch (tempp2->group) {
954 * upon adding a case here, the same
955 * must also be added in the next
956 * switch statement, alongwith
957 * appropriate code
959 case MIB2_IP:
960 case MIB2_IP6:
961 case EXPER_DVMRP:
962 case EXPER_IGMP:
963 case MIB2_ICMP:
964 case MIB2_ICMP6:
965 case MIB2_TCP:
966 case MIB2_UDP:
967 case MIB2_SCTP:
968 case EXPER_RAWIP:
969 nitems++;
972 tempp2 = NULL;
973 if (nitems == 0) {
974 diffp = mib_item_dup(item2);
975 return (diffp);
978 diffp = (mib_item_t *)calloc(nitems, sizeof (mib_item_t));
979 if (diffp == NULL)
980 return (NULL);
981 diffptr = diffp;
982 /* 'for' loop 1: */
983 for (tempp2 = item2; tempp2 != NULL; tempp2 = tempp2->next_item) {
984 if (tempp2->mib_id != 0)
985 continue; /* 'for' loop 1 */
986 /* 'for' loop 2: */
987 for (tempp1 = item1; tempp1 != NULL;
988 tempp1 = tempp1->next_item) {
989 if (!(tempp1->mib_id == 0 &&
990 tempp1->group == tempp2->group &&
991 tempp1->mib_id == tempp2->mib_id))
992 continue; /* 'for' loop 2 */
993 /* found comparable data sets */
994 if (prevp != NULL)
995 prevp->next_item = diffptr;
996 switch (tempp2->group) {
998 * Indenting note: Because of long variable names
999 * in cases MIB2_IP6 and MIB2_ICMP6, their contents
1000 * have been indented by one tab space only
1002 case MIB2_IP: {
1003 mib2_ip_t *i2 = (mib2_ip_t *)tempp2->valp;
1004 mib2_ip_t *i1 = (mib2_ip_t *)tempp1->valp;
1005 mib2_ip_t *d;
1007 diffptr->group = tempp2->group;
1008 diffptr->mib_id = tempp2->mib_id;
1009 diffptr->length = tempp2->length;
1010 d = (mib2_ip_t *)calloc(tempp2->length, 1);
1011 if (d == NULL)
1012 goto mibdiff_out_of_memory;
1013 diffptr->valp = d;
1014 d->ipForwarding = i2->ipForwarding;
1015 d->ipDefaultTTL = i2->ipDefaultTTL;
1016 MDIFF(d, i2, i1, ipInReceives);
1017 MDIFF(d, i2, i1, ipInHdrErrors);
1018 MDIFF(d, i2, i1, ipInAddrErrors);
1019 MDIFF(d, i2, i1, ipInCksumErrs);
1020 MDIFF(d, i2, i1, ipForwDatagrams);
1021 MDIFF(d, i2, i1, ipForwProhibits);
1022 MDIFF(d, i2, i1, ipInUnknownProtos);
1023 MDIFF(d, i2, i1, ipInDiscards);
1024 MDIFF(d, i2, i1, ipInDelivers);
1025 MDIFF(d, i2, i1, ipOutRequests);
1026 MDIFF(d, i2, i1, ipOutDiscards);
1027 MDIFF(d, i2, i1, ipOutNoRoutes);
1028 MDIFF(d, i2, i1, ipReasmTimeout);
1029 MDIFF(d, i2, i1, ipReasmReqds);
1030 MDIFF(d, i2, i1, ipReasmOKs);
1031 MDIFF(d, i2, i1, ipReasmFails);
1032 MDIFF(d, i2, i1, ipReasmDuplicates);
1033 MDIFF(d, i2, i1, ipReasmPartDups);
1034 MDIFF(d, i2, i1, ipFragOKs);
1035 MDIFF(d, i2, i1, ipFragFails);
1036 MDIFF(d, i2, i1, ipFragCreates);
1037 MDIFF(d, i2, i1, ipRoutingDiscards);
1038 MDIFF(d, i2, i1, tcpInErrs);
1039 MDIFF(d, i2, i1, udpNoPorts);
1040 MDIFF(d, i2, i1, udpInCksumErrs);
1041 MDIFF(d, i2, i1, udpInOverflows);
1042 MDIFF(d, i2, i1, rawipInOverflows);
1043 MDIFF(d, i2, i1, ipsecInSucceeded);
1044 MDIFF(d, i2, i1, ipsecInFailed);
1045 MDIFF(d, i2, i1, ipInIPv6);
1046 MDIFF(d, i2, i1, ipOutIPv6);
1047 MDIFF(d, i2, i1, ipOutSwitchIPv6);
1048 prevp = diffptr++;
1049 break;
1051 case MIB2_IP6: {
1052 mib2_ipv6IfStatsEntry_t *i2;
1053 mib2_ipv6IfStatsEntry_t *i1;
1054 mib2_ipv6IfStatsEntry_t *d;
1056 i2 = (mib2_ipv6IfStatsEntry_t *)tempp2->valp;
1057 i1 = (mib2_ipv6IfStatsEntry_t *)tempp1->valp;
1058 diffptr->group = tempp2->group;
1059 diffptr->mib_id = tempp2->mib_id;
1060 diffptr->length = tempp2->length;
1061 d = (mib2_ipv6IfStatsEntry_t *)calloc(
1062 tempp2->length, 1);
1063 if (d == NULL)
1064 goto mibdiff_out_of_memory;
1065 diffptr->valp = d;
1066 d->ipv6Forwarding = i2->ipv6Forwarding;
1067 d->ipv6DefaultHopLimit =
1068 i2->ipv6DefaultHopLimit;
1070 MDIFF(d, i2, i1, ipv6InReceives);
1071 MDIFF(d, i2, i1, ipv6InHdrErrors);
1072 MDIFF(d, i2, i1, ipv6InTooBigErrors);
1073 MDIFF(d, i2, i1, ipv6InNoRoutes);
1074 MDIFF(d, i2, i1, ipv6InAddrErrors);
1075 MDIFF(d, i2, i1, ipv6InUnknownProtos);
1076 MDIFF(d, i2, i1, ipv6InTruncatedPkts);
1077 MDIFF(d, i2, i1, ipv6InDiscards);
1078 MDIFF(d, i2, i1, ipv6InDelivers);
1079 MDIFF(d, i2, i1, ipv6OutForwDatagrams);
1080 MDIFF(d, i2, i1, ipv6OutRequests);
1081 MDIFF(d, i2, i1, ipv6OutDiscards);
1082 MDIFF(d, i2, i1, ipv6OutNoRoutes);
1083 MDIFF(d, i2, i1, ipv6OutFragOKs);
1084 MDIFF(d, i2, i1, ipv6OutFragFails);
1085 MDIFF(d, i2, i1, ipv6OutFragCreates);
1086 MDIFF(d, i2, i1, ipv6ReasmReqds);
1087 MDIFF(d, i2, i1, ipv6ReasmOKs);
1088 MDIFF(d, i2, i1, ipv6ReasmFails);
1089 MDIFF(d, i2, i1, ipv6InMcastPkts);
1090 MDIFF(d, i2, i1, ipv6OutMcastPkts);
1091 MDIFF(d, i2, i1, ipv6ReasmDuplicates);
1092 MDIFF(d, i2, i1, ipv6ReasmPartDups);
1093 MDIFF(d, i2, i1, ipv6ForwProhibits);
1094 MDIFF(d, i2, i1, udpInCksumErrs);
1095 MDIFF(d, i2, i1, udpInOverflows);
1096 MDIFF(d, i2, i1, rawipInOverflows);
1097 MDIFF(d, i2, i1, ipv6InIPv4);
1098 MDIFF(d, i2, i1, ipv6OutIPv4);
1099 MDIFF(d, i2, i1, ipv6OutSwitchIPv4);
1100 prevp = diffptr++;
1101 break;
1103 case EXPER_DVMRP: {
1104 struct mrtstat *m2;
1105 struct mrtstat *m1;
1106 struct mrtstat *d;
1108 m2 = (struct mrtstat *)tempp2->valp;
1109 m1 = (struct mrtstat *)tempp1->valp;
1110 diffptr->group = tempp2->group;
1111 diffptr->mib_id = tempp2->mib_id;
1112 diffptr->length = tempp2->length;
1113 d = (struct mrtstat *)calloc(tempp2->length, 1);
1114 if (d == NULL)
1115 goto mibdiff_out_of_memory;
1116 diffptr->valp = d;
1117 MDIFF(d, m2, m1, mrts_mfc_hits);
1118 MDIFF(d, m2, m1, mrts_mfc_misses);
1119 MDIFF(d, m2, m1, mrts_fwd_in);
1120 MDIFF(d, m2, m1, mrts_fwd_out);
1121 d->mrts_upcalls = m2->mrts_upcalls;
1122 MDIFF(d, m2, m1, mrts_fwd_drop);
1123 MDIFF(d, m2, m1, mrts_bad_tunnel);
1124 MDIFF(d, m2, m1, mrts_cant_tunnel);
1125 MDIFF(d, m2, m1, mrts_wrong_if);
1126 MDIFF(d, m2, m1, mrts_upq_ovflw);
1127 MDIFF(d, m2, m1, mrts_cache_cleanups);
1128 MDIFF(d, m2, m1, mrts_drop_sel);
1129 MDIFF(d, m2, m1, mrts_q_overflow);
1130 MDIFF(d, m2, m1, mrts_pkt2large);
1131 MDIFF(d, m2, m1, mrts_pim_badversion);
1132 MDIFF(d, m2, m1, mrts_pim_rcv_badcsum);
1133 MDIFF(d, m2, m1, mrts_pim_badregisters);
1134 MDIFF(d, m2, m1, mrts_pim_regforwards);
1135 MDIFF(d, m2, m1, mrts_pim_regsend_drops);
1136 MDIFF(d, m2, m1, mrts_pim_malformed);
1137 MDIFF(d, m2, m1, mrts_pim_nomemory);
1138 prevp = diffptr++;
1139 break;
1141 case EXPER_IGMP: {
1142 struct igmpstat *i2;
1143 struct igmpstat *i1;
1144 struct igmpstat *d;
1146 i2 = (struct igmpstat *)tempp2->valp;
1147 i1 = (struct igmpstat *)tempp1->valp;
1148 diffptr->group = tempp2->group;
1149 diffptr->mib_id = tempp2->mib_id;
1150 diffptr->length = tempp2->length;
1151 d = (struct igmpstat *)calloc(
1152 tempp2->length, 1);
1153 if (d == NULL)
1154 goto mibdiff_out_of_memory;
1155 diffptr->valp = d;
1156 MDIFF(d, i2, i1, igps_rcv_total);
1157 MDIFF(d, i2, i1, igps_rcv_tooshort);
1158 MDIFF(d, i2, i1, igps_rcv_badsum);
1159 MDIFF(d, i2, i1, igps_rcv_queries);
1160 MDIFF(d, i2, i1, igps_rcv_badqueries);
1161 MDIFF(d, i2, i1, igps_rcv_reports);
1162 MDIFF(d, i2, i1, igps_rcv_badreports);
1163 MDIFF(d, i2, i1, igps_rcv_ourreports);
1164 MDIFF(d, i2, i1, igps_snd_reports);
1165 prevp = diffptr++;
1166 break;
1168 case MIB2_ICMP: {
1169 mib2_icmp_t *i2;
1170 mib2_icmp_t *i1;
1171 mib2_icmp_t *d;
1173 i2 = (mib2_icmp_t *)tempp2->valp;
1174 i1 = (mib2_icmp_t *)tempp1->valp;
1175 diffptr->group = tempp2->group;
1176 diffptr->mib_id = tempp2->mib_id;
1177 diffptr->length = tempp2->length;
1178 d = (mib2_icmp_t *)calloc(tempp2->length, 1);
1179 if (d == NULL)
1180 goto mibdiff_out_of_memory;
1181 diffptr->valp = d;
1182 MDIFF(d, i2, i1, icmpInMsgs);
1183 MDIFF(d, i2, i1, icmpInErrors);
1184 MDIFF(d, i2, i1, icmpInCksumErrs);
1185 MDIFF(d, i2, i1, icmpInUnknowns);
1186 MDIFF(d, i2, i1, icmpInDestUnreachs);
1187 MDIFF(d, i2, i1, icmpInTimeExcds);
1188 MDIFF(d, i2, i1, icmpInParmProbs);
1189 MDIFF(d, i2, i1, icmpInSrcQuenchs);
1190 MDIFF(d, i2, i1, icmpInRedirects);
1191 MDIFF(d, i2, i1, icmpInBadRedirects);
1192 MDIFF(d, i2, i1, icmpInEchos);
1193 MDIFF(d, i2, i1, icmpInEchoReps);
1194 MDIFF(d, i2, i1, icmpInTimestamps);
1195 MDIFF(d, i2, i1, icmpInAddrMasks);
1196 MDIFF(d, i2, i1, icmpInAddrMaskReps);
1197 MDIFF(d, i2, i1, icmpInFragNeeded);
1198 MDIFF(d, i2, i1, icmpOutMsgs);
1199 MDIFF(d, i2, i1, icmpOutDrops);
1200 MDIFF(d, i2, i1, icmpOutErrors);
1201 MDIFF(d, i2, i1, icmpOutDestUnreachs);
1202 MDIFF(d, i2, i1, icmpOutTimeExcds);
1203 MDIFF(d, i2, i1, icmpOutParmProbs);
1204 MDIFF(d, i2, i1, icmpOutSrcQuenchs);
1205 MDIFF(d, i2, i1, icmpOutRedirects);
1206 MDIFF(d, i2, i1, icmpOutEchos);
1207 MDIFF(d, i2, i1, icmpOutEchoReps);
1208 MDIFF(d, i2, i1, icmpOutTimestamps);
1209 MDIFF(d, i2, i1, icmpOutTimestampReps);
1210 MDIFF(d, i2, i1, icmpOutAddrMasks);
1211 MDIFF(d, i2, i1, icmpOutAddrMaskReps);
1212 MDIFF(d, i2, i1, icmpOutFragNeeded);
1213 MDIFF(d, i2, i1, icmpInOverflows);
1214 prevp = diffptr++;
1215 break;
1217 case MIB2_ICMP6: {
1218 mib2_ipv6IfIcmpEntry_t *i2;
1219 mib2_ipv6IfIcmpEntry_t *i1;
1220 mib2_ipv6IfIcmpEntry_t *d;
1222 i2 = (mib2_ipv6IfIcmpEntry_t *)tempp2->valp;
1223 i1 = (mib2_ipv6IfIcmpEntry_t *)tempp1->valp;
1224 diffptr->group = tempp2->group;
1225 diffptr->mib_id = tempp2->mib_id;
1226 diffptr->length = tempp2->length;
1227 d = (mib2_ipv6IfIcmpEntry_t *)calloc(tempp2->length, 1);
1228 if (d == NULL)
1229 goto mibdiff_out_of_memory;
1230 diffptr->valp = d;
1231 MDIFF(d, i2, i1, ipv6IfIcmpInMsgs);
1232 MDIFF(d, i2, i1, ipv6IfIcmpInErrors);
1233 MDIFF(d, i2, i1, ipv6IfIcmpInDestUnreachs);
1234 MDIFF(d, i2, i1, ipv6IfIcmpInAdminProhibs);
1235 MDIFF(d, i2, i1, ipv6IfIcmpInTimeExcds);
1236 MDIFF(d, i2, i1, ipv6IfIcmpInParmProblems);
1237 MDIFF(d, i2, i1, ipv6IfIcmpInPktTooBigs);
1238 MDIFF(d, i2, i1, ipv6IfIcmpInEchos);
1239 MDIFF(d, i2, i1, ipv6IfIcmpInEchoReplies);
1240 MDIFF(d, i2, i1, ipv6IfIcmpInRouterSolicits);
1241 MDIFF(d, i2, i1, ipv6IfIcmpInRouterAdvertisements);
1242 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborSolicits);
1243 MDIFF(d, i2, i1, ipv6IfIcmpInNeighborAdvertisements);
1244 MDIFF(d, i2, i1, ipv6IfIcmpInRedirects);
1245 MDIFF(d, i2, i1, ipv6IfIcmpInBadRedirects);
1246 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembQueries);
1247 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembResponses);
1248 MDIFF(d, i2, i1, ipv6IfIcmpInGroupMembReductions);
1249 MDIFF(d, i2, i1, ipv6IfIcmpInOverflows);
1250 MDIFF(d, i2, i1, ipv6IfIcmpOutMsgs);
1251 MDIFF(d, i2, i1, ipv6IfIcmpOutErrors);
1252 MDIFF(d, i2, i1, ipv6IfIcmpOutDestUnreachs);
1253 MDIFF(d, i2, i1, ipv6IfIcmpOutAdminProhibs);
1254 MDIFF(d, i2, i1, ipv6IfIcmpOutTimeExcds);
1255 MDIFF(d, i2, i1, ipv6IfIcmpOutParmProblems);
1256 MDIFF(d, i2, i1, ipv6IfIcmpOutPktTooBigs);
1257 MDIFF(d, i2, i1, ipv6IfIcmpOutEchos);
1258 MDIFF(d, i2, i1, ipv6IfIcmpOutEchoReplies);
1259 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterSolicits);
1260 MDIFF(d, i2, i1, ipv6IfIcmpOutRouterAdvertisements);
1261 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborSolicits);
1262 MDIFF(d, i2, i1, ipv6IfIcmpOutNeighborAdvertisements);
1263 MDIFF(d, i2, i1, ipv6IfIcmpOutRedirects);
1264 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembQueries);
1265 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembResponses);
1266 MDIFF(d, i2, i1, ipv6IfIcmpOutGroupMembReductions);
1267 prevp = diffptr++;
1268 break;
1270 case MIB2_TCP: {
1271 mib2_tcp_t *t2;
1272 mib2_tcp_t *t1;
1273 mib2_tcp_t *d;
1275 t2 = (mib2_tcp_t *)tempp2->valp;
1276 t1 = (mib2_tcp_t *)tempp1->valp;
1277 diffptr->group = tempp2->group;
1278 diffptr->mib_id = tempp2->mib_id;
1279 diffptr->length = tempp2->length;
1280 d = (mib2_tcp_t *)calloc(tempp2->length, 1);
1281 if (d == NULL)
1282 goto mibdiff_out_of_memory;
1283 diffptr->valp = d;
1284 d->tcpRtoMin = t2->tcpRtoMin;
1285 d->tcpRtoMax = t2->tcpRtoMax;
1286 d->tcpMaxConn = t2->tcpMaxConn;
1287 MDIFF(d, t2, t1, tcpActiveOpens);
1288 MDIFF(d, t2, t1, tcpPassiveOpens);
1289 MDIFF(d, t2, t1, tcpAttemptFails);
1290 MDIFF(d, t2, t1, tcpEstabResets);
1291 d->tcpCurrEstab = t2->tcpCurrEstab;
1292 MDIFF(d, t2, t1, tcpHCOutSegs);
1293 MDIFF(d, t2, t1, tcpOutDataSegs);
1294 MDIFF(d, t2, t1, tcpOutDataBytes);
1295 MDIFF(d, t2, t1, tcpRetransSegs);
1296 MDIFF(d, t2, t1, tcpRetransBytes);
1297 MDIFF(d, t2, t1, tcpOutAck);
1298 MDIFF(d, t2, t1, tcpOutAckDelayed);
1299 MDIFF(d, t2, t1, tcpOutUrg);
1300 MDIFF(d, t2, t1, tcpOutWinUpdate);
1301 MDIFF(d, t2, t1, tcpOutWinProbe);
1302 MDIFF(d, t2, t1, tcpOutControl);
1303 MDIFF(d, t2, t1, tcpOutRsts);
1304 MDIFF(d, t2, t1, tcpOutFastRetrans);
1305 MDIFF(d, t2, t1, tcpHCInSegs);
1306 MDIFF(d, t2, t1, tcpInAckSegs);
1307 MDIFF(d, t2, t1, tcpInAckBytes);
1308 MDIFF(d, t2, t1, tcpInDupAck);
1309 MDIFF(d, t2, t1, tcpInAckUnsent);
1310 MDIFF(d, t2, t1, tcpInDataInorderSegs);
1311 MDIFF(d, t2, t1, tcpInDataInorderBytes);
1312 MDIFF(d, t2, t1, tcpInDataUnorderSegs);
1313 MDIFF(d, t2, t1, tcpInDataUnorderBytes);
1314 MDIFF(d, t2, t1, tcpInDataDupSegs);
1315 MDIFF(d, t2, t1, tcpInDataDupBytes);
1316 MDIFF(d, t2, t1, tcpInDataPartDupSegs);
1317 MDIFF(d, t2, t1, tcpInDataPartDupBytes);
1318 MDIFF(d, t2, t1, tcpInDataPastWinSegs);
1319 MDIFF(d, t2, t1, tcpInDataPastWinBytes);
1320 MDIFF(d, t2, t1, tcpInWinProbe);
1321 MDIFF(d, t2, t1, tcpInWinUpdate);
1322 MDIFF(d, t2, t1, tcpInClosed);
1323 MDIFF(d, t2, t1, tcpRttNoUpdate);
1324 MDIFF(d, t2, t1, tcpRttUpdate);
1325 MDIFF(d, t2, t1, tcpTimRetrans);
1326 MDIFF(d, t2, t1, tcpTimRetransDrop);
1327 MDIFF(d, t2, t1, tcpTimKeepalive);
1328 MDIFF(d, t2, t1, tcpTimKeepaliveProbe);
1329 MDIFF(d, t2, t1, tcpTimKeepaliveDrop);
1330 MDIFF(d, t2, t1, tcpListenDrop);
1331 MDIFF(d, t2, t1, tcpListenDropQ0);
1332 MDIFF(d, t2, t1, tcpHalfOpenDrop);
1333 MDIFF(d, t2, t1, tcpOutSackRetransSegs);
1334 prevp = diffptr++;
1335 break;
1337 case MIB2_UDP: {
1338 mib2_udp_t *u2;
1339 mib2_udp_t *u1;
1340 mib2_udp_t *d;
1342 u2 = (mib2_udp_t *)tempp2->valp;
1343 u1 = (mib2_udp_t *)tempp1->valp;
1344 diffptr->group = tempp2->group;
1345 diffptr->mib_id = tempp2->mib_id;
1346 diffptr->length = tempp2->length;
1347 d = (mib2_udp_t *)calloc(tempp2->length, 1);
1348 if (d == NULL)
1349 goto mibdiff_out_of_memory;
1350 diffptr->valp = d;
1351 MDIFF(d, u2, u1, udpHCInDatagrams);
1352 MDIFF(d, u2, u1, udpInErrors);
1353 MDIFF(d, u2, u1, udpHCOutDatagrams);
1354 MDIFF(d, u2, u1, udpOutErrors);
1355 prevp = diffptr++;
1356 break;
1358 case MIB2_SCTP: {
1359 mib2_sctp_t *s2;
1360 mib2_sctp_t *s1;
1361 mib2_sctp_t *d;
1363 s2 = (mib2_sctp_t *)tempp2->valp;
1364 s1 = (mib2_sctp_t *)tempp1->valp;
1365 diffptr->group = tempp2->group;
1366 diffptr->mib_id = tempp2->mib_id;
1367 diffptr->length = tempp2->length;
1368 d = (mib2_sctp_t *)calloc(tempp2->length, 1);
1369 if (d == NULL)
1370 goto mibdiff_out_of_memory;
1371 diffptr->valp = d;
1372 d->sctpRtoAlgorithm = s2->sctpRtoAlgorithm;
1373 d->sctpRtoMin = s2->sctpRtoMin;
1374 d->sctpRtoMax = s2->sctpRtoMax;
1375 d->sctpRtoInitial = s2->sctpRtoInitial;
1376 d->sctpMaxAssocs = s2->sctpMaxAssocs;
1377 d->sctpValCookieLife = s2->sctpValCookieLife;
1378 d->sctpMaxInitRetr = s2->sctpMaxInitRetr;
1379 d->sctpCurrEstab = s2->sctpCurrEstab;
1380 MDIFF(d, s2, s1, sctpActiveEstab);
1381 MDIFF(d, s2, s1, sctpPassiveEstab);
1382 MDIFF(d, s2, s1, sctpAborted);
1383 MDIFF(d, s2, s1, sctpShutdowns);
1384 MDIFF(d, s2, s1, sctpOutOfBlue);
1385 MDIFF(d, s2, s1, sctpChecksumError);
1386 MDIFF(d, s2, s1, sctpOutCtrlChunks);
1387 MDIFF(d, s2, s1, sctpOutOrderChunks);
1388 MDIFF(d, s2, s1, sctpOutUnorderChunks);
1389 MDIFF(d, s2, s1, sctpRetransChunks);
1390 MDIFF(d, s2, s1, sctpOutAck);
1391 MDIFF(d, s2, s1, sctpOutAckDelayed);
1392 MDIFF(d, s2, s1, sctpOutWinUpdate);
1393 MDIFF(d, s2, s1, sctpOutFastRetrans);
1394 MDIFF(d, s2, s1, sctpOutWinProbe);
1395 MDIFF(d, s2, s1, sctpInCtrlChunks);
1396 MDIFF(d, s2, s1, sctpInOrderChunks);
1397 MDIFF(d, s2, s1, sctpInUnorderChunks);
1398 MDIFF(d, s2, s1, sctpInAck);
1399 MDIFF(d, s2, s1, sctpInDupAck);
1400 MDIFF(d, s2, s1, sctpInAckUnsent);
1401 MDIFF(d, s2, s1, sctpFragUsrMsgs);
1402 MDIFF(d, s2, s1, sctpReasmUsrMsgs);
1403 MDIFF(d, s2, s1, sctpOutSCTPPkts);
1404 MDIFF(d, s2, s1, sctpInSCTPPkts);
1405 MDIFF(d, s2, s1, sctpInInvalidCookie);
1406 MDIFF(d, s2, s1, sctpTimRetrans);
1407 MDIFF(d, s2, s1, sctpTimRetransDrop);
1408 MDIFF(d, s2, s1, sctpTimHeartBeatProbe);
1409 MDIFF(d, s2, s1, sctpTimHeartBeatDrop);
1410 MDIFF(d, s2, s1, sctpListenDrop);
1411 MDIFF(d, s2, s1, sctpInClosed);
1412 prevp = diffptr++;
1413 break;
1415 case EXPER_RAWIP: {
1416 mib2_rawip_t *r2;
1417 mib2_rawip_t *r1;
1418 mib2_rawip_t *d;
1420 r2 = (mib2_rawip_t *)tempp2->valp;
1421 r1 = (mib2_rawip_t *)tempp1->valp;
1422 diffptr->group = tempp2->group;
1423 diffptr->mib_id = tempp2->mib_id;
1424 diffptr->length = tempp2->length;
1425 d = (mib2_rawip_t *)calloc(tempp2->length, 1);
1426 if (d == NULL)
1427 goto mibdiff_out_of_memory;
1428 diffptr->valp = d;
1429 MDIFF(d, r2, r1, rawipInDatagrams);
1430 MDIFF(d, r2, r1, rawipInErrors);
1431 MDIFF(d, r2, r1, rawipInCksumErrs);
1432 MDIFF(d, r2, r1, rawipOutDatagrams);
1433 MDIFF(d, r2, r1, rawipOutErrors);
1434 prevp = diffptr++;
1435 break;
1438 * there are more "group" types but they aren't
1439 * required for the -s and -Ms options
1442 } /* 'for' loop 2 ends */
1443 tempp1 = NULL;
1444 } /* 'for' loop 1 ends */
1445 tempp2 = NULL;
1446 diffptr--;
1447 diffptr->next_item = NULL;
1448 return (diffp);
1450 mibdiff_out_of_memory:;
1451 mib_item_destroy(&diffp);
1452 return (NULL);
1456 * mib_item_destroy: cleans up a mib_item_t *
1457 * that was created by calling mib_item_dup or
1458 * mib_item_diff
1460 static void
1461 mib_item_destroy(mib_item_t **itemp) {
1462 int nitems = 0;
1463 int c = 0;
1464 mib_item_t *tempp;
1466 if (itemp == NULL || *itemp == NULL)
1467 return;
1469 for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1470 if (tempp->mib_id == 0)
1471 nitems++;
1472 else
1473 return; /* cannot destroy! */
1475 if (nitems == 0)
1476 return; /* cannot destroy! */
1478 for (c = nitems - 1; c >= 0; c--) {
1479 free((itemp[0][c]).valp);
1481 free(*itemp);
1483 *itemp = NULL;
1486 /* Compare two Octet_ts. Return B_TRUE if they match, B_FALSE if not. */
1487 static boolean_t
1488 octetstrmatch(const Octet_t *a, const Octet_t *b)
1490 if (a == NULL || b == NULL)
1491 return (B_FALSE);
1493 if (a->o_length != b->o_length)
1494 return (B_FALSE);
1496 return (memcmp(a->o_bytes, b->o_bytes, a->o_length) == 0);
1499 /* If octetstr() changes make an appropriate change to STR_EXPAND */
1500 static char *
1501 octetstr(const Octet_t *op, int code, char *dst, uint_t dstlen)
1503 int i;
1504 char *cp;
1506 cp = dst;
1507 if (op) {
1508 for (i = 0; i < op->o_length; i++) {
1509 switch (code) {
1510 case 'd':
1511 if (cp - dst + 4 > dstlen) {
1512 *cp = '\0';
1513 return (dst);
1515 (void) snprintf(cp, 5, "%d.",
1516 0xff & op->o_bytes[i]);
1517 cp = strchr(cp, '\0');
1518 break;
1519 case 'a':
1520 if (cp - dst + 1 > dstlen) {
1521 *cp = '\0';
1522 return (dst);
1524 *cp++ = op->o_bytes[i];
1525 break;
1526 case 'h':
1527 default:
1528 if (cp - dst + 3 > dstlen) {
1529 *cp = '\0';
1530 return (dst);
1532 (void) snprintf(cp, 4, "%02x:",
1533 0xff & op->o_bytes[i]);
1534 cp += 3;
1535 break;
1539 if (code != 'a' && cp != dst)
1540 cp--;
1541 *cp = '\0';
1542 return (dst);
1545 static const char *
1546 mitcp_state(int state)
1548 static char tcpsbuf[50];
1549 const char *cp;
1551 switch (state) {
1552 case TCPS_CLOSED:
1553 cp = "CLOSED";
1554 break;
1555 case TCPS_IDLE:
1556 cp = "IDLE";
1557 break;
1558 case TCPS_BOUND:
1559 cp = "BOUND";
1560 break;
1561 case TCPS_LISTEN:
1562 cp = "LISTEN";
1563 break;
1564 case TCPS_SYN_SENT:
1565 cp = "SYN_SENT";
1566 break;
1567 case TCPS_SYN_RCVD:
1568 cp = "SYN_RCVD";
1569 break;
1570 case TCPS_ESTABLISHED:
1571 cp = "ESTABLISHED";
1572 break;
1573 case TCPS_CLOSE_WAIT:
1574 cp = "CLOSE_WAIT";
1575 break;
1576 case TCPS_FIN_WAIT_1:
1577 cp = "FIN_WAIT_1";
1578 break;
1579 case TCPS_CLOSING:
1580 cp = "CLOSING";
1581 break;
1582 case TCPS_LAST_ACK:
1583 cp = "LAST_ACK";
1584 break;
1585 case TCPS_FIN_WAIT_2:
1586 cp = "FIN_WAIT_2";
1587 break;
1588 case TCPS_TIME_WAIT:
1589 cp = "TIME_WAIT";
1590 break;
1591 default:
1592 (void) snprintf(tcpsbuf, sizeof (tcpsbuf),
1593 "UnknownState(%d)", state);
1594 cp = tcpsbuf;
1595 break;
1598 return (cp);
1601 static const char *
1602 miudp_state(int state)
1604 static char udpsbuf[50];
1605 const char *cp;
1607 switch (state) {
1608 case MIB2_UDP_unbound:
1609 cp = "Unbound";
1610 break;
1611 case MIB2_UDP_idle:
1612 cp = "Idle";
1613 break;
1614 case MIB2_UDP_connected:
1615 cp = "Connected";
1616 break;
1617 default:
1618 (void) snprintf(udpsbuf, sizeof (udpsbuf),
1619 "Unknown State(%d)", state);
1620 cp = udpsbuf;
1621 break;
1624 return (cp);
1627 static int odd;
1629 static void
1630 prval_init(void)
1632 odd = 0;
1635 static void
1636 prval(char *str, Counter val)
1638 (void) printf("\t%-20s=%6u", str, val);
1639 if (odd++ & 1)
1640 (void) putchar('\n');
1643 static void
1644 prval64(char *str, Counter64 val)
1646 (void) printf("\t%-20s=%6llu", str, val);
1647 if (odd++ & 1)
1648 (void) putchar('\n');
1651 static void
1652 pr_int_val(char *str, int val)
1654 (void) printf("\t%-20s=%6d", str, val);
1655 if (odd++ & 1)
1656 (void) putchar('\n');
1659 static void
1660 pr_sctp_rtoalgo(char *str, int val)
1662 (void) printf("\t%-20s=", str);
1663 switch (val) {
1664 case MIB2_SCTP_RTOALGO_OTHER:
1665 (void) printf("%6.6s", "other");
1666 break;
1668 case MIB2_SCTP_RTOALGO_VANJ:
1669 (void) printf("%6.6s", "vanj");
1670 break;
1672 default:
1673 (void) printf("%6d", val);
1674 break;
1676 if (odd++ & 1)
1677 (void) putchar('\n');
1680 static void
1681 prval_end(void)
1683 if (odd++ & 1)
1684 (void) putchar('\n');
1687 /* Extract constant sizes */
1688 static void
1689 mib_get_constants(mib_item_t *item)
1691 /* 'for' loop 1: */
1692 for (; item; item = item->next_item) {
1693 if (item->mib_id != 0)
1694 continue; /* 'for' loop 1 */
1696 switch (item->group) {
1697 case MIB2_IP: {
1698 mib2_ip_t *ip = (mib2_ip_t *)item->valp;
1700 ipAddrEntrySize = ip->ipAddrEntrySize;
1701 ipRouteEntrySize = ip->ipRouteEntrySize;
1702 ipNetToMediaEntrySize = ip->ipNetToMediaEntrySize;
1703 ipMemberEntrySize = ip->ipMemberEntrySize;
1704 ipGroupSourceEntrySize = ip->ipGroupSourceEntrySize;
1705 ipDestEntrySize = ip->ipDestEntrySize;
1706 assert(IS_P2ALIGNED(ipAddrEntrySize,
1707 sizeof (mib2_ipAddrEntry_t *)));
1708 assert(IS_P2ALIGNED(ipRouteEntrySize,
1709 sizeof (mib2_ipRouteEntry_t *)));
1710 assert(IS_P2ALIGNED(ipNetToMediaEntrySize,
1711 sizeof (mib2_ipNetToMediaEntry_t *)));
1712 assert(IS_P2ALIGNED(ipMemberEntrySize,
1713 sizeof (ip_member_t *)));
1714 assert(IS_P2ALIGNED(ipGroupSourceEntrySize,
1715 sizeof (ip_grpsrc_t *)));
1716 break;
1718 case EXPER_DVMRP: {
1719 struct mrtstat *mrts = (struct mrtstat *)item->valp;
1721 vifctlSize = mrts->mrts_vifctlSize;
1722 mfcctlSize = mrts->mrts_mfcctlSize;
1723 assert(IS_P2ALIGNED(vifctlSize,
1724 sizeof (struct vifclt *)));
1725 assert(IS_P2ALIGNED(mfcctlSize,
1726 sizeof (struct mfcctl *)));
1727 break;
1729 case MIB2_IP6: {
1730 mib2_ipv6IfStatsEntry_t *ip6;
1731 /* Just use the first entry */
1733 ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp;
1734 ipv6IfStatsEntrySize = ip6->ipv6IfStatsEntrySize;
1735 ipv6AddrEntrySize = ip6->ipv6AddrEntrySize;
1736 ipv6RouteEntrySize = ip6->ipv6RouteEntrySize;
1737 ipv6NetToMediaEntrySize = ip6->ipv6NetToMediaEntrySize;
1738 ipv6MemberEntrySize = ip6->ipv6MemberEntrySize;
1739 ipv6GroupSourceEntrySize =
1740 ip6->ipv6GroupSourceEntrySize;
1741 assert(IS_P2ALIGNED(ipv6IfStatsEntrySize,
1742 sizeof (mib2_ipv6IfStatsEntry_t *)));
1743 assert(IS_P2ALIGNED(ipv6AddrEntrySize,
1744 sizeof (mib2_ipv6AddrEntry_t *)));
1745 assert(IS_P2ALIGNED(ipv6RouteEntrySize,
1746 sizeof (mib2_ipv6RouteEntry_t *)));
1747 assert(IS_P2ALIGNED(ipv6NetToMediaEntrySize,
1748 sizeof (mib2_ipv6NetToMediaEntry_t *)));
1749 assert(IS_P2ALIGNED(ipv6MemberEntrySize,
1750 sizeof (ipv6_member_t *)));
1751 assert(IS_P2ALIGNED(ipv6GroupSourceEntrySize,
1752 sizeof (ipv6_grpsrc_t *)));
1753 break;
1755 case MIB2_ICMP6: {
1756 mib2_ipv6IfIcmpEntry_t *icmp6;
1757 /* Just use the first entry */
1759 icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp;
1760 ipv6IfIcmpEntrySize = icmp6->ipv6IfIcmpEntrySize;
1761 assert(IS_P2ALIGNED(ipv6IfIcmpEntrySize,
1762 sizeof (mib2_ipv6IfIcmpEntry_t *)));
1763 break;
1765 case MIB2_TCP: {
1766 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp;
1768 tcpConnEntrySize = tcp->tcpConnTableSize;
1769 tcp6ConnEntrySize = tcp->tcp6ConnTableSize;
1770 assert(IS_P2ALIGNED(tcpConnEntrySize,
1771 sizeof (mib2_tcpConnEntry_t *)));
1772 assert(IS_P2ALIGNED(tcp6ConnEntrySize,
1773 sizeof (mib2_tcp6ConnEntry_t *)));
1774 break;
1776 case MIB2_UDP: {
1777 mib2_udp_t *udp = (mib2_udp_t *)item->valp;
1779 udpEntrySize = udp->udpEntrySize;
1780 udp6EntrySize = udp->udp6EntrySize;
1781 assert(IS_P2ALIGNED(udpEntrySize,
1782 sizeof (mib2_udpEntry_t *)));
1783 assert(IS_P2ALIGNED(udp6EntrySize,
1784 sizeof (mib2_udp6Entry_t *)));
1785 break;
1787 case MIB2_SCTP: {
1788 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp;
1790 sctpEntrySize = sctp->sctpEntrySize;
1791 sctpLocalEntrySize = sctp->sctpLocalEntrySize;
1792 sctpRemoteEntrySize = sctp->sctpRemoteEntrySize;
1793 break;
1796 } /* 'for' loop 1 ends */
1798 if (Xflag) {
1799 (void) puts("mib_get_constants:");
1800 (void) printf("\tipv6IfStatsEntrySize %d\n",
1801 ipv6IfStatsEntrySize);
1802 (void) printf("\tipAddrEntrySize %d\n", ipAddrEntrySize);
1803 (void) printf("\tipRouteEntrySize %d\n", ipRouteEntrySize);
1804 (void) printf("\tipNetToMediaEntrySize %d\n",
1805 ipNetToMediaEntrySize);
1806 (void) printf("\tipMemberEntrySize %d\n", ipMemberEntrySize);
1807 (void) printf("\tvifctlSize %d\n", vifctlSize);
1808 (void) printf("\tmfcctlSize %d\n", mfcctlSize);
1810 (void) printf("\tipv6AddrEntrySize %d\n", ipv6AddrEntrySize);
1811 (void) printf("\tipv6RouteEntrySize %d\n", ipv6RouteEntrySize);
1812 (void) printf("\tipv6NetToMediaEntrySize %d\n",
1813 ipv6NetToMediaEntrySize);
1814 (void) printf("\tipv6MemberEntrySize %d\n",
1815 ipv6MemberEntrySize);
1816 (void) printf("\tipv6IfIcmpEntrySize %d\n",
1817 ipv6IfIcmpEntrySize);
1818 (void) printf("\tipDestEntrySize %d\n", ipDestEntrySize);
1819 (void) printf("\ttcpConnEntrySize %d\n", tcpConnEntrySize);
1820 (void) printf("\ttcp6ConnEntrySize %d\n", tcp6ConnEntrySize);
1821 (void) printf("\tudpEntrySize %d\n", udpEntrySize);
1822 (void) printf("\tudp6EntrySize %d\n", udp6EntrySize);
1823 (void) printf("\tsctpEntrySize %d\n", sctpEntrySize);
1824 (void) printf("\tsctpLocalEntrySize %d\n", sctpLocalEntrySize);
1825 (void) printf("\tsctpRemoteEntrySize %d\n",
1826 sctpRemoteEntrySize);
1831 /* ----------------------------- STAT_REPORT ------------------------------- */
1833 static void
1834 stat_report(mib_item_t *item)
1836 int jtemp = 0;
1837 char ifname[LIFNAMSIZ + 1];
1839 /* 'for' loop 1: */
1840 for (; item; item = item->next_item) {
1841 if (Xflag) {
1842 (void) printf("\n--- Entry %d ---\n", ++jtemp);
1843 (void) printf("Group = %d, mib_id = %d, "
1844 "length = %d, valp = 0x%p\n",
1845 item->group, item->mib_id,
1846 item->length, item->valp);
1848 if (item->mib_id != 0)
1849 continue; /* 'for' loop 1 */
1851 switch (item->group) {
1852 case MIB2_IP: {
1853 mib2_ip_t *ip = (mib2_ip_t *)item->valp;
1855 if (protocol_selected(IPPROTO_IP) &&
1856 family_selected(AF_INET)) {
1857 (void) fputs(v4compat ? "\nIP" : "\nIPv4",
1858 stdout);
1859 print_ip_stats(ip);
1861 break;
1863 case MIB2_ICMP: {
1864 mib2_icmp_t *icmp =
1865 (mib2_icmp_t *)item->valp;
1867 if (protocol_selected(IPPROTO_ICMP) &&
1868 family_selected(AF_INET)) {
1869 (void) fputs(v4compat ? "\nICMP" : "\nICMPv4",
1870 stdout);
1871 print_icmp_stats(icmp);
1873 break;
1875 case MIB2_IP6: {
1876 mib2_ipv6IfStatsEntry_t *ip6;
1877 mib2_ipv6IfStatsEntry_t sum6;
1879 if (!(protocol_selected(IPPROTO_IPV6)) ||
1880 !(family_selected(AF_INET6)))
1881 break;
1882 bzero(&sum6, sizeof (sum6));
1883 /* 'for' loop 2a: */
1884 for (ip6 = (mib2_ipv6IfStatsEntry_t *)item->valp;
1885 (char *)ip6 < (char *)item->valp + item->length;
1886 /* LINTED: (note 1) */
1887 ip6 = (mib2_ipv6IfStatsEntry_t *)((char *)ip6 +
1888 ipv6IfStatsEntrySize)) {
1889 if (ip6->ipv6IfIndex == 0) {
1891 * The "unknown interface" ip6
1892 * mib. Just add to the sum.
1894 sum_ip6_stats(ip6, &sum6);
1895 continue; /* 'for' loop 2a */
1897 if (Aflag) {
1898 (void) printf("\nIPv6 for %s\n",
1899 ifindex2str(ip6->ipv6IfIndex,
1900 ifname));
1901 print_ip6_stats(ip6);
1903 sum_ip6_stats(ip6, &sum6);
1904 } /* 'for' loop 2a ends */
1905 (void) fputs("\nIPv6", stdout);
1906 print_ip6_stats(&sum6);
1907 break;
1909 case MIB2_ICMP6: {
1910 mib2_ipv6IfIcmpEntry_t *icmp6;
1911 mib2_ipv6IfIcmpEntry_t sum6;
1913 if (!(protocol_selected(IPPROTO_ICMPV6)) ||
1914 !(family_selected(AF_INET6)))
1915 break;
1916 bzero(&sum6, sizeof (sum6));
1917 /* 'for' loop 2b: */
1918 for (icmp6 = (mib2_ipv6IfIcmpEntry_t *)item->valp;
1919 (char *)icmp6 < (char *)item->valp + item->length;
1920 icmp6 = (void *)((char *)icmp6 +
1921 ipv6IfIcmpEntrySize)) {
1922 if (icmp6->ipv6IfIcmpIfIndex == 0) {
1924 * The "unknown interface" icmp6
1925 * mib. Just add to the sum.
1927 sum_icmp6_stats(icmp6, &sum6);
1928 continue; /* 'for' loop 2b: */
1930 if (Aflag) {
1931 (void) printf("\nICMPv6 for %s\n",
1932 ifindex2str(
1933 icmp6->ipv6IfIcmpIfIndex, ifname));
1934 print_icmp6_stats(icmp6);
1936 sum_icmp6_stats(icmp6, &sum6);
1937 } /* 'for' loop 2b ends */
1938 (void) fputs("\nICMPv6", stdout);
1939 print_icmp6_stats(&sum6);
1940 break;
1942 case MIB2_TCP: {
1943 mib2_tcp_t *tcp = (mib2_tcp_t *)item->valp;
1945 if (protocol_selected(IPPROTO_TCP) &&
1946 (family_selected(AF_INET) ||
1947 family_selected(AF_INET6))) {
1948 (void) fputs("\nTCP", stdout);
1949 print_tcp_stats(tcp);
1951 break;
1953 case MIB2_UDP: {
1954 mib2_udp_t *udp = (mib2_udp_t *)item->valp;
1956 if (protocol_selected(IPPROTO_UDP) &&
1957 (family_selected(AF_INET) ||
1958 family_selected(AF_INET6))) {
1959 (void) fputs("\nUDP", stdout);
1960 print_udp_stats(udp);
1962 break;
1964 case MIB2_SCTP: {
1965 mib2_sctp_t *sctp = (mib2_sctp_t *)item->valp;
1967 if (protocol_selected(IPPROTO_SCTP) &&
1968 (family_selected(AF_INET) ||
1969 family_selected(AF_INET6))) {
1970 (void) fputs("\nSCTP", stdout);
1971 print_sctp_stats(sctp);
1973 break;
1975 case EXPER_RAWIP: {
1976 mib2_rawip_t *rawip =
1977 (mib2_rawip_t *)item->valp;
1979 if (protocol_selected(IPPROTO_RAW) &&
1980 (family_selected(AF_INET) ||
1981 family_selected(AF_INET6))) {
1982 (void) fputs("\nRAWIP", stdout);
1983 print_rawip_stats(rawip);
1985 break;
1987 case EXPER_IGMP: {
1988 struct igmpstat *igps =
1989 (struct igmpstat *)item->valp;
1991 if (protocol_selected(IPPROTO_IGMP) &&
1992 (family_selected(AF_INET))) {
1993 (void) fputs("\nIGMP:\n", stdout);
1994 print_igmp_stats(igps);
1996 break;
1999 } /* 'for' loop 1 ends */
2000 (void) putchar('\n');
2001 (void) fflush(stdout);
2004 static void
2005 print_ip_stats(mib2_ip_t *ip)
2007 prval_init();
2008 pr_int_val("ipForwarding", ip->ipForwarding);
2009 pr_int_val("ipDefaultTTL", ip->ipDefaultTTL);
2010 prval("ipInReceives", ip->ipInReceives);
2011 prval("ipInHdrErrors", ip->ipInHdrErrors);
2012 prval("ipInAddrErrors", ip->ipInAddrErrors);
2013 prval("ipInCksumErrs", ip->ipInCksumErrs);
2014 prval("ipForwDatagrams", ip->ipForwDatagrams);
2015 prval("ipForwProhibits", ip->ipForwProhibits);
2016 prval("ipInUnknownProtos", ip->ipInUnknownProtos);
2017 prval("ipInDiscards", ip->ipInDiscards);
2018 prval("ipInDelivers", ip->ipInDelivers);
2019 prval("ipOutRequests", ip->ipOutRequests);
2020 prval("ipOutDiscards", ip->ipOutDiscards);
2021 prval("ipOutNoRoutes", ip->ipOutNoRoutes);
2022 pr_int_val("ipReasmTimeout", ip->ipReasmTimeout);
2023 prval("ipReasmReqds", ip->ipReasmReqds);
2024 prval("ipReasmOKs", ip->ipReasmOKs);
2025 prval("ipReasmFails", ip->ipReasmFails);
2026 prval("ipReasmDuplicates", ip->ipReasmDuplicates);
2027 prval("ipReasmPartDups", ip->ipReasmPartDups);
2028 prval("ipFragOKs", ip->ipFragOKs);
2029 prval("ipFragFails", ip->ipFragFails);
2030 prval("ipFragCreates", ip->ipFragCreates);
2031 prval("ipRoutingDiscards", ip->ipRoutingDiscards);
2033 prval("tcpInErrs", ip->tcpInErrs);
2034 prval("udpNoPorts", ip->udpNoPorts);
2035 prval("udpInCksumErrs", ip->udpInCksumErrs);
2036 prval("udpInOverflows", ip->udpInOverflows);
2037 prval("rawipInOverflows", ip->rawipInOverflows);
2038 prval("ipsecInSucceeded", ip->ipsecInSucceeded);
2039 prval("ipsecInFailed", ip->ipsecInFailed);
2040 prval("ipInIPv6", ip->ipInIPv6);
2041 prval("ipOutIPv6", ip->ipOutIPv6);
2042 prval("ipOutSwitchIPv6", ip->ipOutSwitchIPv6);
2043 prval_end();
2046 static void
2047 print_icmp_stats(mib2_icmp_t *icmp)
2049 prval_init();
2050 prval("icmpInMsgs", icmp->icmpInMsgs);
2051 prval("icmpInErrors", icmp->icmpInErrors);
2052 prval("icmpInCksumErrs", icmp->icmpInCksumErrs);
2053 prval("icmpInUnknowns", icmp->icmpInUnknowns);
2054 prval("icmpInDestUnreachs", icmp->icmpInDestUnreachs);
2055 prval("icmpInTimeExcds", icmp->icmpInTimeExcds);
2056 prval("icmpInParmProbs", icmp->icmpInParmProbs);
2057 prval("icmpInSrcQuenchs", icmp->icmpInSrcQuenchs);
2058 prval("icmpInRedirects", icmp->icmpInRedirects);
2059 prval("icmpInBadRedirects", icmp->icmpInBadRedirects);
2060 prval("icmpInEchos", icmp->icmpInEchos);
2061 prval("icmpInEchoReps", icmp->icmpInEchoReps);
2062 prval("icmpInTimestamps", icmp->icmpInTimestamps);
2063 prval("icmpInTimestampReps", icmp->icmpInTimestampReps);
2064 prval("icmpInAddrMasks", icmp->icmpInAddrMasks);
2065 prval("icmpInAddrMaskReps", icmp->icmpInAddrMaskReps);
2066 prval("icmpInFragNeeded", icmp->icmpInFragNeeded);
2067 prval("icmpOutMsgs", icmp->icmpOutMsgs);
2068 prval("icmpOutDrops", icmp->icmpOutDrops);
2069 prval("icmpOutErrors", icmp->icmpOutErrors);
2070 prval("icmpOutDestUnreachs", icmp->icmpOutDestUnreachs);
2071 prval("icmpOutTimeExcds", icmp->icmpOutTimeExcds);
2072 prval("icmpOutParmProbs", icmp->icmpOutParmProbs);
2073 prval("icmpOutSrcQuenchs", icmp->icmpOutSrcQuenchs);
2074 prval("icmpOutRedirects", icmp->icmpOutRedirects);
2075 prval("icmpOutEchos", icmp->icmpOutEchos);
2076 prval("icmpOutEchoReps", icmp->icmpOutEchoReps);
2077 prval("icmpOutTimestamps", icmp->icmpOutTimestamps);
2078 prval("icmpOutTimestampReps", icmp->icmpOutTimestampReps);
2079 prval("icmpOutAddrMasks", icmp->icmpOutAddrMasks);
2080 prval("icmpOutAddrMaskReps", icmp->icmpOutAddrMaskReps);
2081 prval("icmpOutFragNeeded", icmp->icmpOutFragNeeded);
2082 prval("icmpInOverflows", icmp->icmpInOverflows);
2083 prval_end();
2086 static void
2087 print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6)
2089 prval_init();
2090 prval("ipv6Forwarding", ip6->ipv6Forwarding);
2091 prval("ipv6DefaultHopLimit", ip6->ipv6DefaultHopLimit);
2093 prval("ipv6InReceives", ip6->ipv6InReceives);
2094 prval("ipv6InHdrErrors", ip6->ipv6InHdrErrors);
2095 prval("ipv6InTooBigErrors", ip6->ipv6InTooBigErrors);
2096 prval("ipv6InNoRoutes", ip6->ipv6InNoRoutes);
2097 prval("ipv6InAddrErrors", ip6->ipv6InAddrErrors);
2098 prval("ipv6InUnknownProtos", ip6->ipv6InUnknownProtos);
2099 prval("ipv6InTruncatedPkts", ip6->ipv6InTruncatedPkts);
2100 prval("ipv6InDiscards", ip6->ipv6InDiscards);
2101 prval("ipv6InDelivers", ip6->ipv6InDelivers);
2102 prval("ipv6OutForwDatagrams", ip6->ipv6OutForwDatagrams);
2103 prval("ipv6OutRequests", ip6->ipv6OutRequests);
2104 prval("ipv6OutDiscards", ip6->ipv6OutDiscards);
2105 prval("ipv6OutNoRoutes", ip6->ipv6OutNoRoutes);
2106 prval("ipv6OutFragOKs", ip6->ipv6OutFragOKs);
2107 prval("ipv6OutFragFails", ip6->ipv6OutFragFails);
2108 prval("ipv6OutFragCreates", ip6->ipv6OutFragCreates);
2109 prval("ipv6ReasmReqds", ip6->ipv6ReasmReqds);
2110 prval("ipv6ReasmOKs", ip6->ipv6ReasmOKs);
2111 prval("ipv6ReasmFails", ip6->ipv6ReasmFails);
2112 prval("ipv6InMcastPkts", ip6->ipv6InMcastPkts);
2113 prval("ipv6OutMcastPkts", ip6->ipv6OutMcastPkts);
2114 prval("ipv6ReasmDuplicates", ip6->ipv6ReasmDuplicates);
2115 prval("ipv6ReasmPartDups", ip6->ipv6ReasmPartDups);
2116 prval("ipv6ForwProhibits", ip6->ipv6ForwProhibits);
2117 prval("udpInCksumErrs", ip6->udpInCksumErrs);
2118 prval("udpInOverflows", ip6->udpInOverflows);
2119 prval("rawipInOverflows", ip6->rawipInOverflows);
2120 prval("ipv6InIPv4", ip6->ipv6InIPv4);
2121 prval("ipv6OutIPv4", ip6->ipv6OutIPv4);
2122 prval("ipv6OutSwitchIPv4", ip6->ipv6OutSwitchIPv4);
2123 prval_end();
2126 static void
2127 print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6)
2129 prval_init();
2130 prval("icmp6InMsgs", icmp6->ipv6IfIcmpInMsgs);
2131 prval("icmp6InErrors", icmp6->ipv6IfIcmpInErrors);
2132 prval("icmp6InDestUnreachs", icmp6->ipv6IfIcmpInDestUnreachs);
2133 prval("icmp6InAdminProhibs", icmp6->ipv6IfIcmpInAdminProhibs);
2134 prval("icmp6InTimeExcds", icmp6->ipv6IfIcmpInTimeExcds);
2135 prval("icmp6InParmProblems", icmp6->ipv6IfIcmpInParmProblems);
2136 prval("icmp6InPktTooBigs", icmp6->ipv6IfIcmpInPktTooBigs);
2137 prval("icmp6InEchos", icmp6->ipv6IfIcmpInEchos);
2138 prval("icmp6InEchoReplies", icmp6->ipv6IfIcmpInEchoReplies);
2139 prval("icmp6InRouterSols", icmp6->ipv6IfIcmpInRouterSolicits);
2140 prval("icmp6InRouterAds",
2141 icmp6->ipv6IfIcmpInRouterAdvertisements);
2142 prval("icmp6InNeighborSols", icmp6->ipv6IfIcmpInNeighborSolicits);
2143 prval("icmp6InNeighborAds",
2144 icmp6->ipv6IfIcmpInNeighborAdvertisements);
2145 prval("icmp6InRedirects", icmp6->ipv6IfIcmpInRedirects);
2146 prval("icmp6InBadRedirects", icmp6->ipv6IfIcmpInBadRedirects);
2147 prval("icmp6InGroupQueries", icmp6->ipv6IfIcmpInGroupMembQueries);
2148 prval("icmp6InGroupResps", icmp6->ipv6IfIcmpInGroupMembResponses);
2149 prval("icmp6InGroupReds", icmp6->ipv6IfIcmpInGroupMembReductions);
2150 prval("icmp6InOverflows", icmp6->ipv6IfIcmpInOverflows);
2151 prval_end();
2152 prval_init();
2153 prval("icmp6OutMsgs", icmp6->ipv6IfIcmpOutMsgs);
2154 prval("icmp6OutErrors", icmp6->ipv6IfIcmpOutErrors);
2155 prval("icmp6OutDestUnreachs", icmp6->ipv6IfIcmpOutDestUnreachs);
2156 prval("icmp6OutAdminProhibs", icmp6->ipv6IfIcmpOutAdminProhibs);
2157 prval("icmp6OutTimeExcds", icmp6->ipv6IfIcmpOutTimeExcds);
2158 prval("icmp6OutParmProblems", icmp6->ipv6IfIcmpOutParmProblems);
2159 prval("icmp6OutPktTooBigs", icmp6->ipv6IfIcmpOutPktTooBigs);
2160 prval("icmp6OutEchos", icmp6->ipv6IfIcmpOutEchos);
2161 prval("icmp6OutEchoReplies", icmp6->ipv6IfIcmpOutEchoReplies);
2162 prval("icmp6OutRouterSols", icmp6->ipv6IfIcmpOutRouterSolicits);
2163 prval("icmp6OutRouterAds",
2164 icmp6->ipv6IfIcmpOutRouterAdvertisements);
2165 prval("icmp6OutNeighborSols", icmp6->ipv6IfIcmpOutNeighborSolicits);
2166 prval("icmp6OutNeighborAds",
2167 icmp6->ipv6IfIcmpOutNeighborAdvertisements);
2168 prval("icmp6OutRedirects", icmp6->ipv6IfIcmpOutRedirects);
2169 prval("icmp6OutGroupQueries", icmp6->ipv6IfIcmpOutGroupMembQueries);
2170 prval("icmp6OutGroupResps",
2171 icmp6->ipv6IfIcmpOutGroupMembResponses);
2172 prval("icmp6OutGroupReds",
2173 icmp6->ipv6IfIcmpOutGroupMembReductions);
2174 prval_end();
2177 static void
2178 print_sctp_stats(mib2_sctp_t *sctp)
2180 prval_init();
2181 pr_sctp_rtoalgo("sctpRtoAlgorithm", sctp->sctpRtoAlgorithm);
2182 prval("sctpRtoMin", sctp->sctpRtoMin);
2183 prval("sctpRtoMax", sctp->sctpRtoMax);
2184 prval("sctpRtoInitial", sctp->sctpRtoInitial);
2185 pr_int_val("sctpMaxAssocs", sctp->sctpMaxAssocs);
2186 prval("sctpValCookieLife", sctp->sctpValCookieLife);
2187 prval("sctpMaxInitRetr", sctp->sctpMaxInitRetr);
2188 prval("sctpCurrEstab", sctp->sctpCurrEstab);
2189 prval("sctpActiveEstab", sctp->sctpActiveEstab);
2190 prval("sctpPassiveEstab", sctp->sctpPassiveEstab);
2191 prval("sctpAborted", sctp->sctpAborted);
2192 prval("sctpShutdowns", sctp->sctpShutdowns);
2193 prval("sctpOutOfBlue", sctp->sctpOutOfBlue);
2194 prval("sctpChecksumError", sctp->sctpChecksumError);
2195 prval64("sctpOutCtrlChunks", sctp->sctpOutCtrlChunks);
2196 prval64("sctpOutOrderChunks", sctp->sctpOutOrderChunks);
2197 prval64("sctpOutUnorderChunks", sctp->sctpOutUnorderChunks);
2198 prval64("sctpRetransChunks", sctp->sctpRetransChunks);
2199 prval("sctpOutAck", sctp->sctpOutAck);
2200 prval("sctpOutAckDelayed", sctp->sctpOutAckDelayed);
2201 prval("sctpOutWinUpdate", sctp->sctpOutWinUpdate);
2202 prval("sctpOutFastRetrans", sctp->sctpOutFastRetrans);
2203 prval("sctpOutWinProbe", sctp->sctpOutWinProbe);
2204 prval64("sctpInCtrlChunks", sctp->sctpInCtrlChunks);
2205 prval64("sctpInOrderChunks", sctp->sctpInOrderChunks);
2206 prval64("sctpInUnorderChunks", sctp->sctpInUnorderChunks);
2207 prval("sctpInAck", sctp->sctpInAck);
2208 prval("sctpInDupAck", sctp->sctpInDupAck);
2209 prval("sctpInAckUnsent", sctp->sctpInAckUnsent);
2210 prval64("sctpFragUsrMsgs", sctp->sctpFragUsrMsgs);
2211 prval64("sctpReasmUsrMsgs", sctp->sctpReasmUsrMsgs);
2212 prval64("sctpOutSCTPPkts", sctp->sctpOutSCTPPkts);
2213 prval64("sctpInSCTPPkts", sctp->sctpInSCTPPkts);
2214 prval("sctpInInvalidCookie", sctp->sctpInInvalidCookie);
2215 prval("sctpTimRetrans", sctp->sctpTimRetrans);
2216 prval("sctpTimRetransDrop", sctp->sctpTimRetransDrop);
2217 prval("sctpTimHearBeatProbe", sctp->sctpTimHeartBeatProbe);
2218 prval("sctpTimHearBeatDrop", sctp->sctpTimHeartBeatDrop);
2219 prval("sctpListenDrop", sctp->sctpListenDrop);
2220 prval("sctpInClosed", sctp->sctpInClosed);
2221 prval_end();
2224 static void
2225 print_tcp_stats(mib2_tcp_t *tcp)
2227 prval_init();
2228 pr_int_val("tcpRtoAlgorithm", tcp->tcpRtoAlgorithm);
2229 pr_int_val("tcpRtoMin", tcp->tcpRtoMin);
2230 pr_int_val("tcpRtoMax", tcp->tcpRtoMax);
2231 pr_int_val("tcpMaxConn", tcp->tcpMaxConn);
2232 prval("tcpActiveOpens", tcp->tcpActiveOpens);
2233 prval("tcpPassiveOpens", tcp->tcpPassiveOpens);
2234 prval("tcpAttemptFails", tcp->tcpAttemptFails);
2235 prval("tcpEstabResets", tcp->tcpEstabResets);
2236 prval("tcpCurrEstab", tcp->tcpCurrEstab);
2237 prval64("tcpOutSegs", tcp->tcpHCOutSegs);
2238 prval("tcpOutDataSegs", tcp->tcpOutDataSegs);
2239 prval("tcpOutDataBytes", tcp->tcpOutDataBytes);
2240 prval("tcpRetransSegs", tcp->tcpRetransSegs);
2241 prval("tcpRetransBytes", tcp->tcpRetransBytes);
2242 prval("tcpOutAck", tcp->tcpOutAck);
2243 prval("tcpOutAckDelayed", tcp->tcpOutAckDelayed);
2244 prval("tcpOutUrg", tcp->tcpOutUrg);
2245 prval("tcpOutWinUpdate", tcp->tcpOutWinUpdate);
2246 prval("tcpOutWinProbe", tcp->tcpOutWinProbe);
2247 prval("tcpOutControl", tcp->tcpOutControl);
2248 prval("tcpOutRsts", tcp->tcpOutRsts);
2249 prval("tcpOutFastRetrans", tcp->tcpOutFastRetrans);
2250 prval64("tcpInSegs", tcp->tcpHCInSegs);
2251 prval_end();
2252 prval("tcpInAckSegs", tcp->tcpInAckSegs);
2253 prval("tcpInAckBytes", tcp->tcpInAckBytes);
2254 prval("tcpInDupAck", tcp->tcpInDupAck);
2255 prval("tcpInAckUnsent", tcp->tcpInAckUnsent);
2256 prval("tcpInInorderSegs", tcp->tcpInDataInorderSegs);
2257 prval("tcpInInorderBytes", tcp->tcpInDataInorderBytes);
2258 prval("tcpInUnorderSegs", tcp->tcpInDataUnorderSegs);
2259 prval("tcpInUnorderBytes", tcp->tcpInDataUnorderBytes);
2260 prval("tcpInDupSegs", tcp->tcpInDataDupSegs);
2261 prval("tcpInDupBytes", tcp->tcpInDataDupBytes);
2262 prval("tcpInPartDupSegs", tcp->tcpInDataPartDupSegs);
2263 prval("tcpInPartDupBytes", tcp->tcpInDataPartDupBytes);
2264 prval("tcpInPastWinSegs", tcp->tcpInDataPastWinSegs);
2265 prval("tcpInPastWinBytes", tcp->tcpInDataPastWinBytes);
2266 prval("tcpInWinProbe", tcp->tcpInWinProbe);
2267 prval("tcpInWinUpdate", tcp->tcpInWinUpdate);
2268 prval("tcpInClosed", tcp->tcpInClosed);
2269 prval("tcpRttNoUpdate", tcp->tcpRttNoUpdate);
2270 prval("tcpRttUpdate", tcp->tcpRttUpdate);
2271 prval("tcpTimRetrans", tcp->tcpTimRetrans);
2272 prval("tcpTimRetransDrop", tcp->tcpTimRetransDrop);
2273 prval("tcpTimKeepalive", tcp->tcpTimKeepalive);
2274 prval("tcpTimKeepaliveProbe", tcp->tcpTimKeepaliveProbe);
2275 prval("tcpTimKeepaliveDrop", tcp->tcpTimKeepaliveDrop);
2276 prval("tcpListenDrop", tcp->tcpListenDrop);
2277 prval("tcpListenDropQ0", tcp->tcpListenDropQ0);
2278 prval("tcpHalfOpenDrop", tcp->tcpHalfOpenDrop);
2279 prval("tcpOutSackRetrans", tcp->tcpOutSackRetransSegs);
2280 prval_end();
2284 static void
2285 print_udp_stats(mib2_udp_t *udp)
2287 prval_init();
2288 prval64("udpInDatagrams", udp->udpHCInDatagrams);
2289 prval("udpInErrors", udp->udpInErrors);
2290 prval64("udpOutDatagrams", udp->udpHCOutDatagrams);
2291 prval("udpOutErrors", udp->udpOutErrors);
2292 prval_end();
2295 static void
2296 print_rawip_stats(mib2_rawip_t *rawip)
2298 prval_init();
2299 prval("rawipInDatagrams", rawip->rawipInDatagrams);
2300 prval("rawipInErrors", rawip->rawipInErrors);
2301 prval("rawipInCksumErrs", rawip->rawipInCksumErrs);
2302 prval("rawipOutDatagrams", rawip->rawipOutDatagrams);
2303 prval("rawipOutErrors", rawip->rawipOutErrors);
2304 prval_end();
2307 void
2308 print_igmp_stats(struct igmpstat *igps)
2310 (void) printf(" %10u message%s received\n",
2311 igps->igps_rcv_total, PLURAL(igps->igps_rcv_total));
2312 (void) printf(" %10u message%s received with too few bytes\n",
2313 igps->igps_rcv_tooshort, PLURAL(igps->igps_rcv_tooshort));
2314 (void) printf(" %10u message%s received with bad checksum\n",
2315 igps->igps_rcv_badsum, PLURAL(igps->igps_rcv_badsum));
2316 (void) printf(" %10u membership quer%s received\n",
2317 igps->igps_rcv_queries, PLURALY(igps->igps_rcv_queries));
2318 (void) printf(" %10u membership quer%s received with invalid "
2319 "field(s)\n",
2320 igps->igps_rcv_badqueries, PLURALY(igps->igps_rcv_badqueries));
2321 (void) printf(" %10u membership report%s received\n",
2322 igps->igps_rcv_reports, PLURAL(igps->igps_rcv_reports));
2323 (void) printf(" %10u membership report%s received with invalid "
2324 "field(s)\n",
2325 igps->igps_rcv_badreports, PLURAL(igps->igps_rcv_badreports));
2326 (void) printf(" %10u membership report%s received for groups to "
2327 "which we belong\n",
2328 igps->igps_rcv_ourreports, PLURAL(igps->igps_rcv_ourreports));
2329 (void) printf(" %10u membership report%s sent\n",
2330 igps->igps_snd_reports, PLURAL(igps->igps_snd_reports));
2333 static void
2334 print_mrt_stats(struct mrtstat *mrts)
2336 (void) puts("DVMRP multicast routing:");
2337 (void) printf(" %10u hit%s - kernel forwarding cache hits\n",
2338 mrts->mrts_mfc_hits, PLURAL(mrts->mrts_mfc_hits));
2339 (void) printf(" %10u miss%s - kernel forwarding cache misses\n",
2340 mrts->mrts_mfc_misses, PLURALES(mrts->mrts_mfc_misses));
2341 (void) printf(" %10u packet%s potentially forwarded\n",
2342 mrts->mrts_fwd_in, PLURAL(mrts->mrts_fwd_in));
2343 (void) printf(" %10u packet%s actually sent out\n",
2344 mrts->mrts_fwd_out, PLURAL(mrts->mrts_fwd_out));
2345 (void) printf(" %10u upcall%s - upcalls made to mrouted\n",
2346 mrts->mrts_upcalls, PLURAL(mrts->mrts_upcalls));
2347 (void) printf(" %10u packet%s not sent out due to lack of resources\n",
2348 mrts->mrts_fwd_drop, PLURAL(mrts->mrts_fwd_drop));
2349 (void) printf(" %10u datagram%s with malformed tunnel options\n",
2350 mrts->mrts_bad_tunnel, PLURAL(mrts->mrts_bad_tunnel));
2351 (void) printf(" %10u datagram%s with no room for tunnel options\n",
2352 mrts->mrts_cant_tunnel, PLURAL(mrts->mrts_cant_tunnel));
2353 (void) printf(" %10u datagram%s arrived on wrong interface\n",
2354 mrts->mrts_wrong_if, PLURAL(mrts->mrts_wrong_if));
2355 (void) printf(" %10u datagram%s dropped due to upcall Q overflow\n",
2356 mrts->mrts_upq_ovflw, PLURAL(mrts->mrts_upq_ovflw));
2357 (void) printf(" %10u datagram%s cleaned up by the cache\n",
2358 mrts->mrts_cache_cleanups, PLURAL(mrts->mrts_cache_cleanups));
2359 (void) printf(" %10u datagram%s dropped selectively by ratelimiter\n",
2360 mrts->mrts_drop_sel, PLURAL(mrts->mrts_drop_sel));
2361 (void) printf(" %10u datagram%s dropped - bucket Q overflow\n",
2362 mrts->mrts_q_overflow, PLURAL(mrts->mrts_q_overflow));
2363 (void) printf(" %10u datagram%s dropped - larger than bkt size\n",
2364 mrts->mrts_pkt2large, PLURAL(mrts->mrts_pkt2large));
2365 (void) printf("\nPIM multicast routing:\n");
2366 (void) printf(" %10u datagram%s dropped - bad version number\n",
2367 mrts->mrts_pim_badversion, PLURAL(mrts->mrts_pim_badversion));
2368 (void) printf(" %10u datagram%s dropped - bad checksum\n",
2369 mrts->mrts_pim_rcv_badcsum, PLURAL(mrts->mrts_pim_rcv_badcsum));
2370 (void) printf(" %10u datagram%s dropped - bad register packets\n",
2371 mrts->mrts_pim_badregisters, PLURAL(mrts->mrts_pim_badregisters));
2372 (void) printf(
2373 " %10u datagram%s potentially forwarded - register packets\n",
2374 mrts->mrts_pim_regforwards, PLURAL(mrts->mrts_pim_regforwards));
2375 (void) printf(" %10u datagram%s dropped - register send drops\n",
2376 mrts->mrts_pim_regsend_drops, PLURAL(mrts->mrts_pim_regsend_drops));
2377 (void) printf(" %10u datagram%s dropped - packet malformed\n",
2378 mrts->mrts_pim_malformed, PLURAL(mrts->mrts_pim_malformed));
2379 (void) printf(" %10u datagram%s dropped - no memory to forward\n",
2380 mrts->mrts_pim_nomemory, PLURAL(mrts->mrts_pim_nomemory));
2383 static void
2384 sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6, mib2_ipv6IfStatsEntry_t *sum6)
2386 /* First few are not additive */
2387 sum6->ipv6Forwarding = ip6->ipv6Forwarding;
2388 sum6->ipv6DefaultHopLimit = ip6->ipv6DefaultHopLimit;
2390 sum6->ipv6InReceives += ip6->ipv6InReceives;
2391 sum6->ipv6InHdrErrors += ip6->ipv6InHdrErrors;
2392 sum6->ipv6InTooBigErrors += ip6->ipv6InTooBigErrors;
2393 sum6->ipv6InNoRoutes += ip6->ipv6InNoRoutes;
2394 sum6->ipv6InAddrErrors += ip6->ipv6InAddrErrors;
2395 sum6->ipv6InUnknownProtos += ip6->ipv6InUnknownProtos;
2396 sum6->ipv6InTruncatedPkts += ip6->ipv6InTruncatedPkts;
2397 sum6->ipv6InDiscards += ip6->ipv6InDiscards;
2398 sum6->ipv6InDelivers += ip6->ipv6InDelivers;
2399 sum6->ipv6OutForwDatagrams += ip6->ipv6OutForwDatagrams;
2400 sum6->ipv6OutRequests += ip6->ipv6OutRequests;
2401 sum6->ipv6OutDiscards += ip6->ipv6OutDiscards;
2402 sum6->ipv6OutFragOKs += ip6->ipv6OutFragOKs;
2403 sum6->ipv6OutFragFails += ip6->ipv6OutFragFails;
2404 sum6->ipv6OutFragCreates += ip6->ipv6OutFragCreates;
2405 sum6->ipv6ReasmReqds += ip6->ipv6ReasmReqds;
2406 sum6->ipv6ReasmOKs += ip6->ipv6ReasmOKs;
2407 sum6->ipv6ReasmFails += ip6->ipv6ReasmFails;
2408 sum6->ipv6InMcastPkts += ip6->ipv6InMcastPkts;
2409 sum6->ipv6OutMcastPkts += ip6->ipv6OutMcastPkts;
2410 sum6->ipv6OutNoRoutes += ip6->ipv6OutNoRoutes;
2411 sum6->ipv6ReasmDuplicates += ip6->ipv6ReasmDuplicates;
2412 sum6->ipv6ReasmPartDups += ip6->ipv6ReasmPartDups;
2413 sum6->ipv6ForwProhibits += ip6->ipv6ForwProhibits;
2414 sum6->udpInCksumErrs += ip6->udpInCksumErrs;
2415 sum6->udpInOverflows += ip6->udpInOverflows;
2416 sum6->rawipInOverflows += ip6->rawipInOverflows;
2419 static void
2420 sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6, mib2_ipv6IfIcmpEntry_t *sum6)
2422 sum6->ipv6IfIcmpInMsgs += icmp6->ipv6IfIcmpInMsgs;
2423 sum6->ipv6IfIcmpInErrors += icmp6->ipv6IfIcmpInErrors;
2424 sum6->ipv6IfIcmpInDestUnreachs += icmp6->ipv6IfIcmpInDestUnreachs;
2425 sum6->ipv6IfIcmpInAdminProhibs += icmp6->ipv6IfIcmpInAdminProhibs;
2426 sum6->ipv6IfIcmpInTimeExcds += icmp6->ipv6IfIcmpInTimeExcds;
2427 sum6->ipv6IfIcmpInParmProblems += icmp6->ipv6IfIcmpInParmProblems;
2428 sum6->ipv6IfIcmpInPktTooBigs += icmp6->ipv6IfIcmpInPktTooBigs;
2429 sum6->ipv6IfIcmpInEchos += icmp6->ipv6IfIcmpInEchos;
2430 sum6->ipv6IfIcmpInEchoReplies += icmp6->ipv6IfIcmpInEchoReplies;
2431 sum6->ipv6IfIcmpInRouterSolicits += icmp6->ipv6IfIcmpInRouterSolicits;
2432 sum6->ipv6IfIcmpInRouterAdvertisements +=
2433 icmp6->ipv6IfIcmpInRouterAdvertisements;
2434 sum6->ipv6IfIcmpInNeighborSolicits +=
2435 icmp6->ipv6IfIcmpInNeighborSolicits;
2436 sum6->ipv6IfIcmpInNeighborAdvertisements +=
2437 icmp6->ipv6IfIcmpInNeighborAdvertisements;
2438 sum6->ipv6IfIcmpInRedirects += icmp6->ipv6IfIcmpInRedirects;
2439 sum6->ipv6IfIcmpInGroupMembQueries +=
2440 icmp6->ipv6IfIcmpInGroupMembQueries;
2441 sum6->ipv6IfIcmpInGroupMembResponses +=
2442 icmp6->ipv6IfIcmpInGroupMembResponses;
2443 sum6->ipv6IfIcmpInGroupMembReductions +=
2444 icmp6->ipv6IfIcmpInGroupMembReductions;
2445 sum6->ipv6IfIcmpOutMsgs += icmp6->ipv6IfIcmpOutMsgs;
2446 sum6->ipv6IfIcmpOutErrors += icmp6->ipv6IfIcmpOutErrors;
2447 sum6->ipv6IfIcmpOutDestUnreachs += icmp6->ipv6IfIcmpOutDestUnreachs;
2448 sum6->ipv6IfIcmpOutAdminProhibs += icmp6->ipv6IfIcmpOutAdminProhibs;
2449 sum6->ipv6IfIcmpOutTimeExcds += icmp6->ipv6IfIcmpOutTimeExcds;
2450 sum6->ipv6IfIcmpOutParmProblems += icmp6->ipv6IfIcmpOutParmProblems;
2451 sum6->ipv6IfIcmpOutPktTooBigs += icmp6->ipv6IfIcmpOutPktTooBigs;
2452 sum6->ipv6IfIcmpOutEchos += icmp6->ipv6IfIcmpOutEchos;
2453 sum6->ipv6IfIcmpOutEchoReplies += icmp6->ipv6IfIcmpOutEchoReplies;
2454 sum6->ipv6IfIcmpOutRouterSolicits +=
2455 icmp6->ipv6IfIcmpOutRouterSolicits;
2456 sum6->ipv6IfIcmpOutRouterAdvertisements +=
2457 icmp6->ipv6IfIcmpOutRouterAdvertisements;
2458 sum6->ipv6IfIcmpOutNeighborSolicits +=
2459 icmp6->ipv6IfIcmpOutNeighborSolicits;
2460 sum6->ipv6IfIcmpOutNeighborAdvertisements +=
2461 icmp6->ipv6IfIcmpOutNeighborAdvertisements;
2462 sum6->ipv6IfIcmpOutRedirects += icmp6->ipv6IfIcmpOutRedirects;
2463 sum6->ipv6IfIcmpOutGroupMembQueries +=
2464 icmp6->ipv6IfIcmpOutGroupMembQueries;
2465 sum6->ipv6IfIcmpOutGroupMembResponses +=
2466 icmp6->ipv6IfIcmpOutGroupMembResponses;
2467 sum6->ipv6IfIcmpOutGroupMembReductions +=
2468 icmp6->ipv6IfIcmpOutGroupMembReductions;
2469 sum6->ipv6IfIcmpInOverflows += icmp6->ipv6IfIcmpInOverflows;
2472 /* ----------------------------- MRT_STAT_REPORT --------------------------- */
2474 static void
2475 mrt_stat_report(mib_item_t *curritem)
2477 int jtemp = 0;
2478 mib_item_t *tempitem;
2480 if (!(family_selected(AF_INET)))
2481 return;
2483 (void) putchar('\n');
2484 /* 'for' loop 1: */
2485 for (tempitem = curritem;
2486 tempitem;
2487 tempitem = tempitem->next_item) {
2488 if (Xflag) {
2489 (void) printf("\n--- Entry %d ---\n", ++jtemp);
2490 (void) printf("Group = %d, mib_id = %d, "
2491 "length = %d, valp = 0x%p\n",
2492 tempitem->group, tempitem->mib_id,
2493 tempitem->length, tempitem->valp);
2496 if (tempitem->mib_id == 0) {
2497 switch (tempitem->group) {
2498 case EXPER_DVMRP: {
2499 struct mrtstat *mrts;
2500 mrts = (struct mrtstat *)tempitem->valp;
2502 if (!(family_selected(AF_INET)))
2503 continue; /* 'for' loop 1 */
2505 print_mrt_stats(mrts);
2506 break;
2510 } /* 'for' loop 1 ends */
2511 (void) putchar('\n');
2512 (void) fflush(stdout);
2516 * if_stat_total() - Computes totals for interface statistics
2517 * and returns result by updating sumstats.
2519 static void
2520 if_stat_total(struct ifstat *oldstats, struct ifstat *newstats,
2521 struct ifstat *sumstats)
2523 sumstats->ipackets += newstats->ipackets - oldstats->ipackets;
2524 sumstats->opackets += newstats->opackets - oldstats->opackets;
2525 sumstats->ierrors += newstats->ierrors - oldstats->ierrors;
2526 sumstats->oerrors += newstats->oerrors - oldstats->oerrors;
2527 sumstats->collisions += newstats->collisions - oldstats->collisions;
2530 /* --------------------- IF_REPORT (netstat -i) -------------------------- */
2532 static struct ifstat zerostat = {
2533 0LL, 0LL, 0LL, 0LL, 0LL
2536 static void
2537 if_report(mib_item_t *item, char *matchname,
2538 int Iflag_only, boolean_t once_only)
2540 static boolean_t reentry = B_FALSE;
2541 boolean_t alreadydone = B_FALSE;
2542 int jtemp = 0;
2543 uint32_t ifindex_v4 = 0;
2544 uint32_t ifindex_v6 = 0;
2545 boolean_t first_header = B_TRUE;
2547 /* 'for' loop 1: */
2548 for (; item; item = item->next_item) {
2549 if (Xflag) {
2550 (void) printf("\n--- Entry %d ---\n", ++jtemp);
2551 (void) printf("Group = %d, mib_id = %d, "
2552 "length = %d, valp = 0x%p\n",
2553 item->group, item->mib_id, item->length,
2554 item->valp);
2557 switch (item->group) {
2558 case MIB2_IP:
2559 if (item->mib_id != MIB2_IP_ADDR ||
2560 !family_selected(AF_INET))
2561 continue; /* 'for' loop 1 */
2563 static struct ifstat old = {0L, 0L, 0L, 0L, 0L};
2564 static struct ifstat new = {0L, 0L, 0L, 0L, 0L};
2565 struct ifstat sum;
2566 struct iflist *newlist = NULL;
2567 static struct iflist *oldlist = NULL;
2568 kstat_t *ksp;
2570 if (once_only) {
2571 char ifname[LIFNAMSIZ + 1];
2572 char logintname[LIFNAMSIZ + 1];
2573 mib2_ipAddrEntry_t *ap;
2574 struct ifstat stat = {0L, 0L, 0L, 0L, 0L};
2575 boolean_t first = B_TRUE;
2576 uint32_t new_ifindex;
2578 if (Xflag)
2579 (void) printf("if_report: %d items\n",
2580 (item->length)
2581 / sizeof (mib2_ipAddrEntry_t));
2583 /* 'for' loop 2a: */
2584 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2585 (char *)ap < (char *)item->valp
2586 + item->length;
2587 ap++) {
2588 (void) octetstr(&ap->ipAdEntIfIndex,
2589 'a', logintname,
2590 sizeof (logintname));
2591 (void) strcpy(ifname, logintname);
2592 (void) strtok(ifname, ":");
2593 if (matchname != NULL &&
2594 strcmp(matchname, ifname) != 0 &&
2595 strcmp(matchname, logintname) != 0)
2596 continue; /* 'for' loop 2a */
2597 new_ifindex =
2598 if_nametoindex(logintname);
2600 * First lookup the "link" kstats in
2601 * case the link is renamed. Then
2602 * fallback to the legacy kstats for
2603 * those non-GLDv3 links.
2605 if (new_ifindex != ifindex_v4 &&
2606 (((ksp = kstat_lookup(kc, "link", 0,
2607 ifname)) != NULL) ||
2608 ((ksp = kstat_lookup(kc, NULL, -1,
2609 ifname)) != NULL))) {
2610 (void) safe_kstat_read(kc, ksp,
2611 NULL);
2612 stat.ipackets =
2613 kstat_named_value(ksp,
2614 "ipackets");
2615 stat.ierrors =
2616 kstat_named_value(ksp,
2617 "ierrors");
2618 stat.opackets =
2619 kstat_named_value(ksp,
2620 "opackets");
2621 stat.oerrors =
2622 kstat_named_value(ksp,
2623 "oerrors");
2624 stat.collisions =
2625 kstat_named_value(ksp,
2626 "collisions");
2627 if (first) {
2628 if (!first_header)
2629 (void) putchar('\n');
2630 first_header = B_FALSE;
2631 (void) printf(
2632 "%-5.5s %-5.5s%-13.13s "
2633 "%-14.14s %-6.6s %-5.5s "
2634 "%-6.6s %-5.5s %-6.6s "
2635 "%-6.6s\n",
2636 "Name", "Mtu", "Net/Dest",
2637 "Address", "Ipkts",
2638 "Ierrs", "Opkts", "Oerrs",
2639 "Collis", "Queue");
2641 first = B_FALSE;
2643 if_report_ip4(ap, ifname,
2644 logintname, &stat, B_TRUE);
2645 ifindex_v4 = new_ifindex;
2646 } else {
2647 if_report_ip4(ap, ifname,
2648 logintname, &stat, B_FALSE);
2650 } /* 'for' loop 2a ends */
2651 } else if (!alreadydone) {
2652 char ifname[LIFNAMSIZ + 1];
2653 char buf[LIFNAMSIZ + 1];
2654 mib2_ipAddrEntry_t *ap;
2655 struct ifstat t;
2656 struct iflist *tlp = NULL;
2657 struct iflist **nextnew = &newlist;
2658 struct iflist *walkold;
2659 struct iflist *cleanlist;
2660 boolean_t found_if = B_FALSE;
2662 alreadydone = B_TRUE; /* ignore other case */
2665 * Check if there is anything to do.
2667 if (item->length <
2668 sizeof (mib2_ipAddrEntry_t)) {
2669 fail(0, "No compatible interfaces");
2673 * 'for' loop 2b: find the "right" entry:
2674 * If an interface name to match has been
2675 * supplied then try and find it, otherwise
2676 * match the first non-loopback interface found.
2677 * Use lo0 if all else fails.
2679 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2680 (char *)ap < (char *)item->valp
2681 + item->length;
2682 ap++) {
2683 (void) octetstr(&ap->ipAdEntIfIndex,
2684 'a', ifname, sizeof (ifname));
2685 (void) strtok(ifname, ":");
2687 if (matchname) {
2688 if (strcmp(matchname,
2689 ifname) == 0) {
2690 /* 'for' loop 2b */
2691 found_if = B_TRUE;
2692 break;
2694 } else if (strcmp(ifname, "lo0") != 0)
2695 break; /* 'for' loop 2b */
2696 } /* 'for' loop 2b ends */
2698 if (matchname == NULL) {
2699 matchname = ifname;
2700 } else {
2701 if (!found_if)
2702 fail(0, "-I: %s no such "
2703 "interface.", matchname);
2706 if (Iflag_only == 0 || !reentry) {
2707 (void) printf(" input %-6.6s "
2708 "output ",
2709 matchname);
2710 (void) printf(" input (Total) "
2711 "output\n");
2712 (void) printf("%-7.7s %-5.5s %-7.7s "
2713 "%-5.5s %-6.6s ",
2714 "packets", "errs", "packets",
2715 "errs", "colls");
2716 (void) printf("%-7.7s %-5.5s %-7.7s "
2717 "%-5.5s %-6.6s\n",
2718 "packets", "errs", "packets",
2719 "errs", "colls");
2722 sum = zerostat;
2724 /* 'for' loop 2c: */
2725 for (ap = (mib2_ipAddrEntry_t *)item->valp;
2726 (char *)ap < (char *)item->valp
2727 + item->length;
2728 ap++) {
2729 (void) octetstr(&ap->ipAdEntIfIndex,
2730 'a', buf, sizeof (buf));
2731 (void) strtok(buf, ":");
2734 * We have reduced the IP interface
2735 * name, which could have been a
2736 * logical, down to a name suitable
2737 * for use with kstats.
2738 * We treat this name as unique and
2739 * only collate statistics for it once
2740 * per pass. This is to avoid falsely
2741 * amplifying these statistics by the
2742 * the number of logical instances.
2744 if ((tlp != NULL) &&
2745 ((strcmp(buf, tlp->ifname) == 0))) {
2746 continue;
2750 * First lookup the "link" kstats in
2751 * case the link is renamed. Then
2752 * fallback to the legacy kstats for
2753 * those non-GLDv3 links.
2755 if (((ksp = kstat_lookup(kc, "link",
2756 0, buf)) != NULL ||
2757 (ksp = kstat_lookup(kc, NULL, -1,
2758 buf)) != NULL) && (ksp->ks_type ==
2759 KSTAT_TYPE_NAMED)) {
2760 (void) safe_kstat_read(kc, ksp,
2761 NULL);
2764 t.ipackets = kstat_named_value(ksp,
2765 "ipackets");
2766 t.ierrors = kstat_named_value(ksp,
2767 "ierrors");
2768 t.opackets = kstat_named_value(ksp,
2769 "opackets");
2770 t.oerrors = kstat_named_value(ksp,
2771 "oerrors");
2772 t.collisions = kstat_named_value(ksp,
2773 "collisions");
2775 if (strcmp(buf, matchname) == 0)
2776 new = t;
2778 /* Build the interface list */
2780 tlp = malloc(sizeof (struct iflist));
2781 (void) strlcpy(tlp->ifname, buf,
2782 sizeof (tlp->ifname));
2783 tlp->tot = t;
2784 *nextnew = tlp;
2785 nextnew = &tlp->next_if;
2788 * First time through.
2789 * Just add up the interface stats.
2792 if (oldlist == NULL) {
2793 if_stat_total(&zerostat,
2794 &t, &sum);
2795 continue;
2799 * Walk old list for the interface.
2801 * If found, add difference to total.
2803 * If not, an interface has been plumbed
2804 * up. In this case, we will simply
2805 * ignore the new interface until the
2806 * next interval; as there's no easy way
2807 * to acquire statistics between time
2808 * of the plumb and the next interval
2809 * boundary. This results in inaccurate
2810 * total values for current interval.
2812 * Note the case when an interface is
2813 * unplumbed; as similar problems exist.
2814 * The unplumbed interface is not in the
2815 * current list, and there's no easy way
2816 * to account for the statistics between
2817 * the previous interval and time of the
2818 * unplumb. Therefore, we (in a sense)
2819 * ignore the removed interface by only
2820 * involving "current" interfaces when
2821 * computing the total statistics.
2822 * Unfortunately, this also results in
2823 * inaccurate values for interval total.
2826 for (walkold = oldlist;
2827 walkold != NULL;
2828 walkold = walkold->next_if) {
2829 if (strcmp(walkold->ifname,
2830 buf) == 0) {
2831 if_stat_total(
2832 &walkold->tot,
2833 &t, &sum);
2834 break;
2838 } /* 'for' loop 2c ends */
2840 *nextnew = NULL;
2842 (void) printf("%-7llu %-5llu %-7llu "
2843 "%-5llu %-6llu ",
2844 new.ipackets - old.ipackets,
2845 new.ierrors - old.ierrors,
2846 new.opackets - old.opackets,
2847 new.oerrors - old.oerrors,
2848 new.collisions - old.collisions);
2850 (void) printf("%-7llu %-5llu %-7llu "
2851 "%-5llu %-6llu\n", sum.ipackets,
2852 sum.ierrors, sum.opackets,
2853 sum.oerrors, sum.collisions);
2856 * Tidy things up once finished.
2859 old = new;
2860 cleanlist = oldlist;
2861 oldlist = newlist;
2862 while (cleanlist != NULL) {
2863 tlp = cleanlist->next_if;
2864 free(cleanlist);
2865 cleanlist = tlp;
2868 break;
2870 case MIB2_IP6:
2871 if (item->mib_id != MIB2_IP6_ADDR ||
2872 !family_selected(AF_INET6))
2873 continue; /* 'for' loop 1 */
2875 static struct ifstat old6 = {0L, 0L, 0L, 0L, 0L};
2876 static struct ifstat new6 = {0L, 0L, 0L, 0L, 0L};
2877 struct ifstat sum6;
2878 struct iflist *newlist6 = NULL;
2879 static struct iflist *oldlist6 = NULL;
2880 kstat_t *ksp;
2882 if (once_only) {
2883 char ifname[LIFNAMSIZ + 1];
2884 char logintname[LIFNAMSIZ + 1];
2885 mib2_ipv6AddrEntry_t *ap6;
2886 struct ifstat stat = {0L, 0L, 0L, 0L, 0L};
2887 boolean_t first = B_TRUE;
2888 uint32_t new_ifindex;
2890 if (Xflag)
2891 (void) printf("if_report: %d items\n",
2892 (item->length)
2893 / sizeof (mib2_ipv6AddrEntry_t));
2894 /* 'for' loop 2d: */
2895 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
2896 (char *)ap6 < (char *)item->valp
2897 + item->length;
2898 ap6++) {
2899 (void) octetstr(&ap6->ipv6AddrIfIndex,
2900 'a', logintname,
2901 sizeof (logintname));
2902 (void) strcpy(ifname, logintname);
2903 (void) strtok(ifname, ":");
2904 if (matchname != NULL &&
2905 strcmp(matchname, ifname) != 0 &&
2906 strcmp(matchname, logintname) != 0)
2907 continue; /* 'for' loop 2d */
2908 new_ifindex =
2909 if_nametoindex(logintname);
2912 * First lookup the "link" kstats in
2913 * case the link is renamed. Then
2914 * fallback to the legacy kstats for
2915 * those non-GLDv3 links.
2917 if (new_ifindex != ifindex_v6 &&
2918 ((ksp = kstat_lookup(kc, "link", 0,
2919 ifname)) != NULL ||
2920 (ksp = kstat_lookup(kc, NULL, -1,
2921 ifname)) != NULL)) {
2922 (void) safe_kstat_read(kc, ksp,
2923 NULL);
2924 stat.ipackets =
2925 kstat_named_value(ksp,
2926 "ipackets");
2927 stat.ierrors =
2928 kstat_named_value(ksp,
2929 "ierrors");
2930 stat.opackets =
2931 kstat_named_value(ksp,
2932 "opackets");
2933 stat.oerrors =
2934 kstat_named_value(ksp,
2935 "oerrors");
2936 stat.collisions =
2937 kstat_named_value(ksp,
2938 "collisions");
2939 if (first) {
2940 if (!first_header)
2941 (void) putchar('\n');
2942 first_header = B_FALSE;
2943 (void) printf(
2944 "%-5.5s %-5.5s%"
2945 "-27.27s %-27.27s "
2946 "%-6.6s %-5.5s "
2947 "%-6.6s %-5.5s "
2948 "%-6.6s\n",
2949 "Name", "Mtu",
2950 "Net/Dest",
2951 "Address", "Ipkts",
2952 "Ierrs", "Opkts",
2953 "Oerrs", "Collis");
2954 first = B_FALSE;
2956 if_report_ip6(ap6, ifname,
2957 logintname, &stat, B_TRUE);
2958 ifindex_v6 = new_ifindex;
2959 } else {
2960 if_report_ip6(ap6, ifname,
2961 logintname, &stat, B_FALSE);
2963 } /* 'for' loop 2d ends */
2964 } else if (!alreadydone) {
2965 char ifname[LIFNAMSIZ + 1];
2966 char buf[IFNAMSIZ + 1];
2967 mib2_ipv6AddrEntry_t *ap6;
2968 struct ifstat t;
2969 struct iflist *tlp = NULL;
2970 struct iflist **nextnew = &newlist6;
2971 struct iflist *walkold;
2972 struct iflist *cleanlist;
2973 boolean_t found_if = B_FALSE;
2975 alreadydone = B_TRUE; /* ignore other case */
2978 * Check if there is anything to do.
2980 if (item->length <
2981 sizeof (mib2_ipv6AddrEntry_t)) {
2982 fail(0, "No compatible interfaces");
2986 * 'for' loop 2e: find the "right" entry:
2987 * If an interface name to match has been
2988 * supplied then try and find it, otherwise
2989 * match the first non-loopback interface found.
2990 * Use lo0 if all else fails.
2992 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
2993 (char *)ap6 < (char *)item->valp
2994 + item->length;
2995 ap6++) {
2996 (void) octetstr(&ap6->ipv6AddrIfIndex,
2997 'a', ifname, sizeof (ifname));
2998 (void) strtok(ifname, ":");
3000 if (matchname) {
3001 if (strcmp(matchname,
3002 ifname) == 0) {
3003 /* 'for' loop 2e */
3004 found_if = B_TRUE;
3005 break;
3007 } else if (strcmp(ifname, "lo0") != 0)
3008 break; /* 'for' loop 2e */
3009 } /* 'for' loop 2e ends */
3011 if (matchname == NULL) {
3012 matchname = ifname;
3013 } else {
3014 if (!found_if)
3015 fail(0, "-I: %s no such "
3016 "interface.", matchname);
3019 if (Iflag_only == 0 || !reentry) {
3020 (void) printf(
3021 " input %-6.6s"
3022 " output ",
3023 matchname);
3024 (void) printf(" input (Total)"
3025 " output\n");
3026 (void) printf("%-7.7s %-5.5s %-7.7s "
3027 "%-5.5s %-6.6s ",
3028 "packets", "errs", "packets",
3029 "errs", "colls");
3030 (void) printf("%-7.7s %-5.5s %-7.7s "
3031 "%-5.5s %-6.6s\n",
3032 "packets", "errs", "packets",
3033 "errs", "colls");
3036 sum6 = zerostat;
3038 /* 'for' loop 2f: */
3039 for (ap6 = (mib2_ipv6AddrEntry_t *)item->valp;
3040 (char *)ap6 < (char *)item->valp
3041 + item->length;
3042 ap6++) {
3043 (void) octetstr(&ap6->ipv6AddrIfIndex,
3044 'a', buf, sizeof (buf));
3045 (void) strtok(buf, ":");
3048 * We have reduced the IP interface
3049 * name, which could have been a
3050 * logical, down to a name suitable
3051 * for use with kstats.
3052 * We treat this name as unique and
3053 * only collate statistics for it once
3054 * per pass. This is to avoid falsely
3055 * amplifying these statistics by the
3056 * the number of logical instances.
3059 if ((tlp != NULL) &&
3060 ((strcmp(buf, tlp->ifname) == 0))) {
3061 continue;
3065 * First lookup the "link" kstats in
3066 * case the link is renamed. Then
3067 * fallback to the legacy kstats for
3068 * those non-GLDv3 links.
3070 if (((ksp = kstat_lookup(kc, "link",
3071 0, buf)) != NULL ||
3072 (ksp = kstat_lookup(kc, NULL, -1,
3073 buf)) != NULL) && (ksp->ks_type ==
3074 KSTAT_TYPE_NAMED)) {
3075 (void) safe_kstat_read(kc,
3076 ksp, NULL);
3079 t.ipackets = kstat_named_value(ksp,
3080 "ipackets");
3081 t.ierrors = kstat_named_value(ksp,
3082 "ierrors");
3083 t.opackets = kstat_named_value(ksp,
3084 "opackets");
3085 t.oerrors = kstat_named_value(ksp,
3086 "oerrors");
3087 t.collisions = kstat_named_value(ksp,
3088 "collisions");
3090 if (strcmp(buf, matchname) == 0)
3091 new6 = t;
3093 /* Build the interface list */
3095 tlp = malloc(sizeof (struct iflist));
3096 (void) strlcpy(tlp->ifname, buf,
3097 sizeof (tlp->ifname));
3098 tlp->tot = t;
3099 *nextnew = tlp;
3100 nextnew = &tlp->next_if;
3103 * First time through.
3104 * Just add up the interface stats.
3107 if (oldlist6 == NULL) {
3108 if_stat_total(&zerostat,
3109 &t, &sum6);
3110 continue;
3114 * Walk old list for the interface.
3116 * If found, add difference to total.
3118 * If not, an interface has been plumbed
3119 * up. In this case, we will simply
3120 * ignore the new interface until the
3121 * next interval; as there's no easy way
3122 * to acquire statistics between time
3123 * of the plumb and the next interval
3124 * boundary. This results in inaccurate
3125 * total values for current interval.
3127 * Note the case when an interface is
3128 * unplumbed; as similar problems exist.
3129 * The unplumbed interface is not in the
3130 * current list, and there's no easy way
3131 * to account for the statistics between
3132 * the previous interval and time of the
3133 * unplumb. Therefore, we (in a sense)
3134 * ignore the removed interface by only
3135 * involving "current" interfaces when
3136 * computing the total statistics.
3137 * Unfortunately, this also results in
3138 * inaccurate values for interval total.
3141 for (walkold = oldlist6;
3142 walkold != NULL;
3143 walkold = walkold->next_if) {
3144 if (strcmp(walkold->ifname,
3145 buf) == 0) {
3146 if_stat_total(
3147 &walkold->tot,
3148 &t, &sum6);
3149 break;
3153 } /* 'for' loop 2f ends */
3155 *nextnew = NULL;
3157 (void) printf("%-7llu %-5llu %-7llu "
3158 "%-5llu %-6llu ",
3159 new6.ipackets - old6.ipackets,
3160 new6.ierrors - old6.ierrors,
3161 new6.opackets - old6.opackets,
3162 new6.oerrors - old6.oerrors,
3163 new6.collisions - old6.collisions);
3165 (void) printf("%-7llu %-5llu %-7llu "
3166 "%-5llu %-6llu\n", sum6.ipackets,
3167 sum6.ierrors, sum6.opackets,
3168 sum6.oerrors, sum6.collisions);
3171 * Tidy things up once finished.
3174 old6 = new6;
3175 cleanlist = oldlist6;
3176 oldlist6 = newlist6;
3177 while (cleanlist != NULL) {
3178 tlp = cleanlist->next_if;
3179 free(cleanlist);
3180 cleanlist = tlp;
3183 break;
3186 (void) fflush(stdout);
3187 } /* 'for' loop 1 ends */
3188 if ((Iflag_only == 0) && (!once_only))
3189 (void) putchar('\n');
3190 reentry = B_TRUE;
3193 static void
3194 if_report_ip4(mib2_ipAddrEntry_t *ap,
3195 char ifname[], char logintname[], struct ifstat *statptr,
3196 boolean_t ksp_not_null) {
3198 char abuf[MAXHOSTNAMELEN + 1];
3199 char dstbuf[MAXHOSTNAMELEN + 1];
3201 if (ksp_not_null) {
3202 (void) printf("%-5s %-4u ",
3203 ifname, ap->ipAdEntInfo.ae_mtu);
3204 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3205 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3206 abuf, sizeof (abuf));
3207 else
3208 (void) pr_netaddr(ap->ipAdEntAddr,
3209 ap->ipAdEntNetMask, abuf, sizeof (abuf));
3210 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3211 "%-6llu %-6llu\n",
3212 abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3213 statptr->ipackets, statptr->ierrors,
3214 statptr->opackets, statptr->oerrors,
3215 statptr->collisions, 0LL);
3218 * Print logical interface info if Aflag set (including logical unit 0)
3220 if (Aflag) {
3221 *statptr = zerostat;
3222 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3223 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3225 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3226 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3227 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3228 sizeof (abuf));
3229 else
3230 (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3231 abuf, sizeof (abuf));
3233 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3234 "%-5s %-6s %-6llu\n", abuf,
3235 pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3236 statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3237 0LL);
3241 static void
3242 if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
3243 char ifname[], char logintname[], struct ifstat *statptr,
3244 boolean_t ksp_not_null) {
3246 char abuf[MAXHOSTNAMELEN + 1];
3247 char dstbuf[MAXHOSTNAMELEN + 1];
3249 if (ksp_not_null) {
3250 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3251 if (ap6->ipv6AddrInfo.ae_flags &
3252 IFF_POINTOPOINT) {
3253 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3254 abuf, sizeof (abuf));
3255 } else {
3256 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3257 ap6->ipv6AddrPfxLength, abuf,
3258 sizeof (abuf));
3260 (void) printf("%-27s %-27s %-6llu %-5llu "
3261 "%-6llu %-5llu %-6llu\n",
3262 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3263 sizeof (dstbuf)),
3264 statptr->ipackets, statptr->ierrors, statptr->opackets,
3265 statptr->oerrors, statptr->collisions);
3268 * Print logical interface info if Aflag set (including logical unit 0)
3270 if (Aflag) {
3271 *statptr = zerostat;
3272 statptr->ipackets = ap6->ipv6AddrInfo.ae_ibcnt;
3273 statptr->opackets = ap6->ipv6AddrInfo.ae_obcnt;
3275 (void) printf("%-5s %-4u ", logintname,
3276 ap6->ipv6AddrInfo.ae_mtu);
3277 if (ap6->ipv6AddrInfo.ae_flags & IFF_POINTOPOINT)
3278 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3279 abuf, sizeof (abuf));
3280 else
3281 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3282 ap6->ipv6AddrPfxLength, abuf, sizeof (abuf));
3283 (void) printf("%-27s %-27s %-6llu %-5s %-6s %-5s %-6s\n",
3284 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3285 sizeof (dstbuf)),
3286 statptr->ipackets, "N/A", "N/A", "N/A", "N/A");
3290 /* --------------------- DHCP_REPORT (netstat -D) ------------------------- */
3292 static boolean_t
3293 dhcp_do_ipc(dhcp_ipc_type_t type, const char *ifname, boolean_t printed_one)
3295 dhcp_ipc_request_t *request;
3296 dhcp_ipc_reply_t *reply;
3297 int error;
3299 request = dhcp_ipc_alloc_request(type, ifname, NULL, 0, DHCP_TYPE_NONE);
3300 if (request == NULL)
3301 fail(0, "dhcp_do_ipc: out of memory");
3303 error = dhcp_ipc_make_request(request, &reply, DHCP_IPC_WAIT_DEFAULT);
3304 if (error != 0) {
3305 free(request);
3306 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error));
3309 free(request);
3310 error = reply->return_code;
3311 if (error == DHCP_IPC_E_UNKIF) {
3312 free(reply);
3313 return (printed_one);
3315 if (error != 0) {
3316 free(reply);
3317 fail(0, "dhcp_do_ipc: %s", dhcp_ipc_strerror(error));
3320 if (timestamp_fmt != NODATE)
3321 print_timestamp(timestamp_fmt);
3323 if (!printed_one)
3324 (void) printf("%s", dhcp_status_hdr_string());
3326 (void) printf("%s", dhcp_status_reply_to_string(reply));
3327 free(reply);
3328 return (B_TRUE);
3332 * dhcp_walk_interfaces: walk the list of interfaces for a given address
3333 * family (af). For each, print out the DHCP status using dhcp_do_ipc.
3335 static boolean_t
3336 dhcp_walk_interfaces(int af, boolean_t printed_one)
3338 struct lifnum lifn;
3339 struct lifconf lifc;
3340 int n_ifs, i, sock_fd;
3342 sock_fd = socket(af, SOCK_DGRAM, 0);
3343 if (sock_fd == -1)
3344 return (printed_one);
3347 * SIOCGLIFNUM is just an estimate. If the ioctl fails, we don't care;
3348 * just drive on and use SIOCGLIFCONF with increasing buffer sizes, as
3349 * is traditional.
3351 (void) memset(&lifn, 0, sizeof (lifn));
3352 lifn.lifn_family = af;
3353 lifn.lifn_flags = LIFC_ALLZONES | LIFC_NOXMIT | LIFC_UNDER_IPMP;
3354 if (ioctl(sock_fd, SIOCGLIFNUM, &lifn) == -1)
3355 n_ifs = LIFN_GUARD_VALUE;
3356 else
3357 n_ifs = lifn.lifn_count + LIFN_GUARD_VALUE;
3359 (void) memset(&lifc, 0, sizeof (lifc));
3360 lifc.lifc_family = af;
3361 lifc.lifc_flags = lifn.lifn_flags;
3362 lifc.lifc_len = n_ifs * sizeof (struct lifreq);
3363 lifc.lifc_buf = malloc(lifc.lifc_len);
3364 if (lifc.lifc_buf != NULL) {
3366 if (ioctl(sock_fd, SIOCGLIFCONF, &lifc) == -1) {
3367 (void) close(sock_fd);
3368 free(lifc.lifc_buf);
3369 return (B_FALSE);
3372 n_ifs = lifc.lifc_len / sizeof (struct lifreq);
3374 for (i = 0; i < n_ifs; i++) {
3375 printed_one = dhcp_do_ipc(DHCP_STATUS |
3376 (af == AF_INET6 ? DHCP_V6 : 0),
3377 lifc.lifc_req[i].lifr_name, printed_one);
3380 (void) close(sock_fd);
3381 free(lifc.lifc_buf);
3382 return (printed_one);
3385 static void
3386 dhcp_report(char *ifname)
3388 boolean_t printed_one;
3390 if (!family_selected(AF_INET) && !family_selected(AF_INET6))
3391 return;
3393 printed_one = B_FALSE;
3394 if (ifname != NULL) {
3395 if (family_selected(AF_INET)) {
3396 printed_one = dhcp_do_ipc(DHCP_STATUS, ifname,
3397 printed_one);
3399 if (family_selected(AF_INET6)) {
3400 printed_one = dhcp_do_ipc(DHCP_STATUS | DHCP_V6,
3401 ifname, printed_one);
3403 if (!printed_one) {
3404 fail(0, "%s: %s", ifname,
3405 dhcp_ipc_strerror(DHCP_IPC_E_UNKIF));
3407 } else {
3408 if (family_selected(AF_INET)) {
3409 printed_one = dhcp_walk_interfaces(AF_INET,
3410 printed_one);
3412 if (family_selected(AF_INET6))
3413 (void) dhcp_walk_interfaces(AF_INET6, printed_one);
3417 /* --------------------- GROUP_REPORT (netstat -g) ------------------------- */
3419 static void
3420 group_report(mib_item_t *item)
3422 mib_item_t *v4grp = NULL, *v4src = NULL;
3423 mib_item_t *v6grp = NULL, *v6src = NULL;
3424 int jtemp = 0;
3425 char ifname[LIFNAMSIZ + 1];
3426 char abuf[MAXHOSTNAMELEN + 1];
3427 ip_member_t *ipmp;
3428 ip_grpsrc_t *ips;
3429 ipv6_member_t *ipmp6;
3430 ipv6_grpsrc_t *ips6;
3431 boolean_t first, first_src;
3433 /* 'for' loop 1: */
3434 for (; item; item = item->next_item) {
3435 if (Xflag) {
3436 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3437 (void) printf("Group = %d, mib_id = %d, "
3438 "length = %d, valp = 0x%p\n",
3439 item->group, item->mib_id, item->length,
3440 item->valp);
3442 if (item->group == MIB2_IP && family_selected(AF_INET)) {
3443 switch (item->mib_id) {
3444 case EXPER_IP_GROUP_MEMBERSHIP:
3445 v4grp = item;
3446 if (Xflag)
3447 (void) printf("item is v4grp info\n");
3448 break;
3449 case EXPER_IP_GROUP_SOURCES:
3450 v4src = item;
3451 if (Xflag)
3452 (void) printf("item is v4src info\n");
3453 break;
3454 default:
3455 continue;
3457 continue;
3459 if (item->group == MIB2_IP6 && family_selected(AF_INET6)) {
3460 switch (item->mib_id) {
3461 case EXPER_IP6_GROUP_MEMBERSHIP:
3462 v6grp = item;
3463 if (Xflag)
3464 (void) printf("item is v6grp info\n");
3465 break;
3466 case EXPER_IP6_GROUP_SOURCES:
3467 v6src = item;
3468 if (Xflag)
3469 (void) printf("item is v6src info\n");
3470 break;
3471 default:
3472 continue;
3477 if (family_selected(AF_INET) && v4grp != NULL) {
3478 if (Xflag)
3479 (void) printf("%u records for ipGroupMember:\n",
3480 v4grp->length / sizeof (ip_member_t));
3482 first = B_TRUE;
3483 for (ipmp = (ip_member_t *)v4grp->valp;
3484 (char *)ipmp < (char *)v4grp->valp + v4grp->length;
3485 /* LINTED: (note 1) */
3486 ipmp = (ip_member_t *)((char *)ipmp + ipMemberEntrySize)) {
3487 if (first) {
3488 (void) puts(v4compat ?
3489 "Group Memberships" :
3490 "Group Memberships: IPv4");
3491 (void) puts("Interface "
3492 "Group RefCnt");
3493 (void) puts("--------- "
3494 "-------------------- ------");
3495 first = B_FALSE;
3498 (void) printf("%-9s %-20s %6u\n",
3499 octetstr(&ipmp->ipGroupMemberIfIndex, 'a',
3500 ifname, sizeof (ifname)),
3501 pr_addr(ipmp->ipGroupMemberAddress,
3502 abuf, sizeof (abuf)),
3503 ipmp->ipGroupMemberRefCnt);
3506 if (!Vflag || v4src == NULL)
3507 continue;
3509 if (Xflag)
3510 (void) printf("scanning %u ipGroupSource "
3511 "records...\n",
3512 v4src->length/sizeof (ip_grpsrc_t));
3514 first_src = B_TRUE;
3515 for (ips = (ip_grpsrc_t *)v4src->valp;
3516 (char *)ips < (char *)v4src->valp + v4src->length;
3517 /* LINTED: (note 1) */
3518 ips = (ip_grpsrc_t *)((char *)ips +
3519 ipGroupSourceEntrySize)) {
3521 * We assume that all source addrs for a given
3522 * interface/group pair are contiguous, so on
3523 * the first non-match after we've found at
3524 * least one, we bail.
3526 if ((ipmp->ipGroupMemberAddress !=
3527 ips->ipGroupSourceGroup) ||
3528 (!octetstrmatch(&ipmp->ipGroupMemberIfIndex,
3529 &ips->ipGroupSourceIfIndex))) {
3530 if (first_src)
3531 continue;
3532 else
3533 break;
3535 if (first_src) {
3536 (void) printf("\t%s: %s\n",
3537 fmodestr(
3538 ipmp->ipGroupMemberFilterMode),
3539 pr_addr(ips->ipGroupSourceAddress,
3540 abuf, sizeof (abuf)));
3541 first_src = B_FALSE;
3542 continue;
3545 (void) printf("\t %s\n",
3546 pr_addr(ips->ipGroupSourceAddress, abuf,
3547 sizeof (abuf)));
3550 (void) putchar('\n');
3553 if (family_selected(AF_INET6) && v6grp != NULL) {
3554 if (Xflag)
3555 (void) printf("%u records for ipv6GroupMember:\n",
3556 v6grp->length / sizeof (ipv6_member_t));
3558 first = B_TRUE;
3559 for (ipmp6 = (ipv6_member_t *)v6grp->valp;
3560 (char *)ipmp6 < (char *)v6grp->valp + v6grp->length;
3561 /* LINTED: (note 1) */
3562 ipmp6 = (ipv6_member_t *)((char *)ipmp6 +
3563 ipv6MemberEntrySize)) {
3564 if (first) {
3565 (void) puts("Group Memberships: "
3566 "IPv6");
3567 (void) puts(" If "
3568 "Group RefCnt");
3569 (void) puts("----- "
3570 "--------------------------- ------");
3571 first = B_FALSE;
3574 (void) printf("%-5s %-27s %5u\n",
3575 ifindex2str(ipmp6->ipv6GroupMemberIfIndex, ifname),
3576 pr_addr6(&ipmp6->ipv6GroupMemberAddress,
3577 abuf, sizeof (abuf)),
3578 ipmp6->ipv6GroupMemberRefCnt);
3580 if (!Vflag || v6src == NULL)
3581 continue;
3583 if (Xflag)
3584 (void) printf("scanning %u ipv6GroupSource "
3585 "records...\n",
3586 v6src->length/sizeof (ipv6_grpsrc_t));
3588 first_src = B_TRUE;
3589 for (ips6 = (ipv6_grpsrc_t *)v6src->valp;
3590 (char *)ips6 < (char *)v6src->valp + v6src->length;
3591 /* LINTED: (note 1) */
3592 ips6 = (ipv6_grpsrc_t *)((char *)ips6 +
3593 ipv6GroupSourceEntrySize)) {
3594 /* same assumption as in the v4 case above */
3595 if ((ipmp6->ipv6GroupMemberIfIndex !=
3596 ips6->ipv6GroupSourceIfIndex) ||
3597 (!IN6_ARE_ADDR_EQUAL(
3598 &ipmp6->ipv6GroupMemberAddress,
3599 &ips6->ipv6GroupSourceGroup))) {
3600 if (first_src)
3601 continue;
3602 else
3603 break;
3605 if (first_src) {
3606 (void) printf("\t%s: %s\n",
3607 fmodestr(
3608 ipmp6->ipv6GroupMemberFilterMode),
3609 pr_addr6(
3610 &ips6->ipv6GroupSourceAddress,
3611 abuf, sizeof (abuf)));
3612 first_src = B_FALSE;
3613 continue;
3616 (void) printf("\t %s\n",
3617 pr_addr6(&ips6->ipv6GroupSourceAddress,
3618 abuf, sizeof (abuf)));
3621 (void) putchar('\n');
3624 (void) putchar('\n');
3625 (void) fflush(stdout);
3628 /* --------------------- DCE_REPORT (netstat -d) ------------------------- */
3630 #define FLBUFSIZE 8
3632 /* Assumes flbuf is at least 5 characters; callers use FLBUFSIZE */
3633 static char *
3634 dceflags2str(uint32_t flags, char *flbuf)
3636 char *str = flbuf;
3638 if (flags & DCEF_DEFAULT)
3639 *str++ = 'D';
3640 if (flags & DCEF_PMTU)
3641 *str++ = 'P';
3642 if (flags & DCEF_UINFO)
3643 *str++ = 'U';
3644 if (flags & DCEF_TOO_SMALL_PMTU)
3645 *str++ = 'S';
3646 *str++ = '\0';
3647 return (flbuf);
3650 static void
3651 dce_report(mib_item_t *item)
3653 mib_item_t *v4dce = NULL;
3654 mib_item_t *v6dce = NULL;
3655 int jtemp = 0;
3656 char ifname[LIFNAMSIZ + 1];
3657 char abuf[MAXHOSTNAMELEN + 1];
3658 char flbuf[FLBUFSIZE];
3659 boolean_t first;
3660 dest_cache_entry_t *dce;
3662 /* 'for' loop 1: */
3663 for (; item; item = item->next_item) {
3664 if (Xflag) {
3665 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3666 (void) printf("Group = %d, mib_id = %d, "
3667 "length = %d, valp = 0x%p\n",
3668 item->group, item->mib_id, item->length,
3669 item->valp);
3671 if (item->group == MIB2_IP && family_selected(AF_INET) &&
3672 item->mib_id == EXPER_IP_DCE) {
3673 v4dce = item;
3674 if (Xflag)
3675 (void) printf("item is v4dce info\n");
3677 if (item->group == MIB2_IP6 && family_selected(AF_INET6) &&
3678 item->mib_id == EXPER_IP_DCE) {
3679 v6dce = item;
3680 if (Xflag)
3681 (void) printf("item is v6dce info\n");
3685 if (family_selected(AF_INET) && v4dce != NULL) {
3686 if (Xflag)
3687 (void) printf("%u records for DestCacheEntry:\n",
3688 v4dce->length / ipDestEntrySize);
3690 first = B_TRUE;
3691 for (dce = (dest_cache_entry_t *)v4dce->valp;
3692 (char *)dce < (char *)v4dce->valp + v4dce->length;
3693 /* LINTED: (note 1) */
3694 dce = (dest_cache_entry_t *)((char *)dce +
3695 ipDestEntrySize)) {
3696 if (first) {
3697 (void) putchar('\n');
3698 (void) puts("Destination Cache Entries: IPv4");
3699 (void) puts(
3700 "Address PMTU Age Flags");
3701 (void) puts(
3702 "-------------------- ------ ----- -----");
3703 first = B_FALSE;
3706 (void) printf("%-20s %6u %5u %-5s\n",
3707 pr_addr(dce->DestIpv4Address, abuf, sizeof (abuf)),
3708 dce->DestPmtu, dce->DestAge,
3709 dceflags2str(dce->DestFlags, flbuf));
3713 if (family_selected(AF_INET6) && v6dce != NULL) {
3714 if (Xflag)
3715 (void) printf("%u records for DestCacheEntry:\n",
3716 v6dce->length / ipDestEntrySize);
3718 first = B_TRUE;
3719 for (dce = (dest_cache_entry_t *)v6dce->valp;
3720 (char *)dce < (char *)v6dce->valp + v6dce->length;
3721 /* LINTED: (note 1) */
3722 dce = (dest_cache_entry_t *)((char *)dce +
3723 ipDestEntrySize)) {
3724 if (first) {
3725 (void) putchar('\n');
3726 (void) puts("Destination Cache Entries: IPv6");
3727 (void) puts(
3728 "Address PMTU "
3729 " Age Flags If ");
3730 (void) puts(
3731 "--------------------------- ------ "
3732 "----- ----- ---");
3733 first = B_FALSE;
3736 (void) printf("%-27s %6u %5u %-5s %s\n",
3737 pr_addr6(&dce->DestIpv6Address, abuf,
3738 sizeof (abuf)),
3739 dce->DestPmtu, dce->DestAge,
3740 dceflags2str(dce->DestFlags, flbuf),
3741 dce->DestIfindex == 0 ? "" :
3742 ifindex2str(dce->DestIfindex, ifname));
3745 (void) fflush(stdout);
3748 /* --------------------- ARP_REPORT (netstat -p) -------------------------- */
3750 static void
3751 arp_report(mib_item_t *item)
3753 int jtemp = 0;
3754 char ifname[LIFNAMSIZ + 1];
3755 char abuf[MAXHOSTNAMELEN + 1];
3756 char maskbuf[STR_EXPAND * OCTET_LENGTH + 1];
3757 char flbuf[32]; /* ACE_F_ flags */
3758 char xbuf[STR_EXPAND * OCTET_LENGTH + 1];
3759 mib2_ipNetToMediaEntry_t *np;
3760 int flags;
3761 boolean_t first;
3763 if (!(family_selected(AF_INET)))
3764 return;
3766 /* 'for' loop 1: */
3767 for (; item; item = item->next_item) {
3768 if (Xflag) {
3769 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3770 (void) printf("Group = %d, mib_id = %d, "
3771 "length = %d, valp = 0x%p\n",
3772 item->group, item->mib_id, item->length,
3773 item->valp);
3775 if (!(item->group == MIB2_IP && item->mib_id == MIB2_IP_MEDIA))
3776 continue; /* 'for' loop 1 */
3778 if (Xflag)
3779 (void) printf("%u records for "
3780 "ipNetToMediaEntryTable:\n",
3781 item->length/sizeof (mib2_ipNetToMediaEntry_t));
3783 first = B_TRUE;
3784 /* 'for' loop 2: */
3785 for (np = (mib2_ipNetToMediaEntry_t *)item->valp;
3786 (char *)np < (char *)item->valp + item->length;
3787 /* LINTED: (note 1) */
3788 np = (mib2_ipNetToMediaEntry_t *)((char *)np +
3789 ipNetToMediaEntrySize)) {
3790 if (first) {
3791 (void) puts(v4compat ?
3792 "Net to Media Table" :
3793 "Net to Media Table: IPv4");
3794 (void) puts("Device "
3795 " IP Address Mask "
3796 "Flags Phys Addr");
3797 (void) puts("------ "
3798 "-------------------- --------------- "
3799 "-------- ---------------");
3800 first = B_FALSE;
3803 flbuf[0] = '\0';
3804 flags = np->ipNetToMediaInfo.ntm_flags;
3806 * Note that not all flags are possible at the same
3807 * time. Patterns: SPLAy DUo
3809 if (flags & ACE_F_PERMANENT)
3810 (void) strcat(flbuf, "S");
3811 if (flags & ACE_F_PUBLISH)
3812 (void) strcat(flbuf, "P");
3813 if (flags & ACE_F_DYING)
3814 (void) strcat(flbuf, "D");
3815 if (!(flags & ACE_F_RESOLVED))
3816 (void) strcat(flbuf, "U");
3817 if (flags & ACE_F_MAPPING)
3818 (void) strcat(flbuf, "M");
3819 if (flags & ACE_F_MYADDR)
3820 (void) strcat(flbuf, "L");
3821 if (flags & ACE_F_UNVERIFIED)
3822 (void) strcat(flbuf, "d");
3823 if (flags & ACE_F_AUTHORITY)
3824 (void) strcat(flbuf, "A");
3825 if (flags & ACE_F_OLD)
3826 (void) strcat(flbuf, "o");
3827 if (flags & ACE_F_DELAYED)
3828 (void) strcat(flbuf, "y");
3829 (void) printf("%-6s %-20s %-15s %-8s %s\n",
3830 octetstr(&np->ipNetToMediaIfIndex, 'a',
3831 ifname, sizeof (ifname)),
3832 pr_addr(np->ipNetToMediaNetAddress,
3833 abuf, sizeof (abuf)),
3834 octetstr(&np->ipNetToMediaInfo.ntm_mask, 'd',
3835 maskbuf, sizeof (maskbuf)),
3836 flbuf,
3837 octetstr(&np->ipNetToMediaPhysAddress, 'h',
3838 xbuf, sizeof (xbuf)));
3839 } /* 'for' loop 2 ends */
3840 } /* 'for' loop 1 ends */
3841 (void) fflush(stdout);
3844 /* --------------------- NDP_REPORT (netstat -p) -------------------------- */
3846 static void
3847 ndp_report(mib_item_t *item)
3849 int jtemp = 0;
3850 char abuf[MAXHOSTNAMELEN + 1];
3851 char *state;
3852 char *type;
3853 char xbuf[STR_EXPAND * OCTET_LENGTH + 1];
3854 mib2_ipv6NetToMediaEntry_t *np6;
3855 char ifname[LIFNAMSIZ + 1];
3856 boolean_t first;
3858 if (!(family_selected(AF_INET6)))
3859 return;
3861 /* 'for' loop 1: */
3862 for (; item; item = item->next_item) {
3863 if (Xflag) {
3864 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3865 (void) printf("Group = %d, mib_id = %d, "
3866 "length = %d, valp = 0x%p\n",
3867 item->group, item->mib_id, item->length,
3868 item->valp);
3870 if (!(item->group == MIB2_IP6 &&
3871 item->mib_id == MIB2_IP6_MEDIA))
3872 continue; /* 'for' loop 1 */
3874 first = B_TRUE;
3875 /* 'for' loop 2: */
3876 for (np6 = (mib2_ipv6NetToMediaEntry_t *)item->valp;
3877 (char *)np6 < (char *)item->valp + item->length;
3878 /* LINTED: (note 1) */
3879 np6 = (mib2_ipv6NetToMediaEntry_t *)((char *)np6 +
3880 ipv6NetToMediaEntrySize)) {
3881 if (first) {
3882 (void) puts("\nNet to Media Table: IPv6");
3883 (void) puts(" If Physical Address "
3884 " Type State Destination/Mask");
3885 (void) puts("----- ----------------- "
3886 "------- ------------ "
3887 "---------------------------");
3888 first = B_FALSE;
3891 switch (np6->ipv6NetToMediaState) {
3892 case ND_INCOMPLETE:
3893 state = "INCOMPLETE";
3894 break;
3895 case ND_REACHABLE:
3896 state = "REACHABLE";
3897 break;
3898 case ND_STALE:
3899 state = "STALE";
3900 break;
3901 case ND_DELAY:
3902 state = "DELAY";
3903 break;
3904 case ND_PROBE:
3905 state = "PROBE";
3906 break;
3907 case ND_UNREACHABLE:
3908 state = "UNREACHABLE";
3909 break;
3910 default:
3911 state = "UNKNOWN";
3914 switch (np6->ipv6NetToMediaType) {
3915 case 1:
3916 type = "other";
3917 break;
3918 case 2:
3919 type = "dynamic";
3920 break;
3921 case 3:
3922 type = "static";
3923 break;
3924 case 4:
3925 type = "local";
3926 break;
3928 (void) printf("%-5s %-17s %-7s %-12s %-27s\n",
3929 ifindex2str(np6->ipv6NetToMediaIfIndex, ifname),
3930 octetstr(&np6->ipv6NetToMediaPhysAddress, 'h',
3931 xbuf, sizeof (xbuf)),
3932 type,
3933 state,
3934 pr_addr6(&np6->ipv6NetToMediaNetAddress,
3935 abuf, sizeof (abuf)));
3936 } /* 'for' loop 2 ends */
3937 } /* 'for' loop 1 ends */
3938 (void) putchar('\n');
3939 (void) fflush(stdout);
3942 /* ------------------------- ire_report (netstat -r) ------------------------ */
3944 static boolean_t ire_report_item_v4(const mib2_ipRouteEntry_t *, boolean_t);
3945 static boolean_t ire_report_item_v6(const mib2_ipv6RouteEntry_t *, boolean_t);
3947 static void
3948 ire_report(const mib_item_t *item)
3950 int jtemp = 0;
3951 boolean_t print_hdr_once_v4 = B_TRUE;
3952 boolean_t print_hdr_once_v6 = B_TRUE;
3953 mib2_ipRouteEntry_t *rp;
3954 mib2_ipv6RouteEntry_t *rp6;
3956 for (; item != NULL; item = item->next_item) {
3957 if (Xflag) {
3958 (void) printf("\n--- Entry %d ---\n", ++jtemp);
3959 (void) printf("Group = %d, mib_id = %d, "
3960 "length = %d, valp = 0x%p\n",
3961 item->group, item->mib_id,
3962 item->length, item->valp);
3964 if (!((item->group == MIB2_IP &&
3965 item->mib_id == MIB2_IP_ROUTE) ||
3966 (item->group == MIB2_IP6 &&
3967 item->mib_id == MIB2_IP6_ROUTE)))
3968 continue; /* 'for' loop 1 */
3970 if (item->group == MIB2_IP && !family_selected(AF_INET))
3971 continue; /* 'for' loop 1 */
3972 else if (item->group == MIB2_IP6 && !family_selected(AF_INET6))
3973 continue; /* 'for' loop 1 */
3975 if (Xflag) {
3976 if (item->group == MIB2_IP) {
3977 (void) printf("%u records for "
3978 "ipRouteEntryTable:\n",
3979 item->length/sizeof (mib2_ipRouteEntry_t));
3980 } else {
3981 (void) printf("%u records for "
3982 "ipv6RouteEntryTable:\n",
3983 item->length/
3984 sizeof (mib2_ipv6RouteEntry_t));
3988 if (item->group == MIB2_IP) {
3989 for (rp = (mib2_ipRouteEntry_t *)item->valp;
3990 (char *)rp < (char *)item->valp + item->length;
3991 /* LINTED: (note 1) */
3992 rp = (mib2_ipRouteEntry_t *)((char *)rp +
3993 ipRouteEntrySize)) {
3994 print_hdr_once_v4 = ire_report_item_v4(rp,
3995 print_hdr_once_v4);
3997 } else {
3998 for (rp6 = (mib2_ipv6RouteEntry_t *)item->valp;
3999 (char *)rp6 < (char *)item->valp + item->length;
4000 /* LINTED: (note 1) */
4001 rp6 = (mib2_ipv6RouteEntry_t *)((char *)rp6 +
4002 ipv6RouteEntrySize)) {
4003 print_hdr_once_v6 = ire_report_item_v6(rp6,
4004 print_hdr_once_v6);
4007 } /* 'for' loop 1 ends */
4008 (void) fflush(stdout);
4012 * Match a user-supplied device name. We do this by string because
4013 * the MIB2 interface gives us interface name strings rather than
4014 * ifIndex numbers. The "none" rule matches only routes with no
4015 * interface. The "any" rule matches routes with any non-blank
4016 * interface. A base name ("hme0") matches all aliases as well
4017 * ("hme0:1").
4019 static boolean_t
4020 dev_name_match(const DeviceName *devnam, const char *ifname)
4022 int iflen;
4024 if (ifname == NULL)
4025 return (devnam->o_length == 0); /* "none" */
4026 if (*ifname == '\0')
4027 return (devnam->o_length != 0); /* "any" */
4028 iflen = strlen(ifname);
4029 /* The check for ':' here supports interface aliases. */
4030 if (iflen > devnam->o_length ||
4031 (iflen < devnam->o_length && devnam->o_bytes[iflen] != ':'))
4032 return (B_FALSE);
4033 return (strncmp(ifname, devnam->o_bytes, iflen) == 0);
4037 * Match a user-supplied IP address list. The "any" rule matches any
4038 * non-zero address. The "none" rule matches only the zero address.
4039 * IPv6 addresses supplied by the user are ignored. If the user
4040 * supplies a subnet mask, then match routes that are at least that
4041 * specific (use the user's mask). If the user supplies only an
4042 * address, then select any routes that would match (use the route's
4043 * mask).
4045 static boolean_t
4046 v4_addr_match(IpAddress addr, IpAddress mask, const filter_t *fp)
4048 char **app;
4049 char *aptr;
4050 in_addr_t faddr, fmask;
4052 if (fp->u.a.f_address == NULL) {
4053 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask))
4054 return (addr != INADDR_ANY); /* "any" */
4055 else
4056 return (addr == INADDR_ANY); /* "none" */
4058 if (!IN6_IS_V4MASK(fp->u.a.f_mask))
4059 return (B_FALSE);
4060 IN6_V4MAPPED_TO_IPADDR(&fp->u.a.f_mask, fmask);
4061 if (fmask != IP_HOST_MASK) {
4062 if (fmask > mask)
4063 return (B_FALSE);
4064 mask = fmask;
4066 for (app = fp->u.a.f_address->h_addr_list; (aptr = *app) != NULL; app++)
4067 /* LINTED: (note 1) */
4068 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr)) {
4069 /* LINTED: (note 1) */
4070 IN6_V4MAPPED_TO_IPADDR((in6_addr_t *)aptr, faddr);
4071 if (((faddr ^ addr) & mask) == 0)
4072 return (B_TRUE);
4074 return (B_FALSE);
4078 * Run through the filter list for an IPv4 MIB2 route entry. If all
4079 * filters of a given type fail to match, then the route is filtered
4080 * out (not displayed). If no filter is given or at least one filter
4081 * of each type matches, then display the route.
4083 static boolean_t
4084 ire_filter_match_v4(const mib2_ipRouteEntry_t *rp, uint_t flag_b)
4086 filter_t *fp;
4087 int idx;
4089 /* 'for' loop 1: */
4090 for (idx = 0; idx < NFILTERKEYS; idx++)
4091 if ((fp = filters[idx]) != NULL) {
4092 /* 'for' loop 2: */
4093 for (; fp != NULL; fp = fp->f_next) {
4094 switch (idx) {
4095 case FK_AF:
4096 if (fp->u.f_family != AF_INET)
4097 continue; /* 'for' loop 2 */
4098 break;
4099 case FK_OUTIF:
4100 if (!dev_name_match(&rp->ipRouteIfIndex,
4101 fp->u.f_ifname))
4102 continue; /* 'for' loop 2 */
4103 break;
4104 case FK_DST:
4105 if (!v4_addr_match(rp->ipRouteDest,
4106 rp->ipRouteMask, fp))
4107 continue; /* 'for' loop 2 */
4108 break;
4109 case FK_FLAGS:
4110 if ((flag_b & fp->u.f.f_flagset) !=
4111 fp->u.f.f_flagset ||
4112 (flag_b & fp->u.f.f_flagclear))
4113 continue; /* 'for' loop 2 */
4114 break;
4116 break;
4117 } /* 'for' loop 2 ends */
4118 if (fp == NULL)
4119 return (B_FALSE);
4121 /* 'for' loop 1 ends */
4122 return (B_TRUE);
4126 * Given an IPv4 MIB2 route entry, form the list of flags for the
4127 * route.
4129 static uint_t
4130 form_v4_route_flags(const mib2_ipRouteEntry_t *rp, char *flags)
4132 uint_t flag_b;
4134 flag_b = FLF_U;
4135 (void) strcpy(flags, "U");
4136 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */
4137 if (rp->ipRouteInfo.re_flags & RTF_INDIRECT) {
4138 (void) strcat(flags, "I");
4139 flag_b |= FLF_I;
4140 } else if (rp->ipRouteInfo.re_ire_type & IRE_OFFLINK) {
4141 (void) strcat(flags, "G");
4142 flag_b |= FLF_G;
4144 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */
4145 if (rp->ipRouteInfo.re_ire_type & IRE_IF_CLONE) {
4146 (void) strcat(flags, "C");
4147 flag_b |= FLF_C;
4148 } else if (rp->ipRouteMask == IP_HOST_MASK) {
4149 (void) strcat(flags, "H");
4150 flag_b |= FLF_H;
4152 if (rp->ipRouteInfo.re_flags & RTF_DYNAMIC) {
4153 (void) strcat(flags, "D");
4154 flag_b |= FLF_D;
4156 if (rp->ipRouteInfo.re_ire_type == IRE_BROADCAST) { /* Broadcast */
4157 (void) strcat(flags, "b");
4158 flag_b |= FLF_b;
4160 if (rp->ipRouteInfo.re_ire_type == IRE_LOCAL) { /* Local */
4161 (void) strcat(flags, "L");
4162 flag_b |= FLF_L;
4164 if (rp->ipRouteInfo.re_flags & RTF_SETSRC) {
4165 (void) strcat(flags, "S"); /* Setsrc */
4166 flag_b |= FLF_S;
4168 if (rp->ipRouteInfo.re_flags & RTF_REJECT) {
4169 (void) strcat(flags, "R");
4170 flag_b |= FLF_R;
4172 if (rp->ipRouteInfo.re_flags & RTF_BLACKHOLE) {
4173 (void) strcat(flags, "B");
4174 flag_b |= FLF_B;
4176 if (rp->ipRouteInfo.re_flags & RTF_ZONE) {
4177 (void) strcat(flags, "Z");
4178 flag_b |= FLF_Z;
4180 return (flag_b);
4183 static const char ire_hdr_v4[] =
4184 "\n%s Table: IPv4\n";
4185 static const char ire_hdr_v4_compat[] =
4186 "\n%s Table:\n";
4187 static const char ire_hdr_v4_verbose[] =
4188 " Destination Mask Gateway Device "
4189 " MTU Ref Flg Out In/Fwd\n"
4190 "-------------------- --------------- -------------------- ------ "
4191 "----- --- --- ----- ------\n";
4193 static const char ire_hdr_v4_normal[] =
4194 " Destination Gateway Flags Ref Use Interface"
4195 "\n-------------------- -------------------- ----- ----- ---------- "
4196 "---------\n";
4198 static boolean_t
4199 ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first)
4201 char dstbuf[MAXHOSTNAMELEN + 1];
4202 char maskbuf[MAXHOSTNAMELEN + 1];
4203 char gwbuf[MAXHOSTNAMELEN + 1];
4204 char ifname[LIFNAMSIZ + 1];
4205 char flags[10]; /* RTF_ flags */
4206 uint_t flag_b;
4208 if (!(Aflag || (rp->ipRouteInfo.re_ire_type != IRE_IF_CLONE &&
4209 rp->ipRouteInfo.re_ire_type != IRE_BROADCAST &&
4210 rp->ipRouteInfo.re_ire_type != IRE_MULTICAST &&
4211 rp->ipRouteInfo.re_ire_type != IRE_NOROUTE &&
4212 rp->ipRouteInfo.re_ire_type != IRE_LOCAL))) {
4213 return (first);
4216 flag_b = form_v4_route_flags(rp, flags);
4218 if (!ire_filter_match_v4(rp, flag_b))
4219 return (first);
4221 if (first) {
4222 (void) printf(v4compat ? ire_hdr_v4_compat : ire_hdr_v4,
4223 Vflag ? "IRE" : "Routing");
4224 (void) printf(Vflag ? ire_hdr_v4_verbose : ire_hdr_v4_normal);
4225 first = B_FALSE;
4228 if (flag_b & FLF_H) {
4229 (void) pr_addr(rp->ipRouteDest, dstbuf, sizeof (dstbuf));
4230 } else {
4231 (void) pr_net(rp->ipRouteDest, rp->ipRouteMask,
4232 dstbuf, sizeof (dstbuf));
4234 if (Vflag) {
4235 (void) printf("%-20s %-15s %-20s %-6s %5u %3u "
4236 "%-4s%6u %6u\n",
4237 dstbuf,
4238 pr_mask(rp->ipRouteMask, maskbuf, sizeof (maskbuf)),
4239 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
4240 octetstr(&rp->ipRouteIfIndex, 'a', ifname, sizeof (ifname)),
4241 rp->ipRouteInfo.re_max_frag,
4242 rp->ipRouteInfo.re_ref,
4243 flags,
4244 rp->ipRouteInfo.re_obpkt,
4245 rp->ipRouteInfo.re_ibpkt);
4246 } else {
4247 (void) printf("%-20s %-20s %-5s %4u %10u %-9s\n",
4248 dstbuf,
4249 pr_addrnz(rp->ipRouteNextHop, gwbuf, sizeof (gwbuf)),
4250 flags,
4251 rp->ipRouteInfo.re_ref,
4252 rp->ipRouteInfo.re_obpkt + rp->ipRouteInfo.re_ibpkt,
4253 octetstr(&rp->ipRouteIfIndex, 'a',
4254 ifname, sizeof (ifname)));
4256 return (first);
4260 * Match a user-supplied IP address list against an IPv6 route entry.
4261 * If the user specified "any," then any non-zero address matches. If
4262 * the user specified "none," then only the zero address matches. If
4263 * the user specified a subnet mask length, then use that in matching
4264 * routes (select routes that are at least as specific). If the user
4265 * specified only an address, then use the route's mask (select routes
4266 * that would match that address). IPv4 addresses are ignored.
4268 static boolean_t
4269 v6_addr_match(const Ip6Address *addr, int masklen, const filter_t *fp)
4271 const uint8_t *ucp;
4272 int fmasklen;
4273 int i;
4274 char **app;
4275 const uint8_t *aptr;
4277 if (fp->u.a.f_address == NULL) {
4278 if (IN6_IS_ADDR_UNSPECIFIED(&fp->u.a.f_mask)) /* any */
4279 return (!IN6_IS_ADDR_UNSPECIFIED(addr));
4280 return (IN6_IS_ADDR_UNSPECIFIED(addr)); /* "none" */
4282 fmasklen = 0;
4283 /* 'for' loop 1a: */
4284 for (ucp = fp->u.a.f_mask.s6_addr;
4285 ucp < fp->u.a.f_mask.s6_addr + sizeof (fp->u.a.f_mask.s6_addr);
4286 ucp++) {
4287 if (*ucp != 0xff) {
4288 if (*ucp != 0)
4289 fmasklen += 9 - ffs(*ucp);
4290 break; /* 'for' loop 1a */
4292 fmasklen += 8;
4293 } /* 'for' loop 1a ends */
4294 if (fmasklen != IPV6_ABITS) {
4295 if (fmasklen > masklen)
4296 return (B_FALSE);
4297 masklen = fmasklen;
4299 /* 'for' loop 1b: */
4300 for (app = fp->u.a.f_address->h_addr_list;
4301 (aptr = (uint8_t *)*app) != NULL; app++) {
4302 /* LINTED: (note 1) */
4303 if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)aptr))
4304 continue; /* 'for' loop 1b */
4305 ucp = addr->s6_addr;
4306 for (i = masklen; i >= 8; i -= 8)
4307 if (*ucp++ != *aptr++)
4308 break; /* 'for' loop 1b */
4309 if (i == 0 ||
4310 (i < 8 && ((*ucp ^ *aptr) & ~(0xff >> i)) == 0))
4311 return (B_TRUE);
4312 } /* 'for' loop 1b ends */
4313 return (B_FALSE);
4317 * Run through the filter list for an IPv6 MIB2 IRE. For a given
4318 * type, if there's at least one filter and all filters of that type
4319 * fail to match, then the route doesn't match and isn't displayed.
4320 * If at least one matches, or none are specified, for each of the
4321 * types, then the route is selected and displayed.
4323 static boolean_t
4324 ire_filter_match_v6(const mib2_ipv6RouteEntry_t *rp6, uint_t flag_b)
4326 filter_t *fp;
4327 int idx;
4329 /* 'for' loop 1: */
4330 for (idx = 0; idx < NFILTERKEYS; idx++)
4331 if ((fp = filters[idx]) != NULL) {
4332 /* 'for' loop 2: */
4333 for (; fp != NULL; fp = fp->f_next) {
4334 switch (idx) {
4335 case FK_AF:
4336 if (fp->u.f_family != AF_INET6)
4337 /* 'for' loop 2 */
4338 continue;
4339 break;
4340 case FK_OUTIF:
4341 if (!dev_name_match(&rp6->
4342 ipv6RouteIfIndex, fp->u.f_ifname))
4343 /* 'for' loop 2 */
4344 continue;
4345 break;
4346 case FK_DST:
4347 if (!v6_addr_match(&rp6->ipv6RouteDest,
4348 rp6->ipv6RoutePfxLength, fp))
4349 /* 'for' loop 2 */
4350 continue;
4351 break;
4352 case FK_FLAGS:
4353 if ((flag_b & fp->u.f.f_flagset) !=
4354 fp->u.f.f_flagset ||
4355 (flag_b & fp->u.f.f_flagclear))
4356 /* 'for' loop 2 */
4357 continue;
4358 break;
4360 break;
4361 } /* 'for' loop 2 ends */
4362 if (fp == NULL)
4363 return (B_FALSE);
4365 /* 'for' loop 1 ends */
4366 return (B_TRUE);
4370 * Given an IPv6 MIB2 route entry, form the list of flags for the
4371 * route.
4373 static uint_t
4374 form_v6_route_flags(const mib2_ipv6RouteEntry_t *rp6, char *flags)
4376 uint_t flag_b;
4378 flag_b = FLF_U;
4379 (void) strcpy(flags, "U");
4380 /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */
4381 if (rp6->ipv6RouteInfo.re_flags & RTF_INDIRECT) {
4382 (void) strcat(flags, "I");
4383 flag_b |= FLF_I;
4384 } else if (rp6->ipv6RouteInfo.re_ire_type & IRE_OFFLINK) {
4385 (void) strcat(flags, "G");
4386 flag_b |= FLF_G;
4389 /* IRE_IF_CLONE wins over RTF_HOST - don't display both */
4390 if (rp6->ipv6RouteInfo.re_ire_type & IRE_IF_CLONE) {
4391 (void) strcat(flags, "C");
4392 flag_b |= FLF_C;
4393 } else if (rp6->ipv6RoutePfxLength == IPV6_ABITS) {
4394 (void) strcat(flags, "H");
4395 flag_b |= FLF_H;
4398 if (rp6->ipv6RouteInfo.re_flags & RTF_DYNAMIC) {
4399 (void) strcat(flags, "D");
4400 flag_b |= FLF_D;
4402 if (rp6->ipv6RouteInfo.re_ire_type == IRE_LOCAL) { /* Local */
4403 (void) strcat(flags, "L");
4404 flag_b |= FLF_L;
4406 if (rp6->ipv6RouteInfo.re_flags & RTF_SETSRC) {
4407 (void) strcat(flags, "S"); /* Setsrc */
4408 flag_b |= FLF_S;
4410 if (rp6->ipv6RouteInfo.re_flags & RTF_REJECT) {
4411 (void) strcat(flags, "R");
4412 flag_b |= FLF_R;
4414 if (rp6->ipv6RouteInfo.re_flags & RTF_BLACKHOLE) {
4415 (void) strcat(flags, "B");
4416 flag_b |= FLF_B;
4418 if (rp6->ipv6RouteInfo.re_flags & RTF_ZONE) {
4419 (void) strcat(flags, "Z");
4420 flag_b |= FLF_Z;
4422 return (flag_b);
4425 static const char ire_hdr_v6[] =
4426 "\n%s Table: IPv6\n";
4427 static const char ire_hdr_v6_verbose[] =
4428 " Destination/Mask Gateway If MTU "
4429 "Ref Flags Out In/Fwd\n"
4430 "--------------------------- --------------------------- ----- ----- "
4431 "--- ----- ------ ------\n";
4432 static const char ire_hdr_v6_normal[] =
4433 " Destination/Mask Gateway Flags Ref Use "
4434 " If \n"
4435 "--------------------------- --------------------------- ----- --- ------- "
4436 "-----\n";
4438 static boolean_t
4439 ire_report_item_v6(const mib2_ipv6RouteEntry_t *rp6, boolean_t first)
4441 char dstbuf[MAXHOSTNAMELEN + 1];
4442 char gwbuf[MAXHOSTNAMELEN + 1];
4443 char ifname[LIFNAMSIZ + 1];
4444 char flags[10]; /* RTF_ flags */
4445 uint_t flag_b;
4447 if (!(Aflag || (rp6->ipv6RouteInfo.re_ire_type != IRE_IF_CLONE &&
4448 rp6->ipv6RouteInfo.re_ire_type != IRE_MULTICAST &&
4449 rp6->ipv6RouteInfo.re_ire_type != IRE_NOROUTE &&
4450 rp6->ipv6RouteInfo.re_ire_type != IRE_LOCAL))) {
4451 return (first);
4454 flag_b = form_v6_route_flags(rp6, flags);
4456 if (!ire_filter_match_v6(rp6, flag_b))
4457 return (first);
4459 if (first) {
4460 (void) printf(ire_hdr_v6, Vflag ? "IRE" : "Routing");
4461 (void) printf(Vflag ? ire_hdr_v6_verbose : ire_hdr_v6_normal);
4462 first = B_FALSE;
4465 if (Vflag) {
4466 (void) printf("%-27s %-27s %-5s %5u %3u "
4467 "%-5s %6u %6u\n",
4468 pr_prefix6(&rp6->ipv6RouteDest,
4469 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
4470 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
4471 " --" :
4472 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)),
4473 octetstr(&rp6->ipv6RouteIfIndex, 'a',
4474 ifname, sizeof (ifname)),
4475 rp6->ipv6RouteInfo.re_max_frag,
4476 rp6->ipv6RouteInfo.re_ref,
4477 flags,
4478 rp6->ipv6RouteInfo.re_obpkt,
4479 rp6->ipv6RouteInfo.re_ibpkt);
4480 } else {
4481 (void) printf("%-27s %-27s %-5s %3u %7u %-5s\n",
4482 pr_prefix6(&rp6->ipv6RouteDest,
4483 rp6->ipv6RoutePfxLength, dstbuf, sizeof (dstbuf)),
4484 IN6_IS_ADDR_UNSPECIFIED(&rp6->ipv6RouteNextHop) ?
4485 " --" :
4486 pr_addr6(&rp6->ipv6RouteNextHop, gwbuf, sizeof (gwbuf)),
4487 flags,
4488 rp6->ipv6RouteInfo.re_ref,
4489 rp6->ipv6RouteInfo.re_obpkt + rp6->ipv6RouteInfo.re_ibpkt,
4490 octetstr(&rp6->ipv6RouteIfIndex, 'a',
4491 ifname, sizeof (ifname)));
4493 return (first);
4496 /* ------------------------------ TCP_REPORT------------------------------- */
4498 static const char tcp_hdr_v4[] =
4499 "\nTCP: IPv4\n";
4500 static const char tcp_hdr_v4_compat[] =
4501 "\nTCP\n";
4502 static const char tcp_hdr_v4_verbose[] =
4503 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack "
4504 " Rto Mss State\n"
4505 "-------------------- ----- -------- -------- ----- -------- -------- "
4506 "----- ----- -----------\n";
4507 static const char tcp_hdr_v4_normal[] =
4508 " Local Address Remote Address Swind Send-Q Rwind Recv-Q "
4509 " State\n"
4510 "-------------------- -------------------- ----- ------ ----- ------ "
4511 "-----------\n";
4513 static const char tcp_hdr_v6[] =
4514 "\nTCP: IPv6\n";
4515 static const char tcp_hdr_v6_verbose[] =
4516 "Local/Remote Address Swind Snext Suna Rwind Rnext "
4517 " Rack Rto Mss State If\n"
4518 "--------------------------------- ----- -------- -------- ----- -------- "
4519 "-------- ----- ----- ----------- -----\n";
4520 static const char tcp_hdr_v6_normal[] =
4521 " Local Address Remote Address "
4522 "Swind Send-Q Rwind Recv-Q State If\n"
4523 "--------------------------------- --------------------------------- "
4524 "----- ------ ----- ------ ----------- -----\n";
4526 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4527 boolean_t first);
4528 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4529 boolean_t first);
4531 static void
4532 tcp_report(const mib_item_t *item)
4534 int jtemp = 0;
4535 boolean_t print_hdr_once_v4 = B_TRUE;
4536 boolean_t print_hdr_once_v6 = B_TRUE;
4537 mib2_tcpConnEntry_t *tp;
4538 mib2_tcp6ConnEntry_t *tp6;
4540 if (!protocol_selected(IPPROTO_TCP))
4541 return;
4543 for (; item != NULL; item = item->next_item) {
4544 if (Xflag) {
4545 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4546 (void) printf("Group = %d, mib_id = %d, "
4547 "length = %d, valp = 0x%p\n",
4548 item->group, item->mib_id,
4549 item->length, item->valp);
4552 if (!((item->group == MIB2_TCP &&
4553 item->mib_id == MIB2_TCP_CONN) ||
4554 (item->group == MIB2_TCP6 &&
4555 item->mib_id == MIB2_TCP6_CONN)))
4556 continue; /* 'for' loop 1 */
4558 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4559 continue; /* 'for' loop 1 */
4560 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4561 continue; /* 'for' loop 1 */
4563 if (item->group == MIB2_TCP) {
4564 for (tp = (mib2_tcpConnEntry_t *)item->valp;
4565 (char *)tp < (char *)item->valp + item->length;
4566 /* LINTED: (note 1) */
4567 tp = (mib2_tcpConnEntry_t *)((char *)tp +
4568 tcpConnEntrySize)) {
4569 print_hdr_once_v4 = tcp_report_item_v4(tp,
4570 print_hdr_once_v4);
4572 } else {
4573 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4574 (char *)tp6 < (char *)item->valp + item->length;
4575 /* LINTED: (note 1) */
4576 tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4577 tcp6ConnEntrySize)) {
4578 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4579 print_hdr_once_v6);
4582 } /* 'for' loop 1 ends */
4583 (void) fflush(stdout);
4587 static boolean_t
4588 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first)
4591 * lname and fname below are for the hostname as well as the portname
4592 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4593 * as the limit
4595 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4596 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4598 if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4599 return (first); /* Nothing to print */
4601 if (first) {
4602 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4603 (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);
4606 if (Vflag) {
4607 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4608 "%5u %5u\n",
4609 pr_ap(tp->tcpConnLocalAddress,
4610 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4611 pr_ap(tp->tcpConnRemAddress,
4612 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4613 tp->tcpConnEntryInfo.ce_swnd,
4614 tp->tcpConnEntryInfo.ce_snxt,
4615 tp->tcpConnEntryInfo.ce_suna,
4616 tp->tcpConnEntryInfo.ce_rwnd,
4617 tp->tcpConnEntryInfo.ce_rnxt,
4618 tp->tcpConnEntryInfo.ce_rack,
4619 tp->tcpConnEntryInfo.ce_rto,
4620 tp->tcpConnEntryInfo.ce_mss,
4621 mitcp_state(tp->tcpConnEntryInfo.ce_state));
4622 } else {
4623 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4624 (int)tp->tcpConnEntryInfo.ce_suna - 1;
4625 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4626 (int)tp->tcpConnEntryInfo.ce_rack;
4628 (void) printf("%-20s %-20s %5u %6d %5u %6d\n",
4629 pr_ap(tp->tcpConnLocalAddress,
4630 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4631 pr_ap(tp->tcpConnRemAddress,
4632 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4633 tp->tcpConnEntryInfo.ce_swnd,
4634 (sq >= 0) ? sq : 0,
4635 tp->tcpConnEntryInfo.ce_rwnd,
4636 (rq >= 0) ? rq : 0,
4637 mitcp_state(tp->tcpConnEntryInfo.ce_state));
4640 return (B_FALSE);
4643 static boolean_t
4644 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first)
4647 * lname and fname below are for the hostname as well as the portname
4648 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4649 * as the limit
4651 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4652 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4653 char ifname[LIFNAMSIZ + 1];
4654 char *ifnamep;
4656 if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4657 return (first); /* Nothing to print */
4659 if (first) {
4660 (void) printf(tcp_hdr_v6);
4661 (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);
4664 ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
4665 if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
4666 if (ifnamep == NULL)
4667 ifnamep = "";
4669 if (Vflag) {
4670 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
4671 "%5u %5u %-11s %s\n",
4672 pr_ap6(&tp6->tcp6ConnLocalAddress,
4673 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4674 pr_ap6(&tp6->tcp6ConnRemAddress,
4675 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4676 tp6->tcp6ConnEntryInfo.ce_swnd,
4677 tp6->tcp6ConnEntryInfo.ce_snxt,
4678 tp6->tcp6ConnEntryInfo.ce_suna,
4679 tp6->tcp6ConnEntryInfo.ce_rwnd,
4680 tp6->tcp6ConnEntryInfo.ce_rnxt,
4681 tp6->tcp6ConnEntryInfo.ce_rack,
4682 tp6->tcp6ConnEntryInfo.ce_rto,
4683 tp6->tcp6ConnEntryInfo.ce_mss,
4684 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
4685 ifnamep);
4686 } else {
4687 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
4688 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
4689 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
4690 (int)tp6->tcp6ConnEntryInfo.ce_rack;
4692 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
4693 pr_ap6(&tp6->tcp6ConnLocalAddress,
4694 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4695 pr_ap6(&tp6->tcp6ConnRemAddress,
4696 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4697 tp6->tcp6ConnEntryInfo.ce_swnd,
4698 (sq >= 0) ? sq : 0,
4699 tp6->tcp6ConnEntryInfo.ce_rwnd,
4700 (rq >= 0) ? rq : 0,
4701 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state),
4702 ifnamep);
4705 return (B_FALSE);
4708 /* ------------------------------- UDP_REPORT------------------------------- */
4710 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
4711 boolean_t first);
4712 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
4713 boolean_t first);
4715 static const char udp_hdr_v4[] =
4716 " Local Address Remote Address State\n"
4717 "-------------------- -------------------- ----------\n";
4719 static const char udp_hdr_v6[] =
4720 " Local Address Remote Address "
4721 " State If\n"
4722 "--------------------------------- --------------------------------- "
4723 "---------- -----\n";
4725 static void
4726 udp_report(const mib_item_t *item)
4728 int jtemp = 0;
4729 boolean_t print_hdr_once_v4 = B_TRUE;
4730 boolean_t print_hdr_once_v6 = B_TRUE;
4731 mib2_udpEntry_t *ude;
4732 mib2_udp6Entry_t *ude6;
4734 if (!protocol_selected(IPPROTO_UDP))
4735 return;
4737 /* 'for' loop 1: */
4738 for (; item; item = item->next_item) {
4739 if (Xflag) {
4740 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4741 (void) printf("Group = %d, mib_id = %d, "
4742 "length = %d, valp = 0x%p\n",
4743 item->group, item->mib_id,
4744 item->length, item->valp);
4746 if (!((item->group == MIB2_UDP &&
4747 item->mib_id == MIB2_UDP_ENTRY) ||
4748 (item->group == MIB2_UDP6 &&
4749 item->mib_id == MIB2_UDP6_ENTRY)))
4750 continue; /* 'for' loop 1 */
4752 if (item->group == MIB2_UDP && !family_selected(AF_INET))
4753 continue; /* 'for' loop 1 */
4754 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
4755 continue; /* 'for' loop 1 */
4757 /* xxx.xxx.xxx.xxx,pppp sss... */
4758 if (item->group == MIB2_UDP) {
4759 for (ude = (mib2_udpEntry_t *)item->valp;
4760 (char *)ude < (char *)item->valp + item->length;
4761 /* LINTED: (note 1) */
4762 ude = (mib2_udpEntry_t *)((char *)ude +
4763 udpEntrySize)) {
4764 print_hdr_once_v4 = udp_report_item_v4(ude,
4765 print_hdr_once_v4);
4767 } else {
4768 for (ude6 = (mib2_udp6Entry_t *)item->valp;
4769 (char *)ude6 < (char *)item->valp + item->length;
4770 /* LINTED: (note 1) */
4771 ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
4772 udp6EntrySize)) {
4773 print_hdr_once_v6 = udp_report_item_v6(ude6,
4774 print_hdr_once_v6);
4777 } /* 'for' loop 1 ends */
4778 (void) fflush(stdout);
4781 static boolean_t
4782 udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first)
4784 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4785 /* hostname + portname */
4787 if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
4788 return (first); /* Nothing to print */
4790 if (first) {
4791 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
4792 (void) printf(udp_hdr_v4);
4793 first = B_FALSE;
4796 (void) printf("%-20s ",
4797 pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
4798 lname, sizeof (lname)));
4799 (void) printf("%-20s %s\n",
4800 ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
4801 pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
4802 ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
4804 miudp_state(ude->udpEntryInfo.ue_state));
4806 return (first);
4809 static boolean_t
4810 udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first)
4812 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4813 /* hostname + portname */
4814 char ifname[LIFNAMSIZ + 1];
4815 const char *ifnamep;
4817 if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
4818 return (first); /* Nothing to print */
4820 if (first) {
4821 (void) printf("\nUDP: IPv6\n");
4822 (void) printf(udp_hdr_v6);
4823 first = B_FALSE;
4826 ifnamep = (ude6->udp6IfIndex != 0) ?
4827 if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
4829 (void) printf("%-33s ",
4830 pr_ap6(&ude6->udp6LocalAddress,
4831 ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
4832 (void) printf("%-33s %-10s %s\n",
4833 ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
4834 pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
4835 ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
4837 miudp_state(ude6->udp6EntryInfo.ue_state),
4838 ifnamep == NULL ? "" : ifnamep);
4840 return (first);
4843 /* ------------------------------ SCTP_REPORT------------------------------- */
4845 static const char sctp_hdr[] =
4846 "\nSCTP:";
4847 static const char sctp_hdr_normal[] =
4848 " Local Address Remote Address "
4849 "Swind Send-Q Rwind Recv-Q StrsI/O State\n"
4850 "------------------------------- ------------------------------- "
4851 "------ ------ ------ ------ ------- -----------";
4853 static const char *
4854 nssctp_state(int state)
4856 static char sctpsbuf[50];
4857 const char *cp;
4859 switch (state) {
4860 case MIB2_SCTP_closed:
4861 cp = "CLOSED";
4862 break;
4863 case MIB2_SCTP_cookieWait:
4864 cp = "COOKIE_WAIT";
4865 break;
4866 case MIB2_SCTP_cookieEchoed:
4867 cp = "COOKIE_ECHOED";
4868 break;
4869 case MIB2_SCTP_established:
4870 cp = "ESTABLISHED";
4871 break;
4872 case MIB2_SCTP_shutdownPending:
4873 cp = "SHUTDOWN_PENDING";
4874 break;
4875 case MIB2_SCTP_shutdownSent:
4876 cp = "SHUTDOWN_SENT";
4877 break;
4878 case MIB2_SCTP_shutdownReceived:
4879 cp = "SHUTDOWN_RECEIVED";
4880 break;
4881 case MIB2_SCTP_shutdownAckSent:
4882 cp = "SHUTDOWN_ACK_SENT";
4883 break;
4884 case MIB2_SCTP_listen:
4885 cp = "LISTEN";
4886 break;
4887 default:
4888 (void) snprintf(sctpsbuf, sizeof (sctpsbuf),
4889 "UNKNOWN STATE(%d)", state);
4890 cp = sctpsbuf;
4891 break;
4894 return (cp);
4897 static const mib2_sctpConnRemoteEntry_t *
4898 sctp_getnext_rem(const mib_item_t **itemp,
4899 const mib2_sctpConnRemoteEntry_t *current, uint32_t associd)
4901 const mib_item_t *item = *itemp;
4902 const mib2_sctpConnRemoteEntry_t *sre;
4904 for (; item != NULL; item = item->next_item, current = NULL) {
4905 if (!(item->group == MIB2_SCTP &&
4906 item->mib_id == MIB2_SCTP_CONN_REMOTE)) {
4907 continue;
4910 if (current != NULL) {
4911 /* LINTED: (note 1) */
4912 sre = (const mib2_sctpConnRemoteEntry_t *)
4913 ((const char *)current + sctpRemoteEntrySize);
4914 } else {
4915 sre = item->valp;
4917 for (; (char *)sre < (char *)item->valp + item->length;
4918 /* LINTED: (note 1) */
4919 sre = (const mib2_sctpConnRemoteEntry_t *)
4920 ((const char *)sre + sctpRemoteEntrySize)) {
4921 if (sre->sctpAssocId != associd) {
4922 continue;
4924 *itemp = item;
4925 return (sre);
4928 *itemp = NULL;
4929 return (NULL);
4932 static const mib2_sctpConnLocalEntry_t *
4933 sctp_getnext_local(const mib_item_t **itemp,
4934 const mib2_sctpConnLocalEntry_t *current, uint32_t associd)
4936 const mib_item_t *item = *itemp;
4937 const mib2_sctpConnLocalEntry_t *sle;
4939 for (; item != NULL; item = item->next_item, current = NULL) {
4940 if (!(item->group == MIB2_SCTP &&
4941 item->mib_id == MIB2_SCTP_CONN_LOCAL)) {
4942 continue;
4945 if (current != NULL) {
4946 /* LINTED: (note 1) */
4947 sle = (const mib2_sctpConnLocalEntry_t *)
4948 ((const char *)current + sctpLocalEntrySize);
4949 } else {
4950 sle = item->valp;
4952 for (; (char *)sle < (char *)item->valp + item->length;
4953 /* LINTED: (note 1) */
4954 sle = (const mib2_sctpConnLocalEntry_t *)
4955 ((const char *)sle + sctpLocalEntrySize)) {
4956 if (sle->sctpAssocId != associd) {
4957 continue;
4959 *itemp = item;
4960 return (sle);
4963 *itemp = NULL;
4964 return (NULL);
4967 static void
4968 sctp_pr_addr(int type, char *name, int namelen, const in6_addr_t *addr,
4969 int port)
4971 ipaddr_t v4addr;
4972 in6_addr_t v6addr;
4975 * Address is either a v4 mapped or v6 addr. If
4976 * it's a v4 mapped, convert to v4 before
4977 * displaying.
4979 switch (type) {
4980 case MIB2_SCTP_ADDR_V4:
4981 /* v4 */
4982 v6addr = *addr;
4984 IN6_V4MAPPED_TO_IPADDR(&v6addr, v4addr);
4985 if (port > 0) {
4986 (void) pr_ap(v4addr, port, "sctp", name, namelen);
4987 } else {
4988 (void) pr_addr(v4addr, name, namelen);
4990 break;
4992 case MIB2_SCTP_ADDR_V6:
4993 /* v6 */
4994 if (port > 0) {
4995 (void) pr_ap6(addr, port, "sctp", name, namelen);
4996 } else {
4997 (void) pr_addr6(addr, name, namelen);
4999 break;
5001 default:
5002 (void) snprintf(name, namelen, "<unknown addr type>");
5003 break;
5007 static void
5008 sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp)
5010 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5011 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5012 const mib2_sctpConnRemoteEntry_t *sre = NULL;
5013 const mib2_sctpConnLocalEntry_t *sle = NULL;
5014 const mib_item_t *local = head;
5015 const mib_item_t *remote = head;
5016 uint32_t id = sp->sctpAssocId;
5017 boolean_t printfirst = B_TRUE;
5019 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5020 &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5021 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5022 &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5024 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5025 lname, fname,
5026 sp->sctpConnEntryInfo.ce_swnd,
5027 sp->sctpConnEntryInfo.ce_sendq,
5028 sp->sctpConnEntryInfo.ce_rwnd,
5029 sp->sctpConnEntryInfo.ce_recvq,
5030 sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5031 nssctp_state(sp->sctpAssocState));
5033 if (!Vflag) {
5034 return;
5037 /* Print remote addresses/local addresses on following lines */
5038 while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5039 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5040 &sp->sctpAssocRemPrimAddr)) {
5041 if (printfirst == B_TRUE) {
5042 (void) fputs("\t<Remote: ", stdout);
5043 printfirst = B_FALSE;
5044 } else {
5045 (void) fputs(", ", stdout);
5047 sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5048 sizeof (fname), &sre->sctpAssocRemAddr, -1);
5049 if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5050 (void) fputs(fname, stdout);
5051 } else {
5052 (void) printf("(%s)", fname);
5056 if (printfirst == B_FALSE) {
5057 (void) puts(">");
5058 printfirst = B_TRUE;
5060 while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5061 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5062 &sp->sctpAssocLocPrimAddr)) {
5063 if (printfirst == B_TRUE) {
5064 (void) fputs("\t<Local: ", stdout);
5065 printfirst = B_FALSE;
5066 } else {
5067 (void) fputs(", ", stdout);
5069 sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5070 sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5071 (void) fputs(lname, stdout);
5074 if (printfirst == B_FALSE) {
5075 (void) puts(">");
5079 static void
5080 sctp_report(const mib_item_t *item)
5082 const mib_item_t *head;
5083 const mib2_sctpConnEntry_t *sp;
5084 boolean_t first = B_TRUE;
5086 head = item;
5087 for (; item != NULL; item = item->next_item) {
5089 if (!(item->group == MIB2_SCTP &&
5090 item->mib_id == MIB2_SCTP_CONN))
5091 continue;
5093 for (sp = item->valp;
5094 (char *)sp < (char *)item->valp + item->length;
5095 /* LINTED: (note 1) */
5096 sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
5097 if (Aflag ||
5098 sp->sctpAssocState >= MIB2_SCTP_established) {
5099 if (first == B_TRUE) {
5100 (void) puts(sctp_hdr);
5101 (void) puts(sctp_hdr_normal);
5102 first = B_FALSE;
5104 sctp_conn_report_item(head, sp);
5110 static char *
5111 plural(int n)
5113 return (n != 1 ? "s" : "");
5116 static char *
5117 pluraly(int n)
5119 return (n != 1 ? "ies" : "y");
5122 static char *
5123 plurales(int n)
5125 return (n != 1 ? "es" : "");
5128 static char *
5129 pktscale(n)
5130 int n;
5132 static char buf[6];
5133 char t;
5135 if (n < 1024) {
5136 t = ' ';
5137 } else if (n < 1024 * 1024) {
5138 t = 'k';
5139 n /= 1024;
5140 } else if (n < 1024 * 1024 * 1024) {
5141 t = 'm';
5142 n /= 1024 * 1024;
5143 } else {
5144 t = 'g';
5145 n /= 1024 * 1024 * 1024;
5148 (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5149 return (buf);
5152 /* --------------------- mrt_report (netstat -m) -------------------------- */
5154 static void
5155 mrt_report(mib_item_t *item)
5157 int jtemp = 0;
5158 struct vifctl *vip;
5159 vifi_t vifi;
5160 struct mfcctl *mfccp;
5161 int numvifs = 0;
5162 int nmfc = 0;
5163 char abuf[MAXHOSTNAMELEN + 1];
5165 if (!(family_selected(AF_INET)))
5166 return;
5168 /* 'for' loop 1: */
5169 for (; item; item = item->next_item) {
5170 if (Xflag) {
5171 (void) printf("\n--- Entry %d ---\n", ++jtemp);
5172 (void) printf("Group = %d, mib_id = %d, "
5173 "length = %d, valp = 0x%p\n",
5174 item->group, item->mib_id, item->length,
5175 item->valp);
5177 if (item->group != EXPER_DVMRP)
5178 continue; /* 'for' loop 1 */
5180 switch (item->mib_id) {
5182 case EXPER_DVMRP_VIF:
5183 if (Xflag)
5184 (void) printf("%u records for ipVifTable:\n",
5185 item->length/sizeof (struct vifctl));
5186 if (item->length/sizeof (struct vifctl) == 0) {
5187 (void) puts("\nVirtual Interface Table is "
5188 "empty");
5189 break;
5192 (void) puts("\nVirtual Interface Table\n"
5193 " Vif Threshold Rate_Limit Local-Address"
5194 " Remote-Address Pkt_in Pkt_out");
5196 /* 'for' loop 2: */
5197 for (vip = (struct vifctl *)item->valp;
5198 (char *)vip < (char *)item->valp + item->length;
5199 /* LINTED: (note 1) */
5200 vip = (struct vifctl *)((char *)vip +
5201 vifctlSize)) {
5202 if (vip->vifc_lcl_addr.s_addr == 0)
5203 continue; /* 'for' loop 2 */
5204 /* numvifs = vip->vifc_vifi; */
5206 numvifs++;
5207 (void) printf(" %2u %3u "
5208 "%4u %-15.15s",
5209 vip->vifc_vifi,
5210 vip->vifc_threshold,
5211 vip->vifc_rate_limit,
5212 pr_addr(vip->vifc_lcl_addr.s_addr,
5213 abuf, sizeof (abuf)));
5214 (void) printf(" %-15.15s %8u %8u\n",
5215 (vip->vifc_flags & VIFF_TUNNEL) ?
5216 pr_addr(vip->vifc_rmt_addr.s_addr,
5217 abuf, sizeof (abuf)) : "",
5218 vip->vifc_pkt_in,
5219 vip->vifc_pkt_out);
5220 } /* 'for' loop 2 ends */
5222 (void) printf("Numvifs: %d\n", numvifs);
5223 break;
5225 case EXPER_DVMRP_MRT:
5226 if (Xflag)
5227 (void) printf("%u records for ipMfcTable:\n",
5228 item->length/sizeof (struct vifctl));
5229 if (item->length/sizeof (struct vifctl) == 0) {
5230 (void) puts("\nMulticast Forwarding Cache is "
5231 "empty");
5232 break;
5235 (void) puts("\nMulticast Forwarding Cache\n"
5236 " Origin-Subnet Mcastgroup "
5237 "# Pkts In-Vif Out-vifs/Forw-ttl");
5239 for (mfccp = (struct mfcctl *)item->valp;
5240 (char *)mfccp < (char *)item->valp + item->length;
5241 /* LINTED: (note 1) */
5242 mfccp = (struct mfcctl *)((char *)mfccp +
5243 mfcctlSize)) {
5245 nmfc++;
5246 (void) printf(" %-30.15s",
5247 pr_addr(mfccp->mfcc_origin.s_addr,
5248 abuf, sizeof (abuf)));
5249 (void) printf("%-15.15s %6s %3u ",
5250 pr_net(mfccp->mfcc_mcastgrp.s_addr,
5251 mfccp->mfcc_mcastgrp.s_addr,
5252 abuf, sizeof (abuf)),
5253 pktscale((int)mfccp->mfcc_pkt_cnt),
5254 mfccp->mfcc_parent);
5256 for (vifi = 0; vifi < MAXVIFS; ++vifi) {
5257 if (mfccp->mfcc_ttls[vifi]) {
5258 (void) printf(" %u (%u)",
5259 vifi,
5260 mfccp->mfcc_ttls[vifi]);
5264 (void) putchar('\n');
5266 (void) printf("\nTotal no. of entries in cache: %d\n",
5267 nmfc);
5268 break;
5270 } /* 'for' loop 1 ends */
5271 (void) putchar('\n');
5272 (void) fflush(stdout);
5276 * Get the stats for the cache named 'name'. If prefix != 0, then
5277 * interpret the name as a prefix, and sum up stats for all caches
5278 * named 'name*'.
5280 static void
5281 kmem_cache_stats(char *title, char *name, int prefix, int64_t *total_bytes)
5283 int len;
5284 int alloc;
5285 int64_t total_alloc = 0;
5286 int alloc_fail, total_alloc_fail = 0;
5287 int buf_size = 0;
5288 int buf_avail;
5289 int buf_total;
5290 int buf_max, total_buf_max = 0;
5291 int buf_inuse, total_buf_inuse = 0;
5292 kstat_t *ksp;
5293 char buf[256];
5295 len = prefix ? strlen(name) : 256;
5297 /* 'for' loop 1: */
5298 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
5300 if (strcmp(ksp->ks_class, "kmem_cache") != 0)
5301 continue; /* 'for' loop 1 */
5304 * Hack alert: because of the way streams messages are
5305 * allocated, every constructed free dblk has an associated
5306 * mblk. From the allocator's viewpoint those mblks are
5307 * allocated (because they haven't been freed), but from
5308 * our viewpoint they're actually free (because they're
5309 * not currently in use). To account for this caching
5310 * effect we subtract the total constructed free dblks
5311 * from the total allocated mblks to derive mblks in use.
5313 if (strcmp(name, "streams_mblk") == 0 &&
5314 strncmp(ksp->ks_name, "streams_dblk", 12) == 0) {
5315 (void) safe_kstat_read(kc, ksp, NULL);
5316 total_buf_inuse -=
5317 kstat_named_value(ksp, "buf_constructed");
5318 continue; /* 'for' loop 1 */
5321 if (strncmp(ksp->ks_name, name, len) != 0)
5322 continue; /* 'for' loop 1 */
5324 (void) safe_kstat_read(kc, ksp, NULL);
5326 alloc = kstat_named_value(ksp, "alloc");
5327 alloc_fail = kstat_named_value(ksp, "alloc_fail");
5328 buf_size = kstat_named_value(ksp, "buf_size");
5329 buf_avail = kstat_named_value(ksp, "buf_avail");
5330 buf_total = kstat_named_value(ksp, "buf_total");
5331 buf_max = kstat_named_value(ksp, "buf_max");
5332 buf_inuse = buf_total - buf_avail;
5334 if (Vflag && prefix) {
5335 (void) snprintf(buf, sizeof (buf), "%s%s", title,
5336 ksp->ks_name + len);
5337 (void) printf(" %-18s %6u %9u %11u %11u\n",
5338 buf, buf_inuse, buf_max, alloc, alloc_fail);
5341 total_alloc += alloc;
5342 total_alloc_fail += alloc_fail;
5343 total_buf_max += buf_max;
5344 total_buf_inuse += buf_inuse;
5345 *total_bytes += (int64_t)buf_inuse * buf_size;
5346 } /* 'for' loop 1 ends */
5348 if (buf_size == 0) {
5349 (void) printf("%-22s [couldn't find statistics for %s]\n",
5350 title, name);
5351 return;
5354 if (Vflag && prefix)
5355 (void) snprintf(buf, sizeof (buf), "%s_total", title);
5356 else
5357 (void) snprintf(buf, sizeof (buf), "%s", title);
5359 (void) printf("%-22s %6d %9d %11lld %11d\n", buf,
5360 total_buf_inuse, total_buf_max, total_alloc, total_alloc_fail);
5363 static void
5364 m_report(void)
5366 int64_t total_bytes = 0;
5368 (void) puts("streams allocation:");
5369 (void) printf("%63s\n", "cumulative allocation");
5370 (void) printf("%63s\n",
5371 "current maximum total failures");
5373 kmem_cache_stats("streams",
5374 "stream_head_cache", 0, &total_bytes);
5375 kmem_cache_stats("queues", "queue_cache", 0, &total_bytes);
5376 kmem_cache_stats("mblk", "streams_mblk", 0, &total_bytes);
5377 kmem_cache_stats("dblk", "streams_dblk", 1, &total_bytes);
5378 kmem_cache_stats("linkblk", "linkinfo_cache", 0, &total_bytes);
5379 kmem_cache_stats("syncq", "syncq_cache", 0, &total_bytes);
5380 kmem_cache_stats("qband", "qband_cache", 0, &total_bytes);
5382 (void) printf("\n%lld Kbytes allocated for streams data\n",
5383 total_bytes / 1024);
5385 (void) putchar('\n');
5386 (void) fflush(stdout);
5389 /* --------------------------------- */
5392 * Print an IPv4 address. Remove the matching part of the domain name
5393 * from the returned name.
5395 static char *
5396 pr_addr(uint_t addr, char *dst, uint_t dstlen)
5398 char *cp;
5399 struct hostent *hp = NULL;
5400 static char domain[MAXHOSTNAMELEN + 1];
5401 static boolean_t first = B_TRUE;
5402 int error_num;
5404 if (first) {
5405 first = B_FALSE;
5406 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 &&
5407 (cp = strchr(domain, '.'))) {
5408 (void) strncpy(domain, cp + 1, sizeof (domain));
5409 } else
5410 domain[0] = 0;
5412 cp = NULL;
5413 if (!Nflag) {
5414 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t), AF_INET,
5415 &error_num);
5416 if (hp) {
5417 if ((cp = strchr(hp->h_name, '.')) != NULL &&
5418 strcasecmp(cp + 1, domain) == 0)
5419 *cp = 0;
5420 cp = hp->h_name;
5423 if (cp != NULL) {
5424 (void) strncpy(dst, cp, dstlen);
5425 dst[dstlen - 1] = 0;
5426 } else {
5427 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
5429 if (hp != NULL)
5430 freehostent(hp);
5431 return (dst);
5435 * Print a non-zero IPv4 address. Print " --" if the address is zero.
5437 static char *
5438 pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen)
5440 if (addr == INADDR_ANY) {
5441 (void) strlcpy(dst, " --", dstlen);
5442 return (dst);
5444 return (pr_addr(addr, dst, dstlen));
5448 * Print an IPv6 address. Remove the matching part of the domain name
5449 * from the returned name.
5451 static char *
5452 pr_addr6(const struct in6_addr *addr, char *dst, uint_t dstlen)
5454 char *cp;
5455 struct hostent *hp = NULL;
5456 static char domain[MAXHOSTNAMELEN + 1];
5457 static boolean_t first = B_TRUE;
5458 int error_num;
5460 if (first) {
5461 first = B_FALSE;
5462 if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 &&
5463 (cp = strchr(domain, '.'))) {
5464 (void) strncpy(domain, cp + 1, sizeof (domain));
5465 } else
5466 domain[0] = 0;
5468 cp = NULL;
5469 if (!Nflag) {
5470 hp = getipnodebyaddr((char *)addr,
5471 sizeof (struct in6_addr), AF_INET6, &error_num);
5472 if (hp) {
5473 if ((cp = strchr(hp->h_name, '.')) != NULL &&
5474 strcasecmp(cp + 1, domain) == 0)
5475 *cp = 0;
5476 cp = hp->h_name;
5479 if (cp != NULL) {
5480 (void) strncpy(dst, cp, dstlen);
5481 dst[dstlen - 1] = 0;
5482 } else {
5483 (void) inet_ntop(AF_INET6, (void *)addr, dst, dstlen);
5485 if (hp != NULL)
5486 freehostent(hp);
5487 return (dst);
5490 /* For IPv4 masks */
5491 static char *
5492 pr_mask(uint_t addr, char *dst, uint_t dstlen)
5494 uint8_t *ip_addr = (uint8_t *)&addr;
5496 (void) snprintf(dst, dstlen, "%d.%d.%d.%d",
5497 ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
5498 return (dst);
5502 * For ipv6 masks format is : dest/mask
5503 * Does not print /128 to save space in printout. H flag carries this notion.
5505 static char *
5506 pr_prefix6(const struct in6_addr *addr, uint_t prefixlen, char *dst,
5507 uint_t dstlen)
5509 char *cp;
5511 if (IN6_IS_ADDR_UNSPECIFIED(addr) && prefixlen == 0) {
5512 (void) strncpy(dst, "default", dstlen);
5513 dst[dstlen - 1] = 0;
5514 return (dst);
5517 (void) pr_addr6(addr, dst, dstlen);
5518 if (prefixlen != IPV6_ABITS) {
5519 /* How much room is left? */
5520 cp = strchr(dst, '\0');
5521 if (dst + dstlen > cp) {
5522 dstlen -= (cp - dst);
5523 (void) snprintf(cp, dstlen, "/%d", prefixlen);
5526 return (dst);
5529 /* Print IPv4 address and port */
5530 static char *
5531 pr_ap(uint_t addr, uint_t port, char *proto,
5532 char *dst, uint_t dstlen)
5534 char *cp;
5536 if (addr == INADDR_ANY) {
5537 (void) strncpy(dst, " *", dstlen);
5538 dst[dstlen - 1] = 0;
5539 } else {
5540 (void) pr_addr(addr, dst, dstlen);
5542 /* How much room is left? */
5543 cp = strchr(dst, '\0');
5544 if (dst + dstlen > cp + 1) {
5545 *cp++ = '.';
5546 dstlen -= (cp - dst);
5547 dstlen--;
5548 (void) portname(port, proto, cp, dstlen);
5550 return (dst);
5553 /* Print IPv6 address and port */
5554 static char *
5555 pr_ap6(const in6_addr_t *addr, uint_t port, char *proto,
5556 char *dst, uint_t dstlen)
5558 char *cp;
5560 if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
5561 (void) strncpy(dst, " *", dstlen);
5562 dst[dstlen - 1] = 0;
5563 } else {
5564 (void) pr_addr6(addr, dst, dstlen);
5566 /* How much room is left? */
5567 cp = strchr(dst, '\0');
5568 if (dst + dstlen + 1 > cp) {
5569 *cp++ = '.';
5570 dstlen -= (cp - dst);
5571 dstlen--;
5572 (void) portname(port, proto, cp, dstlen);
5574 return (dst);
5578 * Return the name of the network whose address is given. The address is
5579 * assumed to be that of a net or subnet, not a host.
5581 static char *
5582 pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
5584 char *cp = NULL;
5585 struct netent *np = NULL;
5586 struct hostent *hp = NULL;
5587 uint_t net;
5588 int subnetshift;
5589 int error_num;
5591 if (addr == INADDR_ANY && mask == INADDR_ANY) {
5592 (void) strncpy(dst, "default", dstlen);
5593 dst[dstlen - 1] = 0;
5594 return (dst);
5597 if (!Nflag && addr) {
5598 if (mask == 0) {
5599 if (IN_CLASSA(addr)) {
5600 mask = (uint_t)IN_CLASSA_NET;
5601 subnetshift = 8;
5602 } else if (IN_CLASSB(addr)) {
5603 mask = (uint_t)IN_CLASSB_NET;
5604 subnetshift = 8;
5605 } else {
5606 mask = (uint_t)IN_CLASSC_NET;
5607 subnetshift = 4;
5610 * If there are more bits than the standard mask
5611 * would suggest, subnets must be in use. Guess at
5612 * the subnet mask, assuming reasonable width subnet
5613 * fields.
5615 while (addr & ~mask)
5616 /* compiler doesn't sign extend! */
5617 mask = (mask | ((int)mask >> subnetshift));
5619 net = addr & mask;
5620 while ((mask & 1) == 0)
5621 mask >>= 1, net >>= 1;
5622 np = getnetbyaddr(net, AF_INET);
5623 if (np && np->n_net == net)
5624 cp = np->n_name;
5625 else {
5627 * Look for subnets in hosts map.
5629 hp = getipnodebyaddr((char *)&addr, sizeof (uint_t),
5630 AF_INET, &error_num);
5631 if (hp)
5632 cp = hp->h_name;
5635 if (cp != NULL) {
5636 (void) strncpy(dst, cp, dstlen);
5637 dst[dstlen - 1] = 0;
5638 } else {
5639 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
5641 if (hp != NULL)
5642 freehostent(hp);
5643 return (dst);
5647 * Return the name of the network whose address is given.
5648 * The address is assumed to be a host address.
5650 static char *
5651 pr_netaddr(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
5653 char *cp = NULL;
5654 struct netent *np = NULL;
5655 struct hostent *hp = NULL;
5656 uint_t net;
5657 uint_t netshifted;
5658 int subnetshift;
5659 struct in_addr in;
5660 int error_num;
5661 uint_t nbo_addr = addr; /* network byte order */
5663 addr = ntohl(addr);
5664 mask = ntohl(mask);
5665 if (addr == INADDR_ANY && mask == INADDR_ANY) {
5666 (void) strncpy(dst, "default", dstlen);
5667 dst[dstlen - 1] = 0;
5668 return (dst);
5671 /* Figure out network portion of address (with host portion = 0) */
5672 if (addr) {
5673 /* Try figuring out mask if unknown (all 0s). */
5674 if (mask == 0) {
5675 if (IN_CLASSA(addr)) {
5676 mask = (uint_t)IN_CLASSA_NET;
5677 subnetshift = 8;
5678 } else if (IN_CLASSB(addr)) {
5679 mask = (uint_t)IN_CLASSB_NET;
5680 subnetshift = 8;
5681 } else {
5682 mask = (uint_t)IN_CLASSC_NET;
5683 subnetshift = 4;
5686 * If there are more bits than the standard mask
5687 * would suggest, subnets must be in use. Guess at
5688 * the subnet mask, assuming reasonable width subnet
5689 * fields.
5691 while (addr & ~mask)
5692 /* compiler doesn't sign extend! */
5693 mask = (mask | ((int)mask >> subnetshift));
5695 net = netshifted = addr & mask;
5696 while ((mask & 1) == 0)
5697 mask >>= 1, netshifted >>= 1;
5699 else
5700 net = netshifted = 0;
5702 /* Try looking up name unless -n was specified. */
5703 if (!Nflag) {
5704 np = getnetbyaddr(netshifted, AF_INET);
5705 if (np && np->n_net == netshifted)
5706 cp = np->n_name;
5707 else {
5709 * Look for subnets in hosts map.
5711 hp = getipnodebyaddr((char *)&nbo_addr, sizeof (uint_t),
5712 AF_INET, &error_num);
5713 if (hp)
5714 cp = hp->h_name;
5717 if (cp != NULL) {
5718 (void) strncpy(dst, cp, dstlen);
5719 dst[dstlen - 1] = 0;
5720 if (hp != NULL)
5721 freehostent(hp);
5722 return (dst);
5725 * No name found for net: fallthru and return in decimal
5726 * dot notation.
5730 in.s_addr = htonl(net);
5731 (void) inet_ntop(AF_INET, (char *)&in, dst, dstlen);
5732 if (hp != NULL)
5733 freehostent(hp);
5734 return (dst);
5738 * Return the filter mode as a string:
5739 * 1 => "INCLUDE"
5740 * 2 => "EXCLUDE"
5741 * otherwise "<unknown>"
5743 static char *
5744 fmodestr(uint_t fmode)
5746 switch (fmode) {
5747 case 1:
5748 return ("INCLUDE");
5749 case 2:
5750 return ("EXCLUDE");
5751 default:
5752 return ("<unknown>");
5756 #define MAX_STRING_SIZE 256
5759 * Pretty print a port number. If the Nflag was
5760 * specified, use numbers instead of names.
5762 static char *
5763 portname(uint_t port, char *proto, char *dst, uint_t dstlen)
5765 struct servent *sp = NULL;
5767 if (!Nflag && port)
5768 sp = getservbyport(htons(port), proto);
5769 if (sp || port == 0)
5770 (void) snprintf(dst, dstlen, "%.*s", MAXHOSTNAMELEN,
5771 sp ? sp->s_name : "*");
5772 else
5773 (void) snprintf(dst, dstlen, "%d", port);
5774 dst[dstlen - 1] = 0;
5775 return (dst);
5778 /*PRINTFLIKE2*/
5779 void
5780 fail(int do_perror, char *message, ...)
5782 va_list args;
5784 va_start(args, message);
5785 (void) fputs("netstat: ", stderr);
5786 (void) vfprintf(stderr, message, args);
5787 va_end(args);
5788 if (do_perror)
5789 (void) fprintf(stderr, ": %s", strerror(errno));
5790 (void) fputc('\n', stderr);
5791 exit(2);
5795 * Return value of named statistic for given kstat_named kstat;
5796 * return 0LL if named statistic is not in list (use "ll" as a
5797 * type qualifier when printing 64-bit int's with printf() )
5799 static uint64_t
5800 kstat_named_value(kstat_t *ksp, char *name)
5802 kstat_named_t *knp;
5803 uint64_t value;
5805 if (ksp == NULL)
5806 return (0LL);
5808 knp = kstat_data_lookup(ksp, name);
5809 if (knp == NULL)
5810 return (0LL);
5812 switch (knp->data_type) {
5813 case KSTAT_DATA_INT32:
5814 case KSTAT_DATA_UINT32:
5815 value = (uint64_t)(knp->value.ui32);
5816 break;
5817 case KSTAT_DATA_INT64:
5818 case KSTAT_DATA_UINT64:
5819 value = knp->value.ui64;
5820 break;
5821 default:
5822 value = 0LL;
5823 break;
5826 return (value);
5829 kid_t
5830 safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
5832 kid_t kstat_chain_id = kstat_read(kc, ksp, data);
5834 if (kstat_chain_id == -1)
5835 fail(1, "kstat_read(%p, '%s') failed", (void *)kc,
5836 ksp->ks_name);
5837 return (kstat_chain_id);
5841 * Parse a list of IRE flag characters into a bit field.
5843 static uint_t
5844 flag_bits(const char *arg)
5846 const char *cp;
5847 uint_t val;
5849 if (*arg == '\0')
5850 fatal(1, "missing flag list\n");
5852 val = 0;
5853 while (*arg != '\0') {
5854 if ((cp = strchr(flag_list, *arg)) == NULL)
5855 fatal(1, "%c: illegal flag\n", *arg);
5856 val |= 1 << (cp - flag_list);
5857 arg++;
5859 return (val);
5863 * Handle -f argument. Validate input format, sort by keyword, and
5864 * save off digested results.
5866 static void
5867 process_filter(char *arg)
5869 int idx;
5870 int klen = 0;
5871 char *cp, *cp2;
5872 int val;
5873 filter_t *newf;
5874 struct hostent *hp;
5875 int error_num;
5876 uint8_t *ucp;
5877 int maxv;
5879 /* Look up the keyword first */
5880 if (strchr(arg, ':') == NULL) {
5881 idx = FK_AF;
5882 } else {
5883 for (idx = 0; idx < NFILTERKEYS; idx++) {
5884 klen = strlen(filter_keys[idx]);
5885 if (strncmp(filter_keys[idx], arg, klen) == 0 &&
5886 arg[klen] == ':')
5887 break;
5889 if (idx >= NFILTERKEYS)
5890 fatal(1, "%s: unknown filter keyword\n", arg);
5892 /* Advance past keyword and separator. */
5893 arg += klen + 1;
5896 if ((newf = malloc(sizeof (*newf))) == NULL) {
5897 perror("filter");
5898 exit(1);
5900 switch (idx) {
5901 case FK_AF:
5902 if (strcmp(arg, "inet") == 0) {
5903 newf->u.f_family = AF_INET;
5904 } else if (strcmp(arg, "inet6") == 0) {
5905 newf->u.f_family = AF_INET6;
5906 } else if (strcmp(arg, "unix") == 0) {
5907 newf->u.f_family = AF_UNIX;
5908 } else {
5909 newf->u.f_family = strtol(arg, &cp, 0);
5910 if (arg == cp || *cp != '\0')
5911 fatal(1, "%s: unknown address family.\n", arg);
5913 break;
5915 case FK_OUTIF:
5916 if (strcmp(arg, "none") == 0) {
5917 newf->u.f_ifname = NULL;
5918 break;
5920 if (strcmp(arg, "any") == 0) {
5921 newf->u.f_ifname = "";
5922 break;
5924 val = strtol(arg, &cp, 0);
5925 if (val <= 0 || arg == cp || cp[0] != '\0') {
5926 if ((val = if_nametoindex(arg)) == 0) {
5927 perror(arg);
5928 exit(1);
5931 newf->u.f_ifname = arg;
5932 break;
5934 case FK_DST:
5935 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask);
5936 if (strcmp(arg, "any") == 0) {
5937 /* Special semantics; any address *but* zero */
5938 newf->u.a.f_address = NULL;
5939 (void) memset(&newf->u.a.f_mask, 0,
5940 sizeof (newf->u.a.f_mask));
5941 break;
5943 if (strcmp(arg, "none") == 0) {
5944 newf->u.a.f_address = NULL;
5945 break;
5947 if ((cp = strrchr(arg, '/')) != NULL)
5948 *cp++ = '\0';
5949 hp = getipnodebyname(arg, AF_INET6, AI_V4MAPPED|AI_ALL,
5950 &error_num);
5951 if (hp == NULL)
5952 fatal(1, "%s: invalid or unknown host address\n", arg);
5953 newf->u.a.f_address = hp;
5954 if (cp == NULL) {
5955 V4MASK_TO_V6(IP_HOST_MASK, newf->u.a.f_mask);
5956 } else {
5957 val = strtol(cp, &cp2, 0);
5958 if (cp != cp2 && cp2[0] == '\0') {
5960 * If decode as "/n" works, then translate
5961 * into a mask.
5963 if (hp->h_addr_list[0] != NULL &&
5964 /* LINTED: (note 1) */
5965 IN6_IS_ADDR_V4MAPPED((in6_addr_t *)
5966 hp->h_addr_list[0])) {
5967 maxv = IP_ABITS;
5968 } else {
5969 maxv = IPV6_ABITS;
5971 if (val < 0 || val >= maxv)
5972 fatal(1, "%d: not in range 0 to %d\n",
5973 val, maxv - 1);
5974 if (maxv == IP_ABITS)
5975 val += IPV6_ABITS - IP_ABITS;
5976 ucp = newf->u.a.f_mask.s6_addr;
5977 while (val >= 8)
5978 *ucp++ = 0xff, val -= 8;
5979 *ucp++ = (0xff << (8 - val)) & 0xff;
5980 while (ucp < newf->u.a.f_mask.s6_addr +
5981 sizeof (newf->u.a.f_mask.s6_addr))
5982 *ucp++ = 0;
5983 /* Otherwise, try as numeric address */
5984 } else if (inet_pton(AF_INET6,
5985 cp, &newf->u.a.f_mask) <= 0) {
5986 fatal(1, "%s: illegal mask format\n", cp);
5989 break;
5991 case FK_FLAGS:
5992 if (*arg == '+') {
5993 newf->u.f.f_flagset = flag_bits(arg + 1);
5994 newf->u.f.f_flagclear = 0;
5995 } else if (*arg == '-') {
5996 newf->u.f.f_flagset = 0;
5997 newf->u.f.f_flagclear = flag_bits(arg + 1);
5998 } else {
5999 newf->u.f.f_flagset = flag_bits(arg);
6000 newf->u.f.f_flagclear = ~newf->u.f.f_flagset;
6002 break;
6004 default:
6005 assert(0);
6007 newf->f_next = filters[idx];
6008 filters[idx] = newf;
6011 /* Determine if user wants this address family printed. */
6012 static boolean_t
6013 family_selected(int family)
6015 const filter_t *fp;
6017 if (v4compat && family == AF_INET6)
6018 return (B_FALSE);
6019 if ((fp = filters[FK_AF]) == NULL)
6020 return (B_TRUE);
6021 while (fp != NULL) {
6022 if (fp->u.f_family == family)
6023 return (B_TRUE);
6024 fp = fp->f_next;
6026 return (B_FALSE);
6030 * Convert the interface index to a string using the buffer `ifname', which
6031 * must be at least LIFNAMSIZ bytes. We first try to map it to name. If that
6032 * fails (e.g., because we're inside a zone and it does not have access to
6033 * interface for the index in question), just return "if#<num>".
6035 static char *
6036 ifindex2str(uint_t ifindex, char *ifname)
6038 if (if_indextoname(ifindex, ifname) == NULL)
6039 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6041 return (ifname);
6045 * print the usage line
6047 static void
6048 usage(char *cmdname)
6050 (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] "
6051 "[-T d|u]\n", cmdname);
6052 (void) fprintf(stderr, " %s [-n] [-f address_family] "
6053 "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6054 cmdname);
6055 (void) fprintf(stderr, " %s -m [-v] [-T d|u] "
6056 "[interval [count]]\n", cmdname);
6057 (void) fprintf(stderr, " %s -i [-I interface] [-an] "
6058 "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6059 (void) fprintf(stderr, " %s -r [-anv] "
6060 "[-f address_family|filter] [-T d|u]\n", cmdname);
6061 (void) fprintf(stderr, " %s -M [-ns] [-f address_family] "
6062 "[-T d|u]\n", cmdname);
6063 (void) fprintf(stderr, " %s -D [-I interface] "
6064 "[-f address_family] [-T d|u]\n", cmdname);
6065 exit(EXIT_FAILURE);
6069 * fatal: print error message to stderr and
6070 * call exit(errcode)
6072 /*PRINTFLIKE2*/
6073 static void
6074 fatal(int errcode, char *format, ...)
6076 va_list argp;
6078 if (format == NULL)
6079 return;
6081 va_start(argp, format);
6082 (void) vfprintf(stderr, format, argp);
6083 va_end(argp);
6085 exit(errcode);