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.
41 *
42 * TODO:
43 * Add ability to request subsets from kernel (with level = MIB2_IP;
44 * name = 0 meaning everything for compatibility)
45 */
46
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>
58
59 #include <sys/types.h>
60 #include <sys/stream.h>
61 #include <stropts.h>
62 #include <sys/strstat.h>
63 #include <sys/tihdr.h>
64
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>
70
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>
77
78 #include <arpa/inet.h>
79 #include <netdb.h>
80 #include <fcntl.h>
81 #include <sys/systeminfo.h>
82 #include <arpa/inet.h>
83
84 #include <netinet/dhcp.h>
85 #include <dhcpagent_ipc.h>
86 #include <dhcpagent_util.h>
87 #include <compat.h>
88
89 #include <libtsnet.h>
90 #include <tsol/label.h>
91
92 #include "statcommon.h"
93
94 extern void unixpr(kstat_ctl_t *kc);
95
96 #define STR_EXPAND 4
97
98 #define V4MASK_TO_V6(v4, v6) ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
99 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \
100 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \
101 (v6)._S6_un._S6_u32[3] = (v4))
102
103 #define IN6_IS_V4MASK(v6) ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
104 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \
105 (v6)._S6_un._S6_u32[2] == 0xfffffffful)
106
107 /*
108 * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
109 * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
110 * possible for an administrator to plumb new interfaces between those two
111 * calls, resulting in the failure of the latter. This addition makes that
112 * less likely.
113 */
114 #define LIFN_GUARD_VALUE 10
118 int group;
119 int mib_id;
120 int length;
121 void *valp;
122 } mib_item_t;
123
124 struct ifstat {
125 uint64_t ipackets;
126 uint64_t ierrors;
127 uint64_t opackets;
128 uint64_t oerrors;
129 uint64_t collisions;
130 };
131
132 struct iflist {
133 struct iflist *next_if;
134 char ifname[LIFNAMSIZ];
135 struct ifstat tot;
136 };
137
138 static mib_item_t *mibget(int sd);
139 static void mibfree(mib_item_t *firstitem);
140 static int mibopen(void);
141 static void mib_get_constants(mib_item_t *item);
142 static mib_item_t *mib_item_dup(mib_item_t *item);
143 static mib_item_t *mib_item_diff(mib_item_t *item1,
144 mib_item_t *item2);
145 static void mib_item_destroy(mib_item_t **item);
146
147 static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b);
148 static char *octetstr(const Octet_t *op, int code,
149 char *dst, uint_t dstlen);
150 static char *pr_addr(uint_t addr,
151 char *dst, uint_t dstlen);
152 static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
153 static char *pr_addr6(const in6_addr_t *addr,
154 char *dst, uint_t dstlen);
155 static char *pr_mask(uint_t addr,
156 char *dst, uint_t dstlen);
157 static char *pr_prefix6(const struct in6_addr *addr,
174 const mib2_transportMLPEntry_t *attr);
175
176 static void stat_report(mib_item_t *item);
177 static void mrt_stat_report(mib_item_t *item);
178 static void arp_report(mib_item_t *item);
179 static void ndp_report(mib_item_t *item);
180 static void mrt_report(mib_item_t *item);
181 static void if_stat_total(struct ifstat *oldstats,
182 struct ifstat *newstats, struct ifstat *sumstats);
183 static void if_report(mib_item_t *item, char *ifname,
184 int Iflag_only, boolean_t once_only);
185 static void if_report_ip4(mib2_ipAddrEntry_t *ap,
186 char ifname[], char logintname[],
187 struct ifstat *statptr, boolean_t ksp_not_null);
188 static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
189 char ifname[], char logintname[],
190 struct ifstat *statptr, boolean_t ksp_not_null);
191 static void ire_report(const mib_item_t *item);
192 static void tcp_report(const mib_item_t *item);
193 static void udp_report(const mib_item_t *item);
194 static void group_report(mib_item_t *item);
195 static void dce_report(mib_item_t *item);
196 static void print_ip_stats(mib2_ip_t *ip);
197 static void print_icmp_stats(mib2_icmp_t *icmp);
198 static void print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
199 static void print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
200 static void print_sctp_stats(mib2_sctp_t *tcp);
201 static void print_tcp_stats(mib2_tcp_t *tcp);
202 static void print_udp_stats(mib2_udp_t *udp);
203 static void print_rawip_stats(mib2_rawip_t *rawip);
204 static void print_igmp_stats(struct igmpstat *igps);
205 static void print_mrt_stats(struct mrtstat *mrts);
206 static void sctp_report(const mib_item_t *item);
207 static void sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
208 mib2_ipv6IfStatsEntry_t *sum6);
209 static void sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
210 mib2_ipv6IfIcmpEntry_t *sum6);
211 static void m_report(void);
212 static void dhcp_report(char *);
213
214 static uint64_t kstat_named_value(kstat_t *, char *);
215 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
216 static int isnum(char *);
217 static char *plural(int n);
218 static char *pluraly(int n);
219 static char *plurales(int n);
220 static void process_filter(char *arg);
221 static char *ifindex2str(uint_t, char *);
222 static boolean_t family_selected(int family);
223
224 static void usage(char *);
225 static void fatal(int errcode, char *str1, ...);
226
227 #define PLURAL(n) plural((int)n)
228 #define PLURALY(n) pluraly((int)n)
229 #define PLURALES(n) plurales((int)n)
230 #define IFLAGMOD(flg, val1, val2) if (flg == val1) flg = val2
231 #define MDIFF(diff, elem2, elem1, member) (diff)->member = \
232 (elem2)->member - (elem1)->member
233
234
235 static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */
236 static boolean_t Dflag = B_FALSE; /* DCE info */
237 static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */
238 static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */
239 static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */
240 static boolean_t Rflag = B_FALSE; /* Routing Tables */
241 static boolean_t RSECflag = B_FALSE; /* Security attributes */
242 static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */
243 static boolean_t Vflag = B_FALSE; /* Verbose */
244 static boolean_t Pflag = B_FALSE; /* Net to Media Tables */
245 static boolean_t Gflag = B_FALSE; /* Multicast group membership */
246 static boolean_t MMflag = B_FALSE; /* Multicast routing table */
247 static boolean_t DHCPflag = B_FALSE; /* DHCP statistics */
248 static boolean_t Xflag = B_FALSE; /* Debug Info */
249
250 static int v4compat = 0; /* Compatible printing format for status */
251
252 static int proto = IPPROTO_MAX; /* all protocols */
253 kstat_ctl_t *kc = NULL;
254
255 /*
256 * Sizes of data structures extracted from the base mib.
257 * This allows the size of the tables entries to grow while preserving
258 * binary compatibility.
259 */
260 static int ipAddrEntrySize;
261 static int ipRouteEntrySize;
262 static int ipNetToMediaEntrySize;
263 static int ipMemberEntrySize;
368 * 1, IFlag is the only feature-flag enabled
369 * : trinary variable, modified using IFLAGMOD()
370 */
371 int Iflag_only = -1;
372 boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
373 extern char *optarg;
374 extern int optind;
375 char *default_ip_str = NULL;
376
377 name = argv[0];
378
379 v4compat = get_compat_flag(&default_ip_str);
380 if (v4compat == DEFAULT_PROT_BAD_VALUE)
381 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
382 default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
383 free(default_ip_str);
384
385 (void) setlocale(LC_ALL, "");
386 (void) textdomain(TEXT_DOMAIN);
387
388 while ((c = getopt(argc, argv, "adimnrspMgvxf:P:I:DRT:")) != -1) {
389 switch ((char)c) {
390 case 'a': /* all connections */
391 Aflag = B_TRUE;
392 break;
393
394 case 'd': /* DCE info */
395 Dflag = B_TRUE;
396 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
397 break;
398
399 case 'i': /* interface (ill/ipif report) */
400 Iflag = B_TRUE;
401 IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
402 break;
403
404 case 'm': /* streams msg report */
405 Mflag = B_TRUE;
406 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
407 break;
408
428 case 'p': /* arp/ndp table */
429 Pflag = B_TRUE;
430 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
431 break;
432
433 case 'M': /* multicast routing tables */
434 MMflag = B_TRUE;
435 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
436 break;
437
438 case 'g': /* multicast group membership */
439 Gflag = B_TRUE;
440 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
441 break;
442
443 case 'v': /* verbose output format */
444 Vflag = B_TRUE;
445 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
446 break;
447
448 case 'x': /* turn on debugging */
449 Xflag = B_TRUE;
450 break;
451
452 case 'f':
453 process_filter(optarg);
454 break;
455
456 case 'P':
457 if (strcmp(optarg, "ip") == 0) {
458 proto = IPPROTO_IP;
459 } else if (strcmp(optarg, "ipv6") == 0 ||
460 strcmp(optarg, "ip6") == 0) {
461 v4compat = 0; /* Overridden */
462 proto = IPPROTO_IPV6;
463 } else if (strcmp(optarg, "icmp") == 0) {
464 proto = IPPROTO_ICMP;
465 } else if (strcmp(optarg, "icmpv6") == 0 ||
466 strcmp(optarg, "icmp6") == 0) {
467 v4compat = 0; /* Overridden */
637 if (MMflag)
638 mrt_report(item);
639 }
640 if (Gflag)
641 group_report(item);
642 if (Pflag) {
643 if (family_selected(AF_INET))
644 arp_report(item);
645 if (family_selected(AF_INET6))
646 ndp_report(item);
647 }
648 if (Dflag)
649 dce_report(item);
650 mib_item_destroy(&curritem);
651 }
652
653 /* netstat: AF_UNIX behaviour */
654 if (family_selected(AF_UNIX) &&
655 (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
656 MMflag || Pflag || Gflag)))
657 unixpr(kc);
658 (void) kstat_close(kc);
659
660 /* iteration handling code */
661 if (count > 0 && --count == 0)
662 break;
663 (void) sleep(interval);
664
665 /* re-populating of data structures */
666 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
667 if (Sflag) {
668 /* previtem is a cut-down list */
669 previtem = mib_item_dup(item);
670 if (previtem == NULL)
671 fatal(1, "can't process mib data, "
672 "out of memory\n");
673 }
674 mibfree(item);
675 (void) close(sd);
676 if ((sd = mibopen()) == -1)
677 fatal(1, "can't open mib stream anymore\n");
955 item->length);
956 tempp = &(localp[c]);
957 if (c > 0)
958 (localp[c - 1]).next_item = tempp;
959 c++;
960 }
961 }
962 return (localp);
963 }
964
965 /*
966 * mib_item_diff: takes two (mib_item_t *) linked lists
967 * item1 and item2 and computes the difference between
968 * differentiable values in item2 against item1 for every
969 * given member of item2; returns an mib_item_t * linked
970 * list of diff's, or a copy of item2 if item1 is NULL;
971 * will return NULL if system out of memory; works only
972 * for item->mib_id == 0
973 */
974 static mib_item_t *
975 mib_item_diff(mib_item_t *item1, mib_item_t *item2) {
976 int nitems = 0; /* no. of items in item2 */
977 mib_item_t *tempp2; /* walking copy of item2 */
978 mib_item_t *tempp1; /* walking copy of item1 */
979 mib_item_t *diffp;
980 mib_item_t *diffptr; /* walking copy of diffp */
981 mib_item_t *prevp = NULL;
982
983 if (item1 == NULL) {
984 diffp = mib_item_dup(item2);
985 return (diffp);
986 }
987
988 for (tempp2 = item2;
989 tempp2;
990 tempp2 = tempp2->next_item) {
991 if (tempp2->mib_id == 0)
992 switch (tempp2->group) {
993 /*
994 * upon adding a case here, the same
995 * must also be added in the next
1481 }
1482 } /* 'for' loop 2 ends */
1483 tempp1 = NULL;
1484 } /* 'for' loop 1 ends */
1485 tempp2 = NULL;
1486 diffptr--;
1487 diffptr->next_item = NULL;
1488 return (diffp);
1489
1490 mibdiff_out_of_memory:;
1491 mib_item_destroy(&diffp);
1492 return (NULL);
1493 }
1494
1495 /*
1496 * mib_item_destroy: cleans up a mib_item_t *
1497 * that was created by calling mib_item_dup or
1498 * mib_item_diff
1499 */
1500 static void
1501 mib_item_destroy(mib_item_t **itemp) {
1502 int nitems = 0;
1503 int c = 0;
1504 mib_item_t *tempp;
1505
1506 if (itemp == NULL || *itemp == NULL)
1507 return;
1508
1509 for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1510 if (tempp->mib_id == 0)
1511 nitems++;
1512 else
1513 return; /* cannot destroy! */
1514
1515 if (nitems == 0)
1516 return; /* cannot destroy! */
1517
1518 for (c = nitems - 1; c >= 0; c--) {
1519 if ((itemp[0][c]).valp != NULL)
1520 free((itemp[0][c]).valp);
1521 }
3246 old6 = new6;
3247 cleanlist = oldlist6;
3248 oldlist6 = newlist6;
3249 while (cleanlist != NULL) {
3250 tlp = cleanlist->next_if;
3251 free(cleanlist);
3252 cleanlist = tlp;
3253 }
3254 }
3255 break;
3256 }
3257 }
3258 (void) fflush(stdout);
3259 } /* 'for' loop 1 ends */
3260 if ((Iflag_only == 0) && (!once_only))
3261 (void) putchar('\n');
3262 reentry = B_TRUE;
3263 }
3264
3265 static void
3266 if_report_ip4(mib2_ipAddrEntry_t *ap,
3267 char ifname[], char logintname[], struct ifstat *statptr,
3268 boolean_t ksp_not_null) {
3269
3270 char abuf[MAXHOSTNAMELEN + 1];
3271 char dstbuf[MAXHOSTNAMELEN + 1];
3272
3273 if (ksp_not_null) {
3274 (void) printf("%-5s %-4u ",
3275 ifname, ap->ipAdEntInfo.ae_mtu);
3276 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3277 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3278 abuf, sizeof (abuf));
3279 else
3280 (void) pr_netaddr(ap->ipAdEntAddr,
3281 ap->ipAdEntNetMask, abuf, sizeof (abuf));
3282 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3283 "%-6llu %-6llu\n",
3284 abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3285 statptr->ipackets, statptr->ierrors,
3286 statptr->opackets, statptr->oerrors,
3287 statptr->collisions, 0LL);
3288 }
3294 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3295 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3296
3297 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3298 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3299 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3300 sizeof (abuf));
3301 else
3302 (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3303 abuf, sizeof (abuf));
3304
3305 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3306 "%-5s %-6s %-6llu\n", abuf,
3307 pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3308 statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3309 0LL);
3310 }
3311 }
3312
3313 static void
3314 if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
3315 char ifname[], char logintname[], struct ifstat *statptr,
3316 boolean_t ksp_not_null) {
3317
3318 char abuf[MAXHOSTNAMELEN + 1];
3319 char dstbuf[MAXHOSTNAMELEN + 1];
3320
3321 if (ksp_not_null) {
3322 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3323 if (ap6->ipv6AddrInfo.ae_flags &
3324 IFF_POINTOPOINT) {
3325 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3326 abuf, sizeof (abuf));
3327 } else {
3328 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3329 ap6->ipv6AddrPfxLength, abuf,
3330 sizeof (abuf));
3331 }
3332 (void) printf("%-27s %-27s %-6llu %-5llu "
3333 "%-6llu %-5llu %-6llu\n",
3334 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3335 sizeof (dstbuf)),
3336 statptr->ipackets, statptr->ierrors, statptr->opackets,
4725 free(sl_str);
4726 }
4727 }
4728
4729 /* ------------------------------ TCP_REPORT------------------------------- */
4730
4731 static const char tcp_hdr_v4[] =
4732 "\nTCP: IPv4\n";
4733 static const char tcp_hdr_v4_compat[] =
4734 "\nTCP\n";
4735 static const char tcp_hdr_v4_verbose[] =
4736 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack "
4737 " Rto Mss State\n"
4738 "-------------------- ----- -------- -------- ----- -------- -------- "
4739 "----- ----- -----------\n";
4740 static const char tcp_hdr_v4_normal[] =
4741 " Local Address Remote Address Swind Send-Q Rwind Recv-Q "
4742 " State\n"
4743 "-------------------- -------------------- ----- ------ ----- ------ "
4744 "-----------\n";
4745
4746 static const char tcp_hdr_v6[] =
4747 "\nTCP: IPv6\n";
4748 static const char tcp_hdr_v6_verbose[] =
4749 "Local/Remote Address Swind Snext Suna Rwind Rnext "
4750 " Rack Rto Mss State If\n"
4751 "--------------------------------- ----- -------- -------- ----- -------- "
4752 "-------- ----- ----- ----------- -----\n";
4753 static const char tcp_hdr_v6_normal[] =
4754 " Local Address Remote Address "
4755 "Swind Send-Q Rwind Recv-Q State If\n"
4756 "--------------------------------- --------------------------------- "
4757 "----- ------ ----- ------ ----------- -----\n";
4758
4759 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4760 boolean_t first, const mib2_transportMLPEntry_t *);
4761 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4762 boolean_t first, const mib2_transportMLPEntry_t *);
4763
4764 static void
4765 tcp_report(const mib_item_t *item)
4766 {
4767 int jtemp = 0;
4768 boolean_t print_hdr_once_v4 = B_TRUE;
4769 boolean_t print_hdr_once_v6 = B_TRUE;
4770 mib2_tcpConnEntry_t *tp;
4771 mib2_tcp6ConnEntry_t *tp6;
4772 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
4773 mib2_transportMLPEntry_t **v4a, **v6a;
4774 mib2_transportMLPEntry_t *aptr;
4775
4776 if (!protocol_selected(IPPROTO_TCP))
4777 return;
4778
4779 /*
4780 * Preparation pass: the kernel returns separate entries for TCP
4781 * connection table entries and Multilevel Port attributes. We loop
4782 * through the attributes first and set up an array for each address
4783 * family.
4784 */
4785 v4_attrs = family_selected(AF_INET) && RSECflag ?
4786 gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) :
4787 NULL;
4788 v6_attrs = family_selected(AF_INET6) && RSECflag ?
4789 gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) :
4790 NULL;
4791
4792 /* 'for' loop 1: */
4793 v4a = v4_attrs;
4794 v6a = v6_attrs;
4795 for (; item != NULL; item = item->next_item) {
4796 if (Xflag) {
4797 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4798 (void) printf("Group = %d, mib_id = %d, "
4799 "length = %d, valp = 0x%p\n",
4800 item->group, item->mib_id,
4801 item->length, item->valp);
4802 }
4803
4804 if (!((item->group == MIB2_TCP &&
4805 item->mib_id == MIB2_TCP_CONN) ||
4806 (item->group == MIB2_TCP6 &&
4807 item->mib_id == MIB2_TCP6_CONN)))
4808 continue; /* 'for' loop 1 */
4809
4810 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4811 continue; /* 'for' loop 1 */
4812 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4813 continue; /* 'for' loop 1 */
4814
4815 if (item->group == MIB2_TCP) {
4816 for (tp = (mib2_tcpConnEntry_t *)item->valp;
4817 (char *)tp < (char *)item->valp + item->length;
4818 /* LINTED: (note 1) */
4819 tp = (mib2_tcpConnEntry_t *)((char *)tp +
4820 tcpConnEntrySize)) {
4821 aptr = v4a == NULL ? NULL : *v4a++;
4822 print_hdr_once_v4 = tcp_report_item_v4(tp,
4823 print_hdr_once_v4, aptr);
4824 }
4825 } else {
4826 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4827 (char *)tp6 < (char *)item->valp + item->length;
4828 /* LINTED: (note 1) */
4829 tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4830 tcp6ConnEntrySize)) {
4831 aptr = v6a == NULL ? NULL : *v6a++;
4832 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4833 print_hdr_once_v6, aptr);
4834 }
4835 }
4836 } /* 'for' loop 1 ends */
4837 (void) fflush(stdout);
4838
4839 if (v4_attrs != NULL)
4840 free(v4_attrs);
4841 if (v6_attrs != NULL)
4842 free(v6_attrs);
4843 }
4844
4845 static boolean_t
4846 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first,
4847 const mib2_transportMLPEntry_t *attr)
4848 {
4849 /*
4850 * lname and fname below are for the hostname as well as the portname
4851 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4852 * as the limit
4853 */
4854 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4855 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4856
4857 if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4858 return (first); /* Nothing to print */
4859
4860 if (first) {
4861 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4862 (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);
4863 }
4864
4865 if (Vflag) {
4866 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4867 "%5u %5u %s\n",
4868 pr_ap(tp->tcpConnLocalAddress,
4869 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4870 pr_ap(tp->tcpConnRemAddress,
4871 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4872 tp->tcpConnEntryInfo.ce_swnd,
4873 tp->tcpConnEntryInfo.ce_snxt,
4874 tp->tcpConnEntryInfo.ce_suna,
4875 tp->tcpConnEntryInfo.ce_rwnd,
4876 tp->tcpConnEntryInfo.ce_rnxt,
4877 tp->tcpConnEntryInfo.ce_rack,
4878 tp->tcpConnEntryInfo.ce_rto,
4879 tp->tcpConnEntryInfo.ce_mss,
4880 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4881 } else {
4882 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4883 (int)tp->tcpConnEntryInfo.ce_suna - 1;
4884 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4885 (int)tp->tcpConnEntryInfo.ce_rack;
4886
4887 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
4888 pr_ap(tp->tcpConnLocalAddress,
4889 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4890 pr_ap(tp->tcpConnRemAddress,
4891 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4892 tp->tcpConnEntryInfo.ce_swnd,
4893 (sq >= 0) ? sq : 0,
4894 tp->tcpConnEntryInfo.ce_rwnd,
4895 (rq >= 0) ? rq : 0,
4896 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4897 }
4898
4899 print_transport_label(attr);
4900
4901 return (B_FALSE);
4902 }
4903
4904 static boolean_t
4905 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first,
4906 const mib2_transportMLPEntry_t *attr)
4907 {
4908 /*
4909 * lname and fname below are for the hostname as well as the portname
4910 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4911 * as the limit
4912 */
4913 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4914 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4915 char ifname[LIFNAMSIZ + 1];
4916 char *ifnamep;
4917
4918 if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4919 return (first); /* Nothing to print */
4920
4921 if (first) {
4922 (void) printf(tcp_hdr_v6);
4923 (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);
4924 }
4925
4926 ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
4927 if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
4928 if (ifnamep == NULL)
4929 ifnamep = "";
4930
4931 if (Vflag) {
4932 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
4933 "%5u %5u %-11s %s\n",
4934 pr_ap6(&tp6->tcp6ConnLocalAddress,
4935 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4936 pr_ap6(&tp6->tcp6ConnRemAddress,
4937 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4938 tp6->tcp6ConnEntryInfo.ce_swnd,
4939 tp6->tcp6ConnEntryInfo.ce_snxt,
4940 tp6->tcp6ConnEntryInfo.ce_suna,
4941 tp6->tcp6ConnEntryInfo.ce_rwnd,
4942 tp6->tcp6ConnEntryInfo.ce_rnxt,
4943 tp6->tcp6ConnEntryInfo.ce_rack,
4944 tp6->tcp6ConnEntryInfo.ce_rto,
4945 tp6->tcp6ConnEntryInfo.ce_mss,
4946 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
4947 ifnamep);
4948 } else {
4949 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
4950 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
4951 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
4952 (int)tp6->tcp6ConnEntryInfo.ce_rack;
4953
4954 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
4955 pr_ap6(&tp6->tcp6ConnLocalAddress,
4956 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4957 pr_ap6(&tp6->tcp6ConnRemAddress,
4958 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4959 tp6->tcp6ConnEntryInfo.ce_swnd,
4960 (sq >= 0) ? sq : 0,
4961 tp6->tcp6ConnEntryInfo.ce_rwnd,
4962 (rq >= 0) ? rq : 0,
4963 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
4964 ifnamep);
4965 }
4966
4967 print_transport_label(attr);
4968
4969 return (B_FALSE);
4970 }
4971
4972 /* ------------------------------- UDP_REPORT------------------------------- */
4973
4974 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
4975 boolean_t first, const mib2_transportMLPEntry_t *attr);
4976 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
4977 boolean_t first, const mib2_transportMLPEntry_t *attr);
4978
4979 static const char udp_hdr_v4[] =
4980 " Local Address Remote Address State\n"
4981 "-------------------- -------------------- ----------\n";
4982
4983 static const char udp_hdr_v6[] =
4984 " Local Address Remote Address "
4985 " State If\n"
4986 "--------------------------------- --------------------------------- "
4987 "---------- -----\n";
4988
4989 static void
4990 udp_report(const mib_item_t *item)
4991 {
4992 int jtemp = 0;
4993 boolean_t print_hdr_once_v4 = B_TRUE;
4994 boolean_t print_hdr_once_v6 = B_TRUE;
4995 mib2_udpEntry_t *ude;
4996 mib2_udp6Entry_t *ude6;
4997 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
4998 mib2_transportMLPEntry_t **v4a, **v6a;
4999 mib2_transportMLPEntry_t *aptr;
5000
5001 if (!protocol_selected(IPPROTO_UDP))
5002 return;
5003
5004 /*
5005 * Preparation pass: the kernel returns separate entries for UDP
5006 * connection table entries and Multilevel Port attributes. We loop
5007 * through the attributes first and set up an array for each address
5008 * family.
5009 */
5010 v4_attrs = family_selected(AF_INET) && RSECflag ?
5011 gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
5012 v6_attrs = family_selected(AF_INET6) && RSECflag ?
5013 gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
5014 NULL;
5015
5016 v4a = v4_attrs;
5017 v6a = v6_attrs;
5018 /* 'for' loop 1: */
5019 for (; item; item = item->next_item) {
5020 if (Xflag) {
5021 (void) printf("\n--- Entry %d ---\n", ++jtemp);
5022 (void) printf("Group = %d, mib_id = %d, "
5023 "length = %d, valp = 0x%p\n",
5024 item->group, item->mib_id,
5025 item->length, item->valp);
5026 }
5027 if (!((item->group == MIB2_UDP &&
5028 item->mib_id == MIB2_UDP_ENTRY) ||
5029 (item->group == MIB2_UDP6 &&
5030 item->mib_id == MIB2_UDP6_ENTRY)))
5031 continue; /* 'for' loop 1 */
5032
5033 if (item->group == MIB2_UDP && !family_selected(AF_INET))
5034 continue; /* 'for' loop 1 */
5035 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
5036 continue; /* 'for' loop 1 */
5037
5038 /* xxx.xxx.xxx.xxx,pppp sss... */
5039 if (item->group == MIB2_UDP) {
5040 for (ude = (mib2_udpEntry_t *)item->valp;
5041 (char *)ude < (char *)item->valp + item->length;
5042 /* LINTED: (note 1) */
5043 ude = (mib2_udpEntry_t *)((char *)ude +
5044 udpEntrySize)) {
5045 aptr = v4a == NULL ? NULL : *v4a++;
5046 print_hdr_once_v4 = udp_report_item_v4(ude,
5047 print_hdr_once_v4, aptr);
5048 }
5049 } else {
5050 for (ude6 = (mib2_udp6Entry_t *)item->valp;
5051 (char *)ude6 < (char *)item->valp + item->length;
5052 /* LINTED: (note 1) */
5053 ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
5054 udp6EntrySize)) {
5055 aptr = v6a == NULL ? NULL : *v6a++;
5056 print_hdr_once_v6 = udp_report_item_v6(ude6,
5057 print_hdr_once_v6, aptr);
5058 }
5059 }
5060 } /* 'for' loop 1 ends */
5061 (void) fflush(stdout);
5062
5063 if (v4_attrs != NULL)
5064 free(v4_attrs);
5065 if (v6_attrs != NULL)
5066 free(v6_attrs);
5067 }
5068
5069 static boolean_t
5070 udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first,
5071 const mib2_transportMLPEntry_t *attr)
5072 {
5073 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5074 /* hostname + portname */
5075
5076 if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
5077 return (first); /* Nothing to print */
5078
5079 if (first) {
5080 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
5081 (void) printf(udp_hdr_v4);
5082 first = B_FALSE;
5083 }
5084
5085 (void) printf("%-20s ",
5086 pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
5087 lname, sizeof (lname)));
5088 (void) printf("%-20s %s\n",
5089 ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
5090 pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
5091 ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5092 "",
5093 miudp_state(ude->udpEntryInfo.ue_state, attr));
5094
5095 print_transport_label(attr);
5096
5097 return (first);
5098 }
5099
5100 static boolean_t
5101 udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first,
5102 const mib2_transportMLPEntry_t *attr)
5103 {
5104 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5105 /* hostname + portname */
5106 char ifname[LIFNAMSIZ + 1];
5107 const char *ifnamep;
5108
5109 if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
5110 return (first); /* Nothing to print */
5111
5112 if (first) {
5113 (void) printf("\nUDP: IPv6\n");
5114 (void) printf(udp_hdr_v6);
5115 first = B_FALSE;
5116 }
5117
5118 ifnamep = (ude6->udp6IfIndex != 0) ?
5119 if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
5120
5121 (void) printf("%-33s ",
5122 pr_ap6(&ude6->udp6LocalAddress,
5123 ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
5124 (void) printf("%-33s %-10s %s\n",
5125 ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
5126 pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
5127 ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5128 "",
5129 miudp_state(ude6->udp6EntryInfo.ue_state, attr),
5130 ifnamep == NULL ? "" : ifnamep);
5131
5132 print_transport_label(attr);
5133
5134 return (first);
5135 }
5136
5137 /* ------------------------------ SCTP_REPORT------------------------------- */
5138
5139 static const char sctp_hdr[] =
5140 "\nSCTP:";
5141 static const char sctp_hdr_normal[] =
5142 " Local Address Remote Address "
5143 "Swind Send-Q Rwind Recv-Q StrsI/O State\n"
5144 "------------------------------- ------------------------------- "
5145 "------ ------ ------ ------ ------- -----------";
5146
5147 static const char *
5148 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
5149 {
5150 static char sctpsbuf[50];
5151 const char *cp;
5152
5153 switch (state) {
5154 case MIB2_SCTP_closed:
5155 cp = "CLOSED";
5156 break;
5157 case MIB2_SCTP_cookieWait:
5158 cp = "COOKIE_WAIT";
5159 break;
5160 case MIB2_SCTP_cookieEchoed:
5161 cp = "COOKIE_ECHOED";
5162 break;
5163 case MIB2_SCTP_established:
5164 cp = "ESTABLISHED";
5165 break;
5292 } else {
5293 (void) pr_addr(v4addr, name, namelen);
5294 }
5295 break;
5296
5297 case MIB2_SCTP_ADDR_V6:
5298 /* v6 */
5299 if (port > 0) {
5300 (void) pr_ap6(addr, port, "sctp", name, namelen);
5301 } else {
5302 (void) pr_addr6(addr, name, namelen);
5303 }
5304 break;
5305
5306 default:
5307 (void) snprintf(name, namelen, "<unknown addr type>");
5308 break;
5309 }
5310 }
5311
5312 static void
5313 sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp,
5314 const mib2_transportMLPEntry_t *attr)
5315 {
5316 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5317 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5318 const mib2_sctpConnRemoteEntry_t *sre = NULL;
5319 const mib2_sctpConnLocalEntry_t *sle = NULL;
5320 const mib_item_t *local = head;
5321 const mib_item_t *remote = head;
5322 uint32_t id = sp->sctpAssocId;
5323 boolean_t printfirst = B_TRUE;
5324
5325 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5326 &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5327 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5328 &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5329
5330 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5331 lname, fname,
5332 sp->sctpConnEntryInfo.ce_swnd,
5333 sp->sctpConnEntryInfo.ce_sendq,
5334 sp->sctpConnEntryInfo.ce_rwnd,
5335 sp->sctpConnEntryInfo.ce_recvq,
5336 sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5337 nssctp_state(sp->sctpAssocState, attr));
5338
5339 print_transport_label(attr);
5340
5341 if (!Vflag) {
5342 return;
5343 }
5344
5345 /* Print remote addresses/local addresses on following lines */
5346 while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5347 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5348 &sp->sctpAssocRemPrimAddr)) {
5349 if (printfirst == B_TRUE) {
5350 (void) fputs("\t<Remote: ", stdout);
5351 printfirst = B_FALSE;
5352 } else {
5353 (void) fputs(", ", stdout);
5354 }
5355 sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5356 sizeof (fname), &sre->sctpAssocRemAddr, -1);
5357 if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5358 (void) fputs(fname, stdout);
5359 } else {
5360 (void) printf("(%s)", fname);
5361 }
5362 }
5365 (void) puts(">");
5366 printfirst = B_TRUE;
5367 }
5368 while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5369 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5370 &sp->sctpAssocLocPrimAddr)) {
5371 if (printfirst == B_TRUE) {
5372 (void) fputs("\t<Local: ", stdout);
5373 printfirst = B_FALSE;
5374 } else {
5375 (void) fputs(", ", stdout);
5376 }
5377 sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5378 sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5379 (void) fputs(lname, stdout);
5380 }
5381 }
5382 if (printfirst == B_FALSE) {
5383 (void) puts(">");
5384 }
5385 }
5386
5387 static void
5388 sctp_report(const mib_item_t *item)
5389 {
5390 const mib_item_t *head;
5391 const mib2_sctpConnEntry_t *sp;
5392 boolean_t first = B_TRUE;
5393 mib2_transportMLPEntry_t **attrs, **aptr;
5394 mib2_transportMLPEntry_t *attr;
5395
5396 /*
5397 * Preparation pass: the kernel returns separate entries for SCTP
5398 * connection table entries and Multilevel Port attributes. We loop
5399 * through the attributes first and set up an array for each address
5400 * family.
5401 */
5402 attrs = RSECflag ?
5403 gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5404 NULL;
5405
5406 aptr = attrs;
5407 head = item;
5408 for (; item != NULL; item = item->next_item) {
5409
5410 if (!(item->group == MIB2_SCTP &&
5411 item->mib_id == MIB2_SCTP_CONN))
5412 continue;
5413
5414 for (sp = item->valp;
5415 (char *)sp < (char *)item->valp + item->length;
5416 /* LINTED: (note 1) */
5417 sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
5418 attr = aptr == NULL ? NULL : *aptr++;
5419 if (Aflag ||
5420 sp->sctpAssocState >= MIB2_SCTP_established) {
5421 if (first == B_TRUE) {
5422 (void) puts(sctp_hdr);
5423 (void) puts(sctp_hdr_normal);
5424 first = B_FALSE;
5425 }
5426 sctp_conn_report_item(head, sp, attr);
5427 }
5428 }
5429 }
5430 if (attrs != NULL)
5431 free(attrs);
5432 }
5433
5434 static char *
5435 plural(int n)
5436 {
5437 return (n != 1 ? "s" : "");
5438 }
5439
5440 static char *
5441 pluraly(int n)
5442 {
5443 return (n != 1 ? "ies" : "y");
5444 }
5445
5446 static char *
5447 plurales(int n)
5448 {
5449 return (n != 1 ? "es" : "");
5450 }
5451
5452 static char *
5453 pktscale(n)
5454 int n;
5455 {
5456 static char buf[6];
5457 char t;
5458
5459 if (n < 1024) {
5460 t = ' ';
5461 } else if (n < 1024 * 1024) {
5462 t = 'k';
5463 n /= 1024;
5464 } else if (n < 1024 * 1024 * 1024) {
5465 t = 'm';
5466 n /= 1024 * 1024;
5467 } else {
5468 t = 'g';
5469 n /= 1024 * 1024 * 1024;
5470 }
5471
5472 (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5473 return (buf);
5474 }
6394 }
6395 return (B_FALSE);
6396 }
6397
6398 /*
6399 * Convert the interface index to a string using the buffer `ifname', which
6400 * must be at least LIFNAMSIZ bytes. We first try to map it to name. If that
6401 * fails (e.g., because we're inside a zone and it does not have access to
6402 * interface for the index in question), just return "if#<num>".
6403 */
6404 static char *
6405 ifindex2str(uint_t ifindex, char *ifname)
6406 {
6407 if (if_indextoname(ifindex, ifname) == NULL)
6408 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6409
6410 return (ifname);
6411 }
6412
6413 /*
6414 * print the usage line
6415 */
6416 static void
6417 usage(char *cmdname)
6418 {
6419 (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] "
6420 "[-T d|u]\n", cmdname);
6421 (void) fprintf(stderr, " %s [-n] [-f address_family] "
6422 "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6423 cmdname);
6424 (void) fprintf(stderr, " %s -m [-v] [-T d|u] "
6425 "[interval [count]]\n", cmdname);
6426 (void) fprintf(stderr, " %s -i [-I interface] [-an] "
6427 "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6428 (void) fprintf(stderr, " %s -r [-anv] "
6429 "[-f address_family|filter] [-T d|u]\n", cmdname);
6430 (void) fprintf(stderr, " %s -M [-ns] [-f address_family] "
6431 "[-T d|u]\n", cmdname);
6432 (void) fprintf(stderr, " %s -D [-I interface] "
6433 "[-f address_family] [-T d|u]\n", cmdname);
6434 exit(EXIT_FAILURE);
6435 }
6436
6437 /*
6438 * fatal: print error message to stderr and
6439 * call exit(errcode)
6440 */
6441 /*PRINTFLIKE2*/
6442 static void
6443 fatal(int errcode, char *format, ...)
6444 {
6445 va_list argp;
6446
6447 if (format == NULL)
6448 return;
6449
6450 va_start(argp, format);
6451 (void) vfprintf(stderr, format, argp);
6452 va_end(argp);
6453
6454 exit(errcode);
6455 }
|
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.
41 *
42 * TODO:
43 * Add ability to request subsets from kernel (with level = MIB2_IP;
44 * name = 0 meaning everything for compatibility)
45 */
46
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>
58 #include <pwd.h>
59 #include <limits.h>
60
61 #include <sys/types.h>
62 #include <sys/stat.h>
63 #include <sys/stream.h>
64 #include <stropts.h>
65 #include <sys/strstat.h>
66 #include <sys/tihdr.h>
67 #include <procfs.h>
68
69 #include <sys/socket.h>
70 #include <sys/socketvar.h>
71 #include <sys/sockio.h>
72 #include <netinet/in.h>
73 #include <net/if.h>
74 #include <net/route.h>
75
76 #include <inet/mib2.h>
77 #include <inet/ip.h>
78 #include <inet/arp.h>
79 #include <inet/tcp.h>
80 #include <netinet/igmp_var.h>
81 #include <netinet/ip_mroute.h>
82
83 #include <arpa/inet.h>
84 #include <netdb.h>
85 #include <fcntl.h>
86 #include <sys/systeminfo.h>
87 #include <arpa/inet.h>
88
89 #include <netinet/dhcp.h>
90 #include <dhcpagent_ipc.h>
91 #include <dhcpagent_util.h>
92 #include <compat.h>
93
94 #include <libtsnet.h>
95 #include <tsol/label.h>
96
97 #include "statcommon.h"
98
99
100 #define STR_EXPAND 4
101
102 #define V4MASK_TO_V6(v4, v6) ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
103 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \
104 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \
105 (v6)._S6_un._S6_u32[3] = (v4))
106
107 #define IN6_IS_V4MASK(v6) ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
108 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \
109 (v6)._S6_un._S6_u32[2] == 0xfffffffful)
110
111 /*
112 * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
113 * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
114 * possible for an administrator to plumb new interfaces between those two
115 * calls, resulting in the failure of the latter. This addition makes that
116 * less likely.
117 */
118 #define LIFN_GUARD_VALUE 10
122 int group;
123 int mib_id;
124 int length;
125 void *valp;
126 } mib_item_t;
127
128 struct ifstat {
129 uint64_t ipackets;
130 uint64_t ierrors;
131 uint64_t opackets;
132 uint64_t oerrors;
133 uint64_t collisions;
134 };
135
136 struct iflist {
137 struct iflist *next_if;
138 char ifname[LIFNAMSIZ];
139 struct ifstat tot;
140 };
141
142 typedef struct proc_info {
143 char *pr_user;
144 char *pr_fname;
145 char *pr_psargs;
146 } proc_info_t;
147
148 static mib_item_t *mibget(int sd);
149 static void mibfree(mib_item_t *firstitem);
150 static int mibopen(void);
151 static void mib_get_constants(mib_item_t *item);
152 static mib_item_t *mib_item_dup(mib_item_t *item);
153 static mib_item_t *mib_item_diff(mib_item_t *item1,
154 mib_item_t *item2);
155 static void mib_item_destroy(mib_item_t **item);
156
157 static boolean_t octetstrmatch(const Octet_t *a, const Octet_t *b);
158 static char *octetstr(const Octet_t *op, int code,
159 char *dst, uint_t dstlen);
160 static char *pr_addr(uint_t addr,
161 char *dst, uint_t dstlen);
162 static char *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
163 static char *pr_addr6(const in6_addr_t *addr,
164 char *dst, uint_t dstlen);
165 static char *pr_mask(uint_t addr,
166 char *dst, uint_t dstlen);
167 static char *pr_prefix6(const struct in6_addr *addr,
184 const mib2_transportMLPEntry_t *attr);
185
186 static void stat_report(mib_item_t *item);
187 static void mrt_stat_report(mib_item_t *item);
188 static void arp_report(mib_item_t *item);
189 static void ndp_report(mib_item_t *item);
190 static void mrt_report(mib_item_t *item);
191 static void if_stat_total(struct ifstat *oldstats,
192 struct ifstat *newstats, struct ifstat *sumstats);
193 static void if_report(mib_item_t *item, char *ifname,
194 int Iflag_only, boolean_t once_only);
195 static void if_report_ip4(mib2_ipAddrEntry_t *ap,
196 char ifname[], char logintname[],
197 struct ifstat *statptr, boolean_t ksp_not_null);
198 static void if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
199 char ifname[], char logintname[],
200 struct ifstat *statptr, boolean_t ksp_not_null);
201 static void ire_report(const mib_item_t *item);
202 static void tcp_report(const mib_item_t *item);
203 static void udp_report(const mib_item_t *item);
204 static void uds_report(kstat_ctl_t *);
205 static void group_report(mib_item_t *item);
206 static void dce_report(mib_item_t *item);
207 static void print_ip_stats(mib2_ip_t *ip);
208 static void print_icmp_stats(mib2_icmp_t *icmp);
209 static void print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
210 static void print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
211 static void print_sctp_stats(mib2_sctp_t *tcp);
212 static void print_tcp_stats(mib2_tcp_t *tcp);
213 static void print_udp_stats(mib2_udp_t *udp);
214 static void print_rawip_stats(mib2_rawip_t *rawip);
215 static void print_igmp_stats(struct igmpstat *igps);
216 static void print_mrt_stats(struct mrtstat *mrts);
217 static void sctp_report(const mib_item_t *item);
218 static void sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
219 mib2_ipv6IfStatsEntry_t *sum6);
220 static void sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
221 mib2_ipv6IfIcmpEntry_t *sum6);
222 static void m_report(void);
223 static void dhcp_report(char *);
224
225 static uint64_t kstat_named_value(kstat_t *, char *);
226 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
227 static int isnum(char *);
228 static char *plural(int n);
229 static char *pluraly(int n);
230 static char *plurales(int n);
231 static void process_filter(char *arg);
232 static char *ifindex2str(uint_t, char *);
233 static boolean_t family_selected(int family);
234
235 static void usage(char *);
236 static char *get_username(uid_t);
237 proc_info_t *get_proc_info(pid_t);
238 static void fatal(int errcode, char *str1, ...);
239
240 #define PLURAL(n) plural((int)n)
241 #define PLURALY(n) pluraly((int)n)
242 #define PLURALES(n) plurales((int)n)
243 #define IFLAGMOD(flg, val1, val2) if (flg == val1) flg = val2
244 #define MDIFF(diff, elem2, elem1, member) (diff)->member = \
245 (elem2)->member - (elem1)->member
246
247
248 static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */
249 static boolean_t Dflag = B_FALSE; /* DCE info */
250 static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */
251 static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */
252 static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */
253 static boolean_t Rflag = B_FALSE; /* Routing Tables */
254 static boolean_t RSECflag = B_FALSE; /* Security attributes */
255 static boolean_t Sflag = B_FALSE; /* Per-protocol Statistics */
256 static boolean_t Vflag = B_FALSE; /* Verbose */
257 static boolean_t Uflag = B_FALSE; /* Show PID and UID info. */
258 static boolean_t Pflag = B_FALSE; /* Net to Media Tables */
259 static boolean_t Gflag = B_FALSE; /* Multicast group membership */
260 static boolean_t MMflag = B_FALSE; /* Multicast routing table */
261 static boolean_t DHCPflag = B_FALSE; /* DHCP statistics */
262 static boolean_t Xflag = B_FALSE; /* Debug Info */
263
264 static int v4compat = 0; /* Compatible printing format for status */
265
266 static int proto = IPPROTO_MAX; /* all protocols */
267 kstat_ctl_t *kc = NULL;
268
269 /*
270 * Sizes of data structures extracted from the base mib.
271 * This allows the size of the tables entries to grow while preserving
272 * binary compatibility.
273 */
274 static int ipAddrEntrySize;
275 static int ipRouteEntrySize;
276 static int ipNetToMediaEntrySize;
277 static int ipMemberEntrySize;
382 * 1, IFlag is the only feature-flag enabled
383 * : trinary variable, modified using IFLAGMOD()
384 */
385 int Iflag_only = -1;
386 boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
387 extern char *optarg;
388 extern int optind;
389 char *default_ip_str = NULL;
390
391 name = argv[0];
392
393 v4compat = get_compat_flag(&default_ip_str);
394 if (v4compat == DEFAULT_PROT_BAD_VALUE)
395 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
396 default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
397 free(default_ip_str);
398
399 (void) setlocale(LC_ALL, "");
400 (void) textdomain(TEXT_DOMAIN);
401
402 while ((c = getopt(argc, argv, "adimnrspMgvuxf:P:I:DRT:")) != -1) {
403 switch ((char)c) {
404 case 'a': /* all connections */
405 Aflag = B_TRUE;
406 break;
407
408 case 'd': /* DCE info */
409 Dflag = B_TRUE;
410 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
411 break;
412
413 case 'i': /* interface (ill/ipif report) */
414 Iflag = B_TRUE;
415 IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
416 break;
417
418 case 'm': /* streams msg report */
419 Mflag = B_TRUE;
420 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
421 break;
422
442 case 'p': /* arp/ndp table */
443 Pflag = B_TRUE;
444 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
445 break;
446
447 case 'M': /* multicast routing tables */
448 MMflag = B_TRUE;
449 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
450 break;
451
452 case 'g': /* multicast group membership */
453 Gflag = B_TRUE;
454 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
455 break;
456
457 case 'v': /* verbose output format */
458 Vflag = B_TRUE;
459 IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
460 break;
461
462 case 'u': /* show pid and uid information */
463 Uflag = B_TRUE;
464 break;
465
466 case 'x': /* turn on debugging */
467 Xflag = B_TRUE;
468 break;
469
470 case 'f':
471 process_filter(optarg);
472 break;
473
474 case 'P':
475 if (strcmp(optarg, "ip") == 0) {
476 proto = IPPROTO_IP;
477 } else if (strcmp(optarg, "ipv6") == 0 ||
478 strcmp(optarg, "ip6") == 0) {
479 v4compat = 0; /* Overridden */
480 proto = IPPROTO_IPV6;
481 } else if (strcmp(optarg, "icmp") == 0) {
482 proto = IPPROTO_ICMP;
483 } else if (strcmp(optarg, "icmpv6") == 0 ||
484 strcmp(optarg, "icmp6") == 0) {
485 v4compat = 0; /* Overridden */
655 if (MMflag)
656 mrt_report(item);
657 }
658 if (Gflag)
659 group_report(item);
660 if (Pflag) {
661 if (family_selected(AF_INET))
662 arp_report(item);
663 if (family_selected(AF_INET6))
664 ndp_report(item);
665 }
666 if (Dflag)
667 dce_report(item);
668 mib_item_destroy(&curritem);
669 }
670
671 /* netstat: AF_UNIX behaviour */
672 if (family_selected(AF_UNIX) &&
673 (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
674 MMflag || Pflag || Gflag)))
675 uds_report(kc);
676 (void) kstat_close(kc);
677
678 /* iteration handling code */
679 if (count > 0 && --count == 0)
680 break;
681 (void) sleep(interval);
682
683 /* re-populating of data structures */
684 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
685 if (Sflag) {
686 /* previtem is a cut-down list */
687 previtem = mib_item_dup(item);
688 if (previtem == NULL)
689 fatal(1, "can't process mib data, "
690 "out of memory\n");
691 }
692 mibfree(item);
693 (void) close(sd);
694 if ((sd = mibopen()) == -1)
695 fatal(1, "can't open mib stream anymore\n");
973 item->length);
974 tempp = &(localp[c]);
975 if (c > 0)
976 (localp[c - 1]).next_item = tempp;
977 c++;
978 }
979 }
980 return (localp);
981 }
982
983 /*
984 * mib_item_diff: takes two (mib_item_t *) linked lists
985 * item1 and item2 and computes the difference between
986 * differentiable values in item2 against item1 for every
987 * given member of item2; returns an mib_item_t * linked
988 * list of diff's, or a copy of item2 if item1 is NULL;
989 * will return NULL if system out of memory; works only
990 * for item->mib_id == 0
991 */
992 static mib_item_t *
993 mib_item_diff(mib_item_t *item1, mib_item_t *item2)
994 {
995 int nitems = 0; /* no. of items in item2 */
996 mib_item_t *tempp2; /* walking copy of item2 */
997 mib_item_t *tempp1; /* walking copy of item1 */
998 mib_item_t *diffp;
999 mib_item_t *diffptr; /* walking copy of diffp */
1000 mib_item_t *prevp = NULL;
1001
1002 if (item1 == NULL) {
1003 diffp = mib_item_dup(item2);
1004 return (diffp);
1005 }
1006
1007 for (tempp2 = item2;
1008 tempp2;
1009 tempp2 = tempp2->next_item) {
1010 if (tempp2->mib_id == 0)
1011 switch (tempp2->group) {
1012 /*
1013 * upon adding a case here, the same
1014 * must also be added in the next
1500 }
1501 } /* 'for' loop 2 ends */
1502 tempp1 = NULL;
1503 } /* 'for' loop 1 ends */
1504 tempp2 = NULL;
1505 diffptr--;
1506 diffptr->next_item = NULL;
1507 return (diffp);
1508
1509 mibdiff_out_of_memory:;
1510 mib_item_destroy(&diffp);
1511 return (NULL);
1512 }
1513
1514 /*
1515 * mib_item_destroy: cleans up a mib_item_t *
1516 * that was created by calling mib_item_dup or
1517 * mib_item_diff
1518 */
1519 static void
1520 mib_item_destroy(mib_item_t **itemp)
1521 {
1522 int nitems = 0;
1523 int c = 0;
1524 mib_item_t *tempp;
1525
1526 if (itemp == NULL || *itemp == NULL)
1527 return;
1528
1529 for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1530 if (tempp->mib_id == 0)
1531 nitems++;
1532 else
1533 return; /* cannot destroy! */
1534
1535 if (nitems == 0)
1536 return; /* cannot destroy! */
1537
1538 for (c = nitems - 1; c >= 0; c--) {
1539 if ((itemp[0][c]).valp != NULL)
1540 free((itemp[0][c]).valp);
1541 }
3266 old6 = new6;
3267 cleanlist = oldlist6;
3268 oldlist6 = newlist6;
3269 while (cleanlist != NULL) {
3270 tlp = cleanlist->next_if;
3271 free(cleanlist);
3272 cleanlist = tlp;
3273 }
3274 }
3275 break;
3276 }
3277 }
3278 (void) fflush(stdout);
3279 } /* 'for' loop 1 ends */
3280 if ((Iflag_only == 0) && (!once_only))
3281 (void) putchar('\n');
3282 reentry = B_TRUE;
3283 }
3284
3285 static void
3286 if_report_ip4(mib2_ipAddrEntry_t *ap, char ifname[], char logintname[],
3287 struct ifstat *statptr, boolean_t ksp_not_null)
3288 {
3289
3290 char abuf[MAXHOSTNAMELEN + 1];
3291 char dstbuf[MAXHOSTNAMELEN + 1];
3292
3293 if (ksp_not_null) {
3294 (void) printf("%-5s %-4u ",
3295 ifname, ap->ipAdEntInfo.ae_mtu);
3296 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3297 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3298 abuf, sizeof (abuf));
3299 else
3300 (void) pr_netaddr(ap->ipAdEntAddr,
3301 ap->ipAdEntNetMask, abuf, sizeof (abuf));
3302 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3303 "%-6llu %-6llu\n",
3304 abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3305 statptr->ipackets, statptr->ierrors,
3306 statptr->opackets, statptr->oerrors,
3307 statptr->collisions, 0LL);
3308 }
3314 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3315 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3316
3317 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3318 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3319 (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3320 sizeof (abuf));
3321 else
3322 (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3323 abuf, sizeof (abuf));
3324
3325 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3326 "%-5s %-6s %-6llu\n", abuf,
3327 pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3328 statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3329 0LL);
3330 }
3331 }
3332
3333 static void
3334 if_report_ip6(mib2_ipv6AddrEntry_t *ap6, char ifname[], char logintname[],
3335 struct ifstat *statptr, boolean_t ksp_not_null)
3336 {
3337
3338 char abuf[MAXHOSTNAMELEN + 1];
3339 char dstbuf[MAXHOSTNAMELEN + 1];
3340
3341 if (ksp_not_null) {
3342 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3343 if (ap6->ipv6AddrInfo.ae_flags &
3344 IFF_POINTOPOINT) {
3345 (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3346 abuf, sizeof (abuf));
3347 } else {
3348 (void) pr_prefix6(&ap6->ipv6AddrAddress,
3349 ap6->ipv6AddrPfxLength, abuf,
3350 sizeof (abuf));
3351 }
3352 (void) printf("%-27s %-27s %-6llu %-5llu "
3353 "%-6llu %-5llu %-6llu\n",
3354 abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3355 sizeof (dstbuf)),
3356 statptr->ipackets, statptr->ierrors, statptr->opackets,
4745 free(sl_str);
4746 }
4747 }
4748
4749 /* ------------------------------ TCP_REPORT------------------------------- */
4750
4751 static const char tcp_hdr_v4[] =
4752 "\nTCP: IPv4\n";
4753 static const char tcp_hdr_v4_compat[] =
4754 "\nTCP\n";
4755 static const char tcp_hdr_v4_verbose[] =
4756 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack "
4757 " Rto Mss State\n"
4758 "-------------------- ----- -------- -------- ----- -------- -------- "
4759 "----- ----- -----------\n";
4760 static const char tcp_hdr_v4_normal[] =
4761 " Local Address Remote Address Swind Send-Q Rwind Recv-Q "
4762 " State\n"
4763 "-------------------- -------------------- ----- ------ ----- ------ "
4764 "-----------\n";
4765 static const char tcp_hdr_v4_pid[] =
4766 " Local Address Remote Address User Pid Command Swind"
4767 " Send-Q Rwind Recv-Q State\n"
4768 "-------------------- -------------------- -------- ------ ------------- ------"
4769 "- ------ ------- ------ -----------\n";
4770 static const char tcp_hdr_v4_pid_verbose[] =
4771 "Local/Remote Address Swind Snext Suna Rwind Rnext Rack Rto "
4772 " Mss State User Pid Command\n"
4773 "-------------------- ------- -------- -------- ------- -------- -------- -----"
4774 " ----- ----------- -------- ------ --------------\n";
4775
4776 static const char tcp_hdr_v6[] =
4777 "\nTCP: IPv6\n";
4778 static const char tcp_hdr_v6_verbose[] =
4779 "Local/Remote Address Swind Snext Suna Rwind Rnext "
4780 " Rack Rto Mss State If\n"
4781 "--------------------------------- ----- -------- -------- ----- -------- "
4782 "-------- ----- ----- ----------- -----\n";
4783 static const char tcp_hdr_v6_normal[] =
4784 " Local Address Remote Address "
4785 "Swind Send-Q Rwind Recv-Q State If\n"
4786 "--------------------------------- --------------------------------- "
4787 "----- ------ ----- ------ ----------- -----\n";
4788 static const char tcp_hdr_v6_pid[] =
4789 " Local Address Remote Address User"
4790 " Pid Command Swind Send-Q Rwind Recv-Q State If\n"
4791 "--------------------------------- --------------------------------- --------"
4792 " ------ -------------- ------- ------ ------- ------ ----------- -----\n";
4793 static const char tcp_hdr_v6_pid_verbose[] =
4794 "Local/Remote Address Swind Snext Suna Rwind Rnext"
4795 " Rack Rto Mss State If User Pid Command\n"
4796 "--------------------------------- ------- -------- -------- ------- --------"
4797 " -------- ----- ----- ----------- ----- -------- ------ --------------\n";
4798
4799 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4800 conn_pid_info_t *, boolean_t first,
4801 const mib2_transportMLPEntry_t *);
4802 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4803 conn_pid_info_t *, boolean_t first,
4804 const mib2_transportMLPEntry_t *);
4805
4806
4807 static void
4808 tcp_report(const mib_item_t *item)
4809 {
4810 int jtemp = 0;
4811 boolean_t print_hdr_once_v4 = B_TRUE;
4812 boolean_t print_hdr_once_v6 = B_TRUE;
4813 mib2_tcpConnEntry_t *tp;
4814 mib2_tcp6ConnEntry_t *tp6;
4815 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
4816 mib2_transportMLPEntry_t **v4a, **v6a;
4817 mib2_transportMLPEntry_t *aptr;
4818 conn_pid_info_t *cpi;
4819
4820 if (!protocol_selected(IPPROTO_TCP))
4821 return;
4822
4823 /*
4824 * Preparation pass: the kernel returns separate entries for TCP
4825 * connection table entries and Multilevel Port attributes. We loop
4826 * through the attributes first and set up an array for each address
4827 * family.
4828 */
4829 v4_attrs = family_selected(AF_INET) && RSECflag ?
4830 gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) :
4831 NULL;
4832 v6_attrs = family_selected(AF_INET6) && RSECflag ?
4833 gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) :
4834 NULL;
4835
4836 /* 'for' loop 1: */
4837 v4a = v4_attrs;
4838 v6a = v6_attrs;
4839 for (; item != NULL; item = item->next_item) {
4840 if (Xflag) {
4841 (void) printf("\n--- Entry %d ---\n", ++jtemp);
4842 (void) printf("Group = %d, mib_id = %d, "
4843 "length = %d, valp = 0x%p\n",
4844 item->group, item->mib_id,
4845 item->length, item->valp);
4846 }
4847
4848 if (!((item->group == MIB2_TCP &&
4849 item->mib_id == MIB2_TCP_CONN) ||
4850 (item->group == MIB2_TCP6 &&
4851 item->mib_id == MIB2_TCP6_CONN) ||
4852 (item->group == MIB2_TCP &&
4853 item->mib_id == EXPER_XPORT_PROC_INFO) ||
4854 (item->group == MIB2_TCP6 &&
4855 item->mib_id == EXPER_XPORT_PROC_INFO)))
4856 continue; /* 'for' loop 1 */
4857
4858 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4859 continue; /* 'for' loop 1 */
4860 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4861 continue; /* 'for' loop 1 */
4862
4863 if ((!Uflag) && item->group == MIB2_TCP &&
4864 item->mib_id == MIB2_TCP_CONN) {
4865 for (tp = (mib2_tcpConnEntry_t *)item->valp;
4866 (char *)tp < (char *)item->valp + item->length;
4867 /* LINTED: (note 1) */
4868 tp = (mib2_tcpConnEntry_t *)((char *)tp +
4869 tcpConnEntrySize)) {
4870 aptr = v4a == NULL ? NULL : *v4a++;
4871 print_hdr_once_v4 = tcp_report_item_v4(tp,
4872 NULL, print_hdr_once_v4, aptr);
4873 }
4874 } else if ((!Uflag) && item->group == MIB2_TCP6 &&
4875 item->mib_id == MIB2_TCP6_CONN) {
4876 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4877 (char *)tp6 < (char *)item->valp + item->length;
4878 /* LINTED: (note 1) */
4879 tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4880 tcp6ConnEntrySize)) {
4881 aptr = v6a == NULL ? NULL : *v6a++;
4882 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4883 NULL, print_hdr_once_v6, aptr);
4884 }
4885 } else if ((Uflag) && item->group == MIB2_TCP &&
4886 item->mib_id == EXPER_XPORT_PROC_INFO) {
4887 for (tp = (mib2_tcpConnEntry_t *)item->valp;
4888 (char *)tp < (char *)item->valp + item->length;
4889 /* LINTED: (note 1) */
4890 tp = (mib2_tcpConnEntry_t *)((char *)cpi +
4891 cpi->cpi_tot_size)) {
4892 aptr = v4a == NULL ? NULL : *v4a++;
4893 /* LINTED: (note 1) */
4894 cpi = (conn_pid_info_t *)((char *)tp +
4895 tcpConnEntrySize);
4896 print_hdr_once_v4 = tcp_report_item_v4(tp,
4897 cpi, print_hdr_once_v4, aptr);
4898 }
4899 } else if ((Uflag) && item->group == MIB2_TCP6 &&
4900 item->mib_id == EXPER_XPORT_PROC_INFO) {
4901 for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4902 (char *)tp6 < (char *)item->valp + item->length;
4903 /* LINTED: (note 1) */
4904 tp6 = (mib2_tcp6ConnEntry_t *)((char *)cpi +
4905 cpi->cpi_tot_size)) {
4906 aptr = v6a == NULL ? NULL : *v6a++;
4907 /* LINTED: (note 1) */
4908 cpi = (conn_pid_info_t *)((char *)tp6 +
4909 tcp6ConnEntrySize);
4910 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4911 cpi, print_hdr_once_v6, aptr);
4912 }
4913 }
4914
4915 } /* 'for' loop 1 ends */
4916 (void) fflush(stdout);
4917
4918 if (v4_attrs != NULL)
4919 free(v4_attrs);
4920 if (v6_attrs != NULL)
4921 free(v6_attrs);
4922 }
4923
4924 static boolean_t
4925 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, conn_pid_info_t *cpi,
4926 boolean_t first, const mib2_transportMLPEntry_t *attr)
4927 {
4928 /*
4929 * lname and fname below are for the hostname as well as the portname
4930 * There is no limit on portname length so we assume MAXHOSTNAMELEN
4931 * as the limit
4932 */
4933 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4934 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4935
4936
4937 if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4938 return (first); /* Nothing to print */
4939
4940 if (first) {
4941 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4942 if (Uflag)
4943 (void) printf(Vflag ? tcp_hdr_v4_pid_verbose :
4944 tcp_hdr_v4_pid);
4945 else
4946 (void) printf(Vflag ? tcp_hdr_v4_verbose :
4947 tcp_hdr_v4_normal);
4948 }
4949
4950 if ((!Uflag) && Vflag) {
4951 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4952 "%5u %5u %s\n",
4953 pr_ap(tp->tcpConnLocalAddress,
4954 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4955 pr_ap(tp->tcpConnRemAddress,
4956 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4957 tp->tcpConnEntryInfo.ce_swnd,
4958 tp->tcpConnEntryInfo.ce_snxt,
4959 tp->tcpConnEntryInfo.ce_suna,
4960 tp->tcpConnEntryInfo.ce_rwnd,
4961 tp->tcpConnEntryInfo.ce_rnxt,
4962 tp->tcpConnEntryInfo.ce_rack,
4963 tp->tcpConnEntryInfo.ce_rto,
4964 tp->tcpConnEntryInfo.ce_mss,
4965 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4966 } else if ((!Uflag) && (!Vflag)) {
4967 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4968 (int)tp->tcpConnEntryInfo.ce_suna - 1;
4969 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4970 (int)tp->tcpConnEntryInfo.ce_rack;
4971
4972 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
4973 pr_ap(tp->tcpConnLocalAddress,
4974 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4975 pr_ap(tp->tcpConnRemAddress,
4976 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4977 tp->tcpConnEntryInfo.ce_swnd,
4978 (sq >= 0) ? sq : 0,
4979 tp->tcpConnEntryInfo.ce_rwnd,
4980 (rq >= 0) ? rq : 0,
4981 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4982 } else if (Uflag && Vflag) {
4983 int i = 0;
4984 pid_t *pids = cpi->cpi_pids;
4985 proc_info_t *pinfo;
4986 do {
4987 pinfo = get_proc_info(*pids);
4988 (void) printf("%-20s\n%-20s %7u %08x %08x %7u %08x "
4989 "%08x %5u %5u %-11s %-8.8s %6u %s\n",
4990 pr_ap(tp->tcpConnLocalAddress,
4991 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4992 pr_ap(tp->tcpConnRemAddress,
4993 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4994 tp->tcpConnEntryInfo.ce_swnd,
4995 tp->tcpConnEntryInfo.ce_snxt,
4996 tp->tcpConnEntryInfo.ce_suna,
4997 tp->tcpConnEntryInfo.ce_rwnd,
4998 tp->tcpConnEntryInfo.ce_rnxt,
4999 tp->tcpConnEntryInfo.ce_rack,
5000 tp->tcpConnEntryInfo.ce_rto,
5001 tp->tcpConnEntryInfo.ce_mss,
5002 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr),
5003 pinfo->pr_user, (int)*pids, pinfo->pr_psargs);
5004 i++; pids++;
5005 } while (i < cpi->cpi_pids_cnt);
5006 } else if (Uflag && (!Vflag)) {
5007 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
5008 (int)tp->tcpConnEntryInfo.ce_suna - 1;
5009 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
5010 (int)tp->tcpConnEntryInfo.ce_rack;
5011 int i = 0;
5012 pid_t *pids = cpi->cpi_pids;
5013 proc_info_t *pinfo;
5014 do {
5015 pinfo = get_proc_info(*pids);
5016 (void) printf("%-20s %-20s %-8.8s %6u %-13.13s %7u "
5017 "%6d %7u %6d %s\n",
5018 pr_ap(tp->tcpConnLocalAddress,
5019 tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
5020 pr_ap(tp->tcpConnRemAddress,
5021 tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
5022 pinfo->pr_user, (int)*pids, pinfo->pr_fname,
5023 tp->tcpConnEntryInfo.ce_swnd,
5024 (sq >= 0) ? sq : 0,
5025 tp->tcpConnEntryInfo.ce_rwnd,
5026 (rq >= 0) ? rq : 0,
5027 mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
5028 i++; pids++;
5029 } while (i < cpi->cpi_pids_cnt);
5030 }
5031
5032 print_transport_label(attr);
5033
5034 return (B_FALSE);
5035 }
5036
5037 static boolean_t
5038 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, conn_pid_info_t *cpi,
5039 boolean_t first, const mib2_transportMLPEntry_t *attr)
5040 {
5041 /*
5042 * lname and fname below are for the hostname as well as the portname
5043 * There is no limit on portname length so we assume MAXHOSTNAMELEN
5044 * as the limit
5045 */
5046 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5047 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5048 char ifname[LIFNAMSIZ + 1];
5049 char *ifnamep;
5050
5051 if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
5052 return (first); /* Nothing to print */
5053
5054 if (first) {
5055 (void) printf(tcp_hdr_v6);
5056 if (Uflag)
5057 (void) printf(Vflag ? tcp_hdr_v6_pid_verbose :
5058 tcp_hdr_v6_pid);
5059 else
5060 (void) printf(Vflag ? tcp_hdr_v6_verbose :
5061 tcp_hdr_v6_normal);
5062 }
5063
5064 ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
5065 if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
5066 if (ifnamep == NULL)
5067 ifnamep = "";
5068
5069 if ((!Uflag) && Vflag) {
5070 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
5071 "%5u %5u %-11s %s\n",
5072 pr_ap6(&tp6->tcp6ConnLocalAddress,
5073 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5074 pr_ap6(&tp6->tcp6ConnRemAddress,
5075 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5076 tp6->tcp6ConnEntryInfo.ce_swnd,
5077 tp6->tcp6ConnEntryInfo.ce_snxt,
5078 tp6->tcp6ConnEntryInfo.ce_suna,
5079 tp6->tcp6ConnEntryInfo.ce_rwnd,
5080 tp6->tcp6ConnEntryInfo.ce_rnxt,
5081 tp6->tcp6ConnEntryInfo.ce_rack,
5082 tp6->tcp6ConnEntryInfo.ce_rto,
5083 tp6->tcp6ConnEntryInfo.ce_mss,
5084 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5085 ifnamep);
5086 } else if ((!Uflag) && (!Vflag)) {
5087 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5088 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5089 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5090 (int)tp6->tcp6ConnEntryInfo.ce_rack;
5091
5092 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
5093 pr_ap6(&tp6->tcp6ConnLocalAddress,
5094 tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5095 pr_ap6(&tp6->tcp6ConnRemAddress,
5096 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5097 tp6->tcp6ConnEntryInfo.ce_swnd,
5098 (sq >= 0) ? sq : 0,
5099 tp6->tcp6ConnEntryInfo.ce_rwnd,
5100 (rq >= 0) ? rq : 0,
5101 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5102 ifnamep);
5103 } else if (Uflag && Vflag) {
5104 int i = 0;
5105 pid_t *pids = cpi->cpi_pids;
5106 proc_info_t *pinfo;
5107 do {
5108 pinfo = get_proc_info(*pids);
5109 (void) printf("%-33s\n%-33s %7u %08x %08x %7u %08x "
5110 "%08x %5u %5u %-11s %-5.5s %-8.8s %6u %s\n",
5111 pr_ap6(&tp6->tcp6ConnLocalAddress,
5112 tp6->tcp6ConnLocalPort, "tcp", lname,
5113 sizeof (lname)),
5114 pr_ap6(&tp6->tcp6ConnRemAddress,
5115 tp6->tcp6ConnRemPort, "tcp", fname,
5116 sizeof (fname)),
5117 tp6->tcp6ConnEntryInfo.ce_swnd,
5118 tp6->tcp6ConnEntryInfo.ce_snxt,
5119 tp6->tcp6ConnEntryInfo.ce_suna,
5120 tp6->tcp6ConnEntryInfo.ce_rwnd,
5121 tp6->tcp6ConnEntryInfo.ce_rnxt,
5122 tp6->tcp6ConnEntryInfo.ce_rack,
5123 tp6->tcp6ConnEntryInfo.ce_rto,
5124 tp6->tcp6ConnEntryInfo.ce_mss,
5125 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5126 ifnamep, pinfo->pr_user, (int)*pids,
5127 pinfo->pr_psargs);
5128 i++; pids++;
5129 } while (i < cpi->cpi_pids_cnt);
5130 } else if (Uflag && (!Vflag)) {
5131 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5132 (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5133 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5134 (int)tp6->tcp6ConnEntryInfo.ce_rack;
5135 int i = 0;
5136 pid_t *pids = cpi->cpi_pids;
5137 proc_info_t *pinfo;
5138 do {
5139 pinfo = get_proc_info(*pids);
5140 (void) printf("%-33s %-33s %-8.8s %6u %-14.14s %7d "
5141 "%6u %7d %6d %-11s %s\n",
5142 pr_ap6(&tp6->tcp6ConnLocalAddress,
5143 tp6->tcp6ConnLocalPort, "tcp", lname,
5144 sizeof (lname)),
5145 pr_ap6(&tp6->tcp6ConnRemAddress,
5146 tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5147 pinfo->pr_user, (int)*pids, pinfo->pr_fname,
5148 tp6->tcp6ConnEntryInfo.ce_swnd,
5149 (sq >= 0) ? sq : 0,
5150 tp6->tcp6ConnEntryInfo.ce_rwnd,
5151 (rq >= 0) ? rq : 0,
5152 mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5153 ifnamep);
5154 i++; pids++;
5155 } while (i < cpi->cpi_pids_cnt);
5156 }
5157
5158 print_transport_label(attr);
5159
5160 return (B_FALSE);
5161 }
5162
5163 /* ------------------------------- UDP_REPORT------------------------------- */
5164
5165 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
5166 conn_pid_info_t *cpi, boolean_t first,
5167 const mib2_transportMLPEntry_t *attr);
5168 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
5169 conn_pid_info_t *cpi, boolean_t first,
5170 const mib2_transportMLPEntry_t *attr);
5171
5172 static const char udp_hdr_v4[] =
5173 " Local Address Remote Address State\n"
5174 "-------------------- -------------------- ----------\n";
5175 static const char udp_hdr_v4_pid[] =
5176 " Local Address Remote Address User Pid "
5177 " Command State\n"
5178 "-------------------- -------------------- -------- ------ "
5179 "-------------- ----------\n";
5180 static const char udp_hdr_v4_pid_verbose[] =
5181 " Local Address Remote Address User Pid State "
5182 " Command\n"
5183 "-------------------- -------------------- -------- ------ ---------- "
5184 "----------------\n";
5185
5186 static const char udp_hdr_v6[] =
5187 " Local Address Remote Address "
5188 " State If\n"
5189 "--------------------------------- --------------------------------- "
5190 "---------- -----\n";
5191 static const char udp_hdr_v6_pid[] =
5192 " Local Address Remote Address "
5193 " User Pid Command State If\n"
5194 "--------------------------------- --------------------------------- "
5195 "-------- ------ -------------- ---------- -----\n";
5196 static const char udp_hdr_v6_pid_verbose[] =
5197 " Local Address Remote Address "
5198 " User Pid State If Command\n"
5199 "--------------------------------- --------------------------------- "
5200 "-------- ------ ---------- ----- ----------------\n";
5201
5202
5203 static void
5204 udp_report(const mib_item_t *item)
5205 {
5206 int jtemp = 0;
5207 boolean_t print_hdr_once_v4 = B_TRUE;
5208 boolean_t print_hdr_once_v6 = B_TRUE;
5209 mib2_udpEntry_t *ude;
5210 mib2_udp6Entry_t *ude6;
5211 mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
5212 mib2_transportMLPEntry_t **v4a, **v6a;
5213 mib2_transportMLPEntry_t *aptr;
5214 conn_pid_info_t *cpi;
5215
5216 if (!protocol_selected(IPPROTO_UDP))
5217 return;
5218
5219 /*
5220 * Preparation pass: the kernel returns separate entries for UDP
5221 * connection table entries and Multilevel Port attributes. We loop
5222 * through the attributes first and set up an array for each address
5223 * family.
5224 */
5225 v4_attrs = family_selected(AF_INET) && RSECflag ?
5226 gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
5227 v6_attrs = family_selected(AF_INET6) && RSECflag ?
5228 gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
5229 NULL;
5230
5231 v4a = v4_attrs;
5232 v6a = v6_attrs;
5233 /* 'for' loop 1: */
5234 for (; item; item = item->next_item) {
5235 if (Xflag) {
5236 (void) printf("\n--- Entry %d ---\n", ++jtemp);
5237 (void) printf("Group = %d, mib_id = %d, "
5238 "length = %d, valp = 0x%p\n",
5239 item->group, item->mib_id,
5240 item->length, item->valp);
5241 }
5242 if (!((item->group == MIB2_UDP &&
5243 item->mib_id == MIB2_UDP_ENTRY) ||
5244 (item->group == MIB2_UDP6 &&
5245 item->mib_id == MIB2_UDP6_ENTRY) ||
5246 (item->group == MIB2_UDP &&
5247 item->mib_id == EXPER_XPORT_PROC_INFO) ||
5248 (item->group == MIB2_UDP6 &&
5249 item->mib_id == EXPER_XPORT_PROC_INFO)))
5250 continue; /* 'for' loop 1 */
5251
5252 if (item->group == MIB2_UDP && !family_selected(AF_INET))
5253 continue; /* 'for' loop 1 */
5254 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
5255 continue; /* 'for' loop 1 */
5256
5257 /* xxx.xxx.xxx.xxx,pppp sss... */
5258 if ((!Uflag) && item->group == MIB2_UDP &&
5259 item->mib_id == MIB2_UDP_ENTRY) {
5260 for (ude = (mib2_udpEntry_t *)item->valp;
5261 (char *)ude < (char *)item->valp + item->length;
5262 /* LINTED: (note 1) */
5263 ude = (mib2_udpEntry_t *)((char *)ude +
5264 udpEntrySize)) {
5265 aptr = v4a == NULL ? NULL : *v4a++;
5266 print_hdr_once_v4 = udp_report_item_v4(ude,
5267 NULL, print_hdr_once_v4, aptr);
5268 }
5269 } else if ((!Uflag) && item->group == MIB2_UDP6 &&
5270 item->mib_id == MIB2_UDP6_ENTRY) {
5271 for (ude6 = (mib2_udp6Entry_t *)item->valp;
5272 (char *)ude6 < (char *)item->valp + item->length;
5273 /* LINTED: (note 1) */
5274 ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
5275 udp6EntrySize)) {
5276 aptr = v6a == NULL ? NULL : *v6a++;
5277 print_hdr_once_v6 = udp_report_item_v6(ude6,
5278 NULL, print_hdr_once_v6, aptr);
5279 }
5280 } else if ((Uflag) && item->group == MIB2_UDP &&
5281 item->mib_id == EXPER_XPORT_PROC_INFO) {
5282 for (ude = (mib2_udpEntry_t *)item->valp;
5283 (char *)ude < (char *)item->valp + item->length;
5284 /* LINTED: (note 1) */
5285 ude = (mib2_udpEntry_t *)((char *)cpi +
5286 cpi->cpi_tot_size)) {
5287 aptr = v4a == NULL ? NULL : *v4a++;
5288 /* LINTED: (note 1) */
5289 cpi = (conn_pid_info_t *)((char *)ude +
5290 udpEntrySize);
5291 print_hdr_once_v4 = udp_report_item_v4(ude,
5292 cpi, print_hdr_once_v4, aptr);
5293 }
5294 } else if ((Uflag) && item->group == MIB2_UDP6 &&
5295 item->mib_id == EXPER_XPORT_PROC_INFO) {
5296 for (ude6 = (mib2_udp6Entry_t *)item->valp;
5297 (char *)ude6 < (char *)item->valp + item->length;
5298 /* LINTED: (note 1) */
5299 ude6 = (mib2_udp6Entry_t *)((char *)cpi +
5300 cpi->cpi_tot_size)) {
5301 aptr = v6a == NULL ? NULL : *v6a++;
5302 /* LINTED: (note 1) */
5303 cpi = (conn_pid_info_t *)((char *)ude6 +
5304 udp6EntrySize);
5305 print_hdr_once_v6 = udp_report_item_v6(ude6,
5306 cpi, print_hdr_once_v6, aptr);
5307 }
5308 }
5309 } /* 'for' loop 1 ends */
5310 (void) fflush(stdout);
5311
5312 if (v4_attrs != NULL)
5313 free(v4_attrs);
5314 if (v6_attrs != NULL)
5315 free(v6_attrs);
5316 }
5317
5318 static boolean_t
5319 udp_report_item_v4(const mib2_udpEntry_t *ude, conn_pid_info_t *cpi,
5320 boolean_t first, const mib2_transportMLPEntry_t *attr)
5321 {
5322 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5323 /* hostname + portname */
5324
5325 if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
5326 return (first); /* Nothing to print */
5327
5328 if (first) {
5329 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
5330
5331 if (Uflag)
5332 (void) printf(Vflag ? udp_hdr_v4_pid_verbose :
5333 udp_hdr_v4_pid);
5334 else
5335 (void) printf(udp_hdr_v4);
5336
5337 first = B_FALSE;
5338 }
5339
5340 (void) printf("%-20s %-20s ",
5341 pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
5342 lname, sizeof (lname)),
5343 ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
5344 pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
5345 ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5346 "");
5347 if (!Uflag) {
5348 (void) printf("%s\n",
5349 miudp_state(ude->udpEntryInfo.ue_state, attr));
5350 } else {
5351 int i = 0;
5352 pid_t *pids = cpi->cpi_pids;
5353 proc_info_t *pinfo;
5354 do {
5355 pinfo = get_proc_info(*pids);
5356 (void) printf("%-8.8s %6u ", pinfo->pr_user,
5357 (int)*pids);
5358 if (Vflag) {
5359 (void) printf("%-10.10s %s\n",
5360 miudp_state(ude->udpEntryInfo.ue_state,
5361 attr),
5362 pinfo->pr_psargs);
5363 } else {
5364 (void) printf("%-14.14s %s\n", pinfo->pr_fname,
5365 miudp_state(ude->udpEntryInfo.ue_state,
5366 attr));
5367 }
5368 i++; pids++;
5369 } while (i < cpi->cpi_pids_cnt);
5370 }
5371
5372 print_transport_label(attr);
5373
5374 return (first);
5375 }
5376
5377 static boolean_t
5378 udp_report_item_v6(const mib2_udp6Entry_t *ude6, conn_pid_info_t *cpi,
5379 boolean_t first, const mib2_transportMLPEntry_t *attr)
5380 {
5381 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5382 /* hostname + portname */
5383 char ifname[LIFNAMSIZ + 1];
5384 const char *ifnamep;
5385
5386 if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
5387 return (first); /* Nothing to print */
5388
5389 if (first) {
5390 (void) printf("\nUDP: IPv6\n");
5391
5392 if (Uflag)
5393 (void) printf(Vflag ? udp_hdr_v6_pid_verbose :
5394 udp_hdr_v6_pid);
5395 else
5396 (void) printf(udp_hdr_v6);
5397
5398 first = B_FALSE;
5399 }
5400
5401 ifnamep = (ude6->udp6IfIndex != 0) ?
5402 if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
5403
5404 (void) printf("%-33s %-33s ",
5405 pr_ap6(&ude6->udp6LocalAddress,
5406 ude6->udp6LocalPort, "udp", lname, sizeof (lname)),
5407 ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
5408 pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
5409 ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5410 "");
5411 if (!Uflag) {
5412 (void) printf("%-10s %s\n",
5413 miudp_state(ude6->udp6EntryInfo.ue_state, attr),
5414 ifnamep == NULL ? "" : ifnamep);
5415 } else {
5416 int i = 0;
5417 pid_t *pids = cpi->cpi_pids;
5418 proc_info_t *pinfo;
5419 do {
5420 pinfo = get_proc_info(*pids);
5421 (void) printf("%-8.8s %6u ", pinfo->pr_user,
5422 (int)*pids);
5423 if (Vflag) {
5424 (void) printf("%-10.10s %-5.5s %s\n",
5425 miudp_state(ude6->udp6EntryInfo.ue_state,
5426 attr),
5427 ifnamep == NULL ? "" : ifnamep,
5428 pinfo->pr_psargs);
5429 } else {
5430 (void) printf("%-14.14s %-10.10s %s\n",
5431 pinfo->pr_fname,
5432 miudp_state(ude6->udp6EntryInfo.ue_state,
5433 attr),
5434 ifnamep == NULL ? "" : ifnamep);
5435 }
5436 i++; pids++;
5437 } while (i < cpi->cpi_pids_cnt);
5438 }
5439
5440 print_transport_label(attr);
5441
5442 return (first);
5443 }
5444
5445 /* ------------------------------ SCTP_REPORT------------------------------- */
5446
5447 static const char sctp_hdr[] =
5448 "\nSCTP:";
5449 static const char sctp_hdr_normal[] =
5450 " Local Address Remote Address "
5451 "Swind Send-Q Rwind Recv-Q StrsI/O State\n"
5452 "------------------------------- ------------------------------- "
5453 "------ ------ ------ ------ ------- -----------";
5454 static const char sctp_hdr_pid[] =
5455 " Local Address Remote Address "
5456 "Swind Send-Q Rwind Recv-Q StrsI/O User Pid Command State\n"
5457 "------------------------------- ------------------------------- ------ "
5458 "------ ------ ------ ------- -------- ------ -------------- -----------";
5459 static const char sctp_hdr_pid_verbose[] =
5460 " Local Address Remote Address "
5461 "Swind Send-Q Rwind Recv-Q StrsI/O User Pid State Command\n"
5462 "------------------------------- ------------------------------- ------ "
5463 "------ ------ ------ ------- -------- ------ ----------- --------------";
5464
5465 static const char *
5466 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
5467 {
5468 static char sctpsbuf[50];
5469 const char *cp;
5470
5471 switch (state) {
5472 case MIB2_SCTP_closed:
5473 cp = "CLOSED";
5474 break;
5475 case MIB2_SCTP_cookieWait:
5476 cp = "COOKIE_WAIT";
5477 break;
5478 case MIB2_SCTP_cookieEchoed:
5479 cp = "COOKIE_ECHOED";
5480 break;
5481 case MIB2_SCTP_established:
5482 cp = "ESTABLISHED";
5483 break;
5610 } else {
5611 (void) pr_addr(v4addr, name, namelen);
5612 }
5613 break;
5614
5615 case MIB2_SCTP_ADDR_V6:
5616 /* v6 */
5617 if (port > 0) {
5618 (void) pr_ap6(addr, port, "sctp", name, namelen);
5619 } else {
5620 (void) pr_addr6(addr, name, namelen);
5621 }
5622 break;
5623
5624 default:
5625 (void) snprintf(name, namelen, "<unknown addr type>");
5626 break;
5627 }
5628 }
5629
5630 static boolean_t
5631 sctp_conn_report_item(const mib_item_t *head, conn_pid_info_t *cpi,
5632 boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp,
5633 const mib2_transportMLPEntry_t *attr)
5634 {
5635 char lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5636 char fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5637 const mib2_sctpConnRemoteEntry_t *sre = NULL;
5638 const mib2_sctpConnLocalEntry_t *sle = NULL;
5639 const mib_item_t *local = head;
5640 const mib_item_t *remote = head;
5641 uint32_t id = sp->sctpAssocId;
5642 boolean_t printfirst = B_TRUE;
5643
5644 if (print_sctp_hdr == B_TRUE) {
5645 (void) puts(sctp_hdr);
5646 if (Uflag)
5647 (void) puts(Vflag? sctp_hdr_pid_verbose: sctp_hdr_pid);
5648 else
5649 (void) puts(sctp_hdr_normal);
5650
5651 print_sctp_hdr = B_FALSE;
5652 }
5653
5654 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5655 &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5656 sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5657 &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5658
5659 if (Uflag) {
5660 int i = 0;
5661 pid_t *pids = cpi->cpi_pids;
5662 proc_info_t *pinfo;
5663 do {
5664 pinfo = get_proc_info(*pids);
5665 (void) printf("%-31s %-31s %6u %6d %6u %6d "
5666 "%3d/%-3d %-8.8s %6u ",
5667 lname, fname,
5668 sp->sctpConnEntryInfo.ce_swnd,
5669 sp->sctpConnEntryInfo.ce_sendq,
5670 sp->sctpConnEntryInfo.ce_rwnd,
5671 sp->sctpConnEntryInfo.ce_recvq,
5672 sp->sctpAssocInStreams,
5673 sp->sctpAssocOutStreams,
5674 pinfo->pr_user, (int)*pids);
5675 if (Vflag) {
5676 (void) printf("%-11.11s %s\n",
5677 nssctp_state(sp->sctpAssocState, attr),
5678 pinfo->pr_psargs);
5679 } else {
5680 (void) printf("%-14.14s %s\n",
5681 pinfo->pr_fname,
5682 nssctp_state(sp->sctpAssocState, attr));
5683 }
5684 i++; pids++;
5685 } while (i < cpi->cpi_pids_cnt);
5686
5687 } else {
5688
5689 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5690 lname, fname,
5691 sp->sctpConnEntryInfo.ce_swnd,
5692 sp->sctpConnEntryInfo.ce_sendq,
5693 sp->sctpConnEntryInfo.ce_rwnd,
5694 sp->sctpConnEntryInfo.ce_recvq,
5695 sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5696 nssctp_state(sp->sctpAssocState, attr));
5697 }
5698
5699 print_transport_label(attr);
5700
5701 if (!Vflag) {
5702 return (print_sctp_hdr);
5703 }
5704
5705 /* Print remote addresses/local addresses on following lines */
5706 while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5707 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5708 &sp->sctpAssocRemPrimAddr)) {
5709 if (printfirst == B_TRUE) {
5710 (void) fputs("\t<Remote: ", stdout);
5711 printfirst = B_FALSE;
5712 } else {
5713 (void) fputs(", ", stdout);
5714 }
5715 sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5716 sizeof (fname), &sre->sctpAssocRemAddr, -1);
5717 if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5718 (void) fputs(fname, stdout);
5719 } else {
5720 (void) printf("(%s)", fname);
5721 }
5722 }
5725 (void) puts(">");
5726 printfirst = B_TRUE;
5727 }
5728 while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5729 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5730 &sp->sctpAssocLocPrimAddr)) {
5731 if (printfirst == B_TRUE) {
5732 (void) fputs("\t<Local: ", stdout);
5733 printfirst = B_FALSE;
5734 } else {
5735 (void) fputs(", ", stdout);
5736 }
5737 sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5738 sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5739 (void) fputs(lname, stdout);
5740 }
5741 }
5742 if (printfirst == B_FALSE) {
5743 (void) puts(">");
5744 }
5745
5746 return (print_sctp_hdr);
5747 }
5748
5749 static void
5750 sctp_report(const mib_item_t *item)
5751 {
5752 const mib_item_t *head;
5753 const mib2_sctpConnEntry_t *sp;
5754 boolean_t print_sctp_hdr_once = B_TRUE;
5755 mib2_transportMLPEntry_t **attrs, **aptr;
5756 mib2_transportMLPEntry_t *attr;
5757 conn_pid_info_t *cpi;
5758
5759 /*
5760 * Preparation pass: the kernel returns separate entries for SCTP
5761 * connection table entries and Multilevel Port attributes. We loop
5762 * through the attributes first and set up an array for each address
5763 * family.
5764 */
5765 attrs = RSECflag ?
5766 gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5767 NULL;
5768
5769 aptr = attrs;
5770 head = item;
5771 for (; item != NULL; item = item->next_item) {
5772
5773 if (!((item->group == MIB2_SCTP &&
5774 item->mib_id == MIB2_SCTP_CONN) ||
5775 (item->group == MIB2_SCTP &&
5776 item->mib_id == EXPER_XPORT_PROC_INFO)))
5777 continue;
5778
5779 if ((!Uflag) && item->group == MIB2_SCTP &&
5780 item->mib_id == MIB2_SCTP_CONN) {
5781 for (sp = item->valp;
5782 (char *)sp < (char *)item->valp + item->length;
5783 /* LINTED: (note 1) */
5784 sp = (mib2_sctpConnEntry_t *)((char *)sp +
5785 sctpEntrySize)) {
5786 if (!(Aflag ||
5787 sp->sctpAssocState >=
5788 MIB2_SCTP_established))
5789 continue;
5790 attr = aptr == NULL ? NULL : *aptr++;
5791 print_sctp_hdr_once = sctp_conn_report_item(
5792 head, NULL, print_sctp_hdr_once, sp, attr);
5793 }
5794 } else if ((Uflag) && item->group == MIB2_SCTP &&
5795 item->mib_id == EXPER_XPORT_PROC_INFO) {
5796 for (sp = (mib2_sctpConnEntry_t *)item->valp;
5797 (char *)sp < (char *)item->valp + item->length;
5798 /* LINTED: (note 1) */
5799 sp = (mib2_sctpConnEntry_t *)((char *)cpi +
5800 cpi->cpi_tot_size)) {
5801 /* LINTED: (note 1) */
5802 cpi = (conn_pid_info_t *)((char *)sp +
5803 sctpEntrySize);
5804 if (!(Aflag ||
5805 sp->sctpAssocState >=
5806 MIB2_SCTP_established))
5807 continue;
5808 attr = aptr == NULL ? NULL : *aptr++;
5809 print_sctp_hdr_once = sctp_conn_report_item(
5810 head, cpi, print_sctp_hdr_once, sp, attr);
5811 }
5812 }
5813 }
5814 if (attrs != NULL)
5815 free(attrs);
5816 }
5817
5818 static char *
5819 plural(int n)
5820 {
5821 return (n != 1 ? "s" : "");
5822 }
5823
5824 static char *
5825 pluraly(int n)
5826 {
5827 return (n != 1 ? "ies" : "y");
5828 }
5829
5830 static char *
5831 plurales(int n)
5832 {
5833 return (n != 1 ? "es" : "");
5834 }
5835
5836 static char *
5837 pktscale(int n)
5838 {
5839 static char buf[6];
5840 char t;
5841
5842 if (n < 1024) {
5843 t = ' ';
5844 } else if (n < 1024 * 1024) {
5845 t = 'k';
5846 n /= 1024;
5847 } else if (n < 1024 * 1024 * 1024) {
5848 t = 'm';
5849 n /= 1024 * 1024;
5850 } else {
5851 t = 'g';
5852 n /= 1024 * 1024 * 1024;
5853 }
5854
5855 (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5856 return (buf);
5857 }
6777 }
6778 return (B_FALSE);
6779 }
6780
6781 /*
6782 * Convert the interface index to a string using the buffer `ifname', which
6783 * must be at least LIFNAMSIZ bytes. We first try to map it to name. If that
6784 * fails (e.g., because we're inside a zone and it does not have access to
6785 * interface for the index in question), just return "if#<num>".
6786 */
6787 static char *
6788 ifindex2str(uint_t ifindex, char *ifname)
6789 {
6790 if (if_indextoname(ifindex, ifname) == NULL)
6791 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6792
6793 return (ifname);
6794 }
6795
6796 /*
6797 * Gets proc info in (proc_info_t) given pid. It doesn't return NULL.
6798 */
6799 proc_info_t *
6800 get_proc_info(pid_t pid)
6801 {
6802 static pid_t saved_pid = 0;
6803 static proc_info_t saved_proc_info;
6804 static proc_info_t unknown_proc_info = {"<unknown>", "", ""};
6805 static psinfo_t pinfo;
6806 char path[128];
6807 int fd;
6808
6809 /* hardcode pid = 0 */
6810 if (pid == 0) {
6811 saved_proc_info.pr_user = "root";
6812 saved_proc_info.pr_fname = "sched";
6813 saved_proc_info.pr_psargs = "sched";
6814 saved_pid = 0;
6815 return (&saved_proc_info);
6816 }
6817
6818 if (pid == saved_pid)
6819 return (&saved_proc_info);
6820 if ((snprintf(path, 128, "/proc/%u/psinfo", (int)pid) > 0) &&
6821 ((fd = open(path, O_RDONLY)) != -1)) {
6822 if (read(fd, &pinfo, sizeof (pinfo)) == sizeof (pinfo)) {
6823 saved_proc_info.pr_user = get_username(pinfo.pr_uid);
6824 saved_proc_info.pr_fname = pinfo.pr_fname;
6825 saved_proc_info.pr_psargs = pinfo.pr_psargs;
6826 saved_pid = pid;
6827 (void) close(fd);
6828 return (&saved_proc_info);
6829 } else {
6830 (void) close(fd);
6831 }
6832 }
6833
6834 return (&unknown_proc_info);
6835 }
6836
6837 /*
6838 * Gets username given uid. It doesn't return NULL.
6839 */
6840 static char *
6841 get_username(uid_t u)
6842 {
6843 static uid_t saved_uid = UINT_MAX;
6844 static char saved_username[128];
6845 struct passwd *pw = NULL;
6846 if (u == UINT_MAX)
6847 return ("<unknown>");
6848 if (u == saved_uid && saved_username[0] != '\0')
6849 return (saved_username);
6850 setpwent();
6851 if ((pw = getpwuid(u)) != NULL)
6852 (void) strlcpy(saved_username, pw->pw_name, 128);
6853 else
6854 (void) snprintf(saved_username, 128, "%u", u);
6855 saved_uid = u;
6856 return (saved_username);
6857 }
6858
6859 /*
6860 * print the usage line
6861 */
6862 static void
6863 usage(char *cmdname)
6864 {
6865 (void) fprintf(stderr, "usage: %s [-anuv] [-f address_family] "
6866 "[-T d|u]\n", cmdname);
6867 (void) fprintf(stderr, " %s [-n] [-f address_family] "
6868 "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6869 cmdname);
6870 (void) fprintf(stderr, " %s -m [-v] [-T d|u] "
6871 "[interval [count]]\n", cmdname);
6872 (void) fprintf(stderr, " %s -i [-I interface] [-an] "
6873 "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6874 (void) fprintf(stderr, " %s -r [-anv] "
6875 "[-f address_family|filter] [-T d|u]\n", cmdname);
6876 (void) fprintf(stderr, " %s -M [-ns] [-f address_family] "
6877 "[-T d|u]\n", cmdname);
6878 (void) fprintf(stderr, " %s -D [-I interface] "
6879 "[-f address_family] [-T d|u]\n", cmdname);
6880 exit(EXIT_FAILURE);
6881 }
6882
6883 /*
6884 * fatal: print error message to stderr and
6885 * call exit(errcode)
6886 */
6887 /*PRINTFLIKE2*/
6888 static void
6889 fatal(int errcode, char *format, ...)
6890 {
6891 va_list argp;
6892
6893 if (format == NULL)
6894 return;
6895
6896 va_start(argp, format);
6897 (void) vfprintf(stderr, format, argp);
6898 va_end(argp);
6899
6900 exit(errcode);
6901 }
6902
6903
6904 /* -------------------UNIX Domain Sockets Report---------------------------- */
6905
6906
6907 #define NO_ADDR " "
6908 #define SO_PAIR " (socketpair) "
6909
6910 static char *typetoname(t_scalar_t);
6911 static boolean_t uds_report_item(struct sockinfo *, boolean_t);
6912
6913
6914 static char uds_hdr[] = "\nActive UNIX domain sockets\n";
6915
6916 static char uds_hdr_normal[] =
6917 " Type Local Adress "
6918 " Remote Address\n"
6919 "---------- --------------------------------------- "
6920 "---------------------------------------\n";
6921
6922 static char uds_hdr_pid[] =
6923 " Type User Pid Command "
6924 " Local Address "
6925 " Remote Address\n"
6926 "---------- -------- ------ -------------- "
6927 "--------------------------------------- "
6928 "---------------------------------------\n";
6929 static char uds_hdr_pid_verbose[] =
6930 " Type User Pid Local Address "
6931 " Remote Address Command\n"
6932 "---------- -------- ------ --------------------------------------- "
6933 "--------------------------------------- --------------\n";
6934
6935 /*
6936 * Print a summary of connections related to unix protocols.
6937 */
6938 static void
6939 uds_report(kstat_ctl_t *kc)
6940 {
6941 int i;
6942 kstat_t *ksp;
6943 struct sockinfo *psi;
6944 boolean_t print_uds_hdr_once = B_TRUE;
6945
6946 if (kc == NULL) {
6947 fail(0, "uds_report: No kstat");
6948 exit(3);
6949 }
6950
6951 if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) ==
6952 (kstat_t *)NULL) {
6953 fail(0, "kstat_data_lookup failed\n");
6954 }
6955
6956 if (kstat_read(kc, ksp, NULL) == -1) {
6957 fail(0, "kstat_read failed for sock_unix_list\n");
6958 }
6959
6960 if (ksp->ks_ndata == 0) {
6961 return; /* no AF_UNIX sockets found */
6962 }
6963
6964 /*
6965 * Having ks_data set with ks_data == NULL shouldn't happen;
6966 * If it does, the sockfs kstat is seriously broken.
6967 */
6968 if ((psi = ksp->ks_data) == NULL) {
6969 fail(0, "uds_report: no kstat data\n");
6970 }
6971
6972 for (i = 0; i < ksp->ks_ndata; i++) {
6973
6974 print_uds_hdr_once = uds_report_item(psi, print_uds_hdr_once);
6975
6976 /* if si_size didn't get filled in, then we're done */
6977 if (psi->si_size == 0 ||
6978 !IS_P2ALIGNED(psi->si_size, sizeof (psi))) {
6979 break;
6980 }
6981
6982 /* point to the next sockinfo in the array */
6983 /* LINTED: (note 1) */
6984 psi = (struct sockinfo *)(((char *)psi) + psi->si_size);
6985 }
6986 }
6987
6988 static boolean_t
6989 uds_report_item(struct sockinfo *psi, boolean_t first)
6990 {
6991 int i = 0;
6992 pid_t *pids;
6993 proc_info_t *pinfo;
6994 char *laddr, *raddr;
6995
6996 if (first) {
6997 (void) printf("%s", uds_hdr);
6998 if (Uflag)
6999 (void) printf("%s", Vflag?uds_hdr_pid_verbose:
7000 uds_hdr_pid);
7001 else
7002 (void) printf("%s", uds_hdr_normal);
7003
7004 first = B_FALSE;
7005 }
7006
7007 pids = psi->si_pids;
7008
7009 do {
7010 pinfo = get_proc_info(*pids);
7011 raddr = laddr = NO_ADDR;
7012
7013 /* Try to fill laddr */
7014 if ((psi->si_state & SS_ISBOUND) &&
7015 strlen(psi->si_laddr_sun_path) != 0 &&
7016 psi->si_laddr_soa_len != 0) {
7017 if (psi->si_faddr_noxlate) {
7018 laddr = SO_PAIR;
7019 } else {
7020 if (psi->si_laddr_soa_len >
7021 sizeof (psi->si_laddr_family))
7022 laddr = psi->si_laddr_sun_path;
7023 }
7024 }
7025
7026 /* Try to fill raddr */
7027 if ((psi->si_state & SS_ISCONNECTED) &&
7028 strlen(psi->si_faddr_sun_path) != 0 &&
7029 psi->si_faddr_soa_len != 0) {
7030
7031 if (psi->si_faddr_noxlate) {
7032 raddr = SO_PAIR;
7033 } else {
7034 if (psi->si_faddr_soa_len >
7035 sizeof (psi->si_faddr_family))
7036 raddr = psi->si_faddr_sun_path;
7037 }
7038 }
7039
7040 if (Uflag && Vflag) {
7041 (void) printf("%-10.10s %-8.8s %6u "
7042 "%-39.39s %-39.39s %s\n",
7043 typetoname(psi->si_serv_type), pinfo->pr_user,
7044 (int)*pids, laddr, raddr, pinfo->pr_psargs);
7045 } else if (Uflag && (!Vflag)) {
7046 (void) printf("%-10.10s %-8.8s %6u %-14.14s"
7047 "%-39.39s %-39.39s\n",
7048 typetoname(psi->si_serv_type), pinfo->pr_user,
7049 (int)*pids, pinfo->pr_fname, laddr, raddr);
7050 } else {
7051 (void) printf("%-10.10s %s %s\n",
7052 typetoname(psi->si_serv_type), laddr, raddr);
7053 }
7054
7055 i++; pids++;
7056 } while (i < psi->si_pn_cnt);
7057
7058 return (first);
7059 }
7060
7061 static char *
7062 typetoname(t_scalar_t type)
7063 {
7064 switch (type) {
7065 case T_CLTS:
7066 return ("dgram");
7067
7068 case T_COTS:
7069 return ("stream");
7070
7071 case T_COTS_ORD:
7072 return ("stream-ord");
7073
7074 default:
7075 return ("");
7076 }
7077 }
|