Print this page
XXXX adding PID information to netstat output


  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");


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 *


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");


4743                 free(sl_str);
4744         }
4745 }
4746 
4747 /* ------------------------------ TCP_REPORT------------------------------- */
4748 
4749 static const char tcp_hdr_v4[] =
4750 "\nTCP: IPv4\n";
4751 static const char tcp_hdr_v4_compat[] =
4752 "\nTCP\n";
4753 static const char tcp_hdr_v4_verbose[] =
4754 "Local/Remote Address Swind  Snext     Suna   Rwind  Rnext     Rack   "
4755 " Rto   Mss     State\n"
4756 "-------------------- ----- -------- -------- ----- -------- -------- "
4757 "----- ----- -----------\n";
4758 static const char tcp_hdr_v4_normal[] =
4759 "   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q "
4760 "   State\n"
4761 "-------------------- -------------------- ----- ------ ----- ------ "
4762 "-----------\n";
4763 static const char tcp_hdr_v4_pid[] =
4764 "   Local Address        Remote Address      User     Pid     Command     Swind"
4765 "   Send-Q  Rwind  Recv-Q    State\n"
4766 "-------------------- -------------------- -------- ------ ------------- ------"
4767 "- ------ ------- ------ -----------\n";
4768 static const char tcp_hdr_v4_pid_verbose[] =
4769 "Local/Remote Address  Swind   Snext     Suna    Rwind   Rnext     Rack    Rto "
4770 "  Mss     State      User    Pid      Command\n"
4771 "-------------------- ------- -------- -------- ------- -------- -------- -----"
4772 " ----- ----------- -------- ------ --------------\n";
4773 
4774 static const char tcp_hdr_v6[] =
4775 "\nTCP: IPv6\n";
4776 static const char tcp_hdr_v6_verbose[] =
4777 "Local/Remote Address              Swind  Snext     Suna   Rwind  Rnext   "
4778 "  Rack    Rto   Mss    State      If\n"
4779 "--------------------------------- ----- -------- -------- ----- -------- "
4780 "-------- ----- ----- ----------- -----\n";
4781 static const char tcp_hdr_v6_normal[] =
4782 "   Local Address                     Remote Address                 "
4783 "Swind Send-Q Rwind Recv-Q   State      If\n"
4784 "--------------------------------- --------------------------------- "
4785 "----- ------ ----- ------ ----------- -----\n";
4786 static const char tcp_hdr_v6_pid[] =
4787 "   Local Address                     Remote Address                   User"
4788 "    Pid      Command      Swind  Send-Q  Rwind  Recv-Q   State      If\n"
4789 "--------------------------------- --------------------------------- --------"
4790 " ------ -------------- ------- ------ ------- ------ ----------- -----\n";
4791 static const char tcp_hdr_v6_pid_verbose[] =
4792 "Local/Remote Address               Swind   Snext     Suna    Rwind   Rnext"
4793 "     Rack    Rto   Mss    State      If     User    Pid     Command\n"
4794 "--------------------------------- ------- -------- -------- ------- --------"
4795 " -------- ----- ----- ----------- ----- -------- ------ --------------\n";
4796 
4797 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4798     conn_pid_info_t *, boolean_t first,
4799     const mib2_transportMLPEntry_t *);
4800 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4801     conn_pid_info_t *, boolean_t first,
4802     const mib2_transportMLPEntry_t *);
4803 
4804 
4805 static void
4806 tcp_report(const mib_item_t *item)
4807 {
4808         int                             jtemp = 0;
4809         boolean_t                       print_hdr_once_v4 = B_TRUE;
4810         boolean_t                       print_hdr_once_v6 = B_TRUE;
4811         mib2_tcpConnEntry_t             *tp;
4812         mib2_tcp6ConnEntry_t            *tp6;
4813         mib2_transportMLPEntry_t        **v4_attrs, **v6_attrs;
4814         mib2_transportMLPEntry_t        **v4a, **v6a;
4815         mib2_transportMLPEntry_t        *aptr;
4816         conn_pid_info_t                 *cpi;
4817 
4818         if (!protocol_selected(IPPROTO_TCP))
4819                 return;
4820 
4821         /*
4822          * Preparation pass: the kernel returns separate entries for TCP
4823          * connection table entries and Multilevel Port attributes.  We loop
4824          * through the attributes first and set up an array for each address
4825          * family.
4826          */
4827         v4_attrs = family_selected(AF_INET) && RSECflag ?
4828             gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) :
4829             NULL;
4830         v6_attrs = family_selected(AF_INET6) && RSECflag ?
4831             gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) :
4832             NULL;
4833 
4834         /* 'for' loop 1: */
4835         v4a = v4_attrs;
4836         v6a = v6_attrs;
4837         for (; item != NULL; item = item->next_item) {
4838                 if (Xflag) {
4839                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
4840                         (void) printf("Group = %d, mib_id = %d, "
4841                             "length = %d, valp = 0x%p\n",
4842                             item->group, item->mib_id,
4843                             item->length, item->valp);
4844                 }
4845 
4846                 if (!((item->group == MIB2_TCP &&
4847                     item->mib_id == MIB2_TCP_CONN) ||
4848                     (item->group == MIB2_TCP6 &&
4849                     item->mib_id == MIB2_TCP6_CONN) ||
4850                     (item->group == MIB2_TCP &&
4851                     item->mib_id == EXPER_XPORT_PROC_INFO) ||
4852                     (item->group == MIB2_TCP6 &&
4853                     item->mib_id == EXPER_XPORT_PROC_INFO)))
4854                         continue; /* 'for' loop 1 */
4855 
4856                 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4857                         continue; /* 'for' loop 1 */
4858                 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4859                         continue; /* 'for' loop 1 */
4860 
4861                 if ((!Uflag) && item->group == MIB2_TCP &&
4862                     item->mib_id == MIB2_TCP_CONN) {
4863                         for (tp = (mib2_tcpConnEntry_t *)item->valp;
4864                             (char *)tp < (char *)item->valp + item->length;
4865                             /* LINTED: (note 1) */
4866                             tp = (mib2_tcpConnEntry_t *)((char *)tp +
4867                             tcpConnEntrySize)) {
4868                                 aptr = v4a == NULL ? NULL : *v4a++;
4869                                 print_hdr_once_v4 = tcp_report_item_v4(tp,
4870                                     NULL, print_hdr_once_v4, aptr);
4871                         }
4872                 } else if ((!Uflag) && item->group == MIB2_TCP6 &&
4873                     item->mib_id == MIB2_TCP6_CONN) {
4874                         for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4875                             (char *)tp6 < (char *)item->valp + item->length;
4876                             /* LINTED: (note 1) */
4877                             tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4878                             tcp6ConnEntrySize)) {
4879                                 aptr = v6a == NULL ? NULL : *v6a++;
4880                                 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4881                                     NULL, print_hdr_once_v6, aptr);
4882                         }
4883                 } else if ((Uflag) && item->group == MIB2_TCP &&
4884                     item->mib_id == EXPER_XPORT_PROC_INFO) {
4885                         for (tp = (mib2_tcpConnEntry_t *)item->valp;
4886                             (char *)tp < (char *)item->valp + item->length;
4887                             /* LINTED: (note 1) */
4888                             tp = (mib2_tcpConnEntry_t *)((char *)cpi +
4889                             cpi->cpi_tot_size)) {
4890                                 aptr = v4a == NULL ? NULL : *v4a++;
4891                                 /* LINTED: (note 1) */
4892                                 cpi = (conn_pid_info_t *) ((char *)tp +
4893                                     tcpConnEntrySize);
4894                                 print_hdr_once_v4 = tcp_report_item_v4(tp,
4895                                     cpi, print_hdr_once_v4, aptr);
4896                         }
4897                 } else if ((Uflag) && item->group == MIB2_TCP6 &&
4898                     item->mib_id == EXPER_XPORT_PROC_INFO) {
4899                         for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4900                             (char *)tp6 < (char *)item->valp + item->length;
4901                             /* LINTED: (note 1) */
4902                             tp6 = (mib2_tcp6ConnEntry_t *)((char *)cpi +
4903                             cpi->cpi_tot_size)) {
4904                                 aptr = v6a == NULL ? NULL : *v6a++;
4905                                 /* LINTED: (note 1) */
4906                                 cpi = (conn_pid_info_t *) ((char *)tp6 +
4907                                     tcp6ConnEntrySize);
4908                                 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4909                                     cpi, print_hdr_once_v6, aptr);
4910                         }
4911                 }
4912 
4913         } /* 'for' loop 1 ends */
4914         (void) fflush(stdout);
4915 
4916         if (v4_attrs != NULL)
4917                 free(v4_attrs);
4918         if (v6_attrs != NULL)
4919                 free(v6_attrs);
4920 }
4921 
4922 static boolean_t
4923 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, conn_pid_info_t * cpi,
4924     boolean_t first, const mib2_transportMLPEntry_t *attr)
4925 {
4926         /*
4927          * lname and fname below are for the hostname as well as the portname
4928          * There is no limit on portname length so we assume MAXHOSTNAMELEN
4929          * as the limit
4930          */
4931         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4932         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4933 
4934 
4935         if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4936                 return (first); /* Nothing to print */
4937 
4938         if (first) {
4939                 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4940                 if (Uflag)
4941                         (void) printf(Vflag ? tcp_hdr_v4_pid_verbose :
4942                                 tcp_hdr_v4_pid);
4943                 else
4944                         (void) printf(Vflag ? tcp_hdr_v4_verbose :
4945                                 tcp_hdr_v4_normal);
4946         }
4947 
4948         if ((!Uflag) && Vflag) {
4949                 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4950                     "%5u %5u %s\n",
4951                     pr_ap(tp->tcpConnLocalAddress,
4952                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4953                     pr_ap(tp->tcpConnRemAddress,
4954                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4955                     tp->tcpConnEntryInfo.ce_swnd,
4956                     tp->tcpConnEntryInfo.ce_snxt,
4957                     tp->tcpConnEntryInfo.ce_suna,
4958                     tp->tcpConnEntryInfo.ce_rwnd,
4959                     tp->tcpConnEntryInfo.ce_rnxt,
4960                     tp->tcpConnEntryInfo.ce_rack,
4961                     tp->tcpConnEntryInfo.ce_rto,
4962                     tp->tcpConnEntryInfo.ce_mss,
4963                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4964         } else if ((!Uflag) && (!Vflag)) {
4965                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4966                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
4967                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4968                     (int)tp->tcpConnEntryInfo.ce_rack;
4969 
4970                 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
4971                     pr_ap(tp->tcpConnLocalAddress,
4972                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4973                     pr_ap(tp->tcpConnRemAddress,
4974                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4975                     tp->tcpConnEntryInfo.ce_swnd,
4976                     (sq >= 0) ? sq : 0,
4977                     tp->tcpConnEntryInfo.ce_rwnd,
4978                     (rq >= 0) ? rq : 0,
4979                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4980         } else if (Uflag && Vflag) {
4981                 int i = 0;
4982                 pid_t *pids = cpi->cpi_pids;
4983                 proc_info_t *pinfo;
4984                 do {
4985                         pinfo = get_proc_info(*pids);
4986                         (void) printf("%-20s\n%-20s %7u %08x %08x %7u %08x %08x "
4987                             "%5u %5u %-11s %-8.8s %6u %s\n",
4988                             pr_ap(tp->tcpConnLocalAddress,
4989                             tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4990                             pr_ap(tp->tcpConnRemAddress,
4991                             tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4992                             tp->tcpConnEntryInfo.ce_swnd,
4993                             tp->tcpConnEntryInfo.ce_snxt,
4994                             tp->tcpConnEntryInfo.ce_suna,
4995                             tp->tcpConnEntryInfo.ce_rwnd,
4996                             tp->tcpConnEntryInfo.ce_rnxt,
4997                             tp->tcpConnEntryInfo.ce_rack,
4998                             tp->tcpConnEntryInfo.ce_rto,
4999                             tp->tcpConnEntryInfo.ce_mss,
5000                             mitcp_state(tp->tcpConnEntryInfo.ce_state, attr),
5001                             pinfo->pr_user, (int)*pids, pinfo->pr_psargs);
5002                         i++; pids++;
5003                 } while (i < cpi->cpi_pids_cnt);
5004         } else if (Uflag && (!Vflag)) {
5005                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
5006                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
5007                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
5008                    (int)tp->tcpConnEntryInfo.ce_rack;
5009                 int i = 0;
5010                 pid_t *pids = cpi->cpi_pids;
5011                 proc_info_t *pinfo;
5012                 do {
5013                         pinfo = get_proc_info(*pids);
5014                         (void) printf("%-20s %-20s %-8.8s %6u %-13.13s %7u %6d %7u %6d %s\n",
5015                             pr_ap(tp->tcpConnLocalAddress,
5016                             tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
5017                             pr_ap(tp->tcpConnRemAddress,
5018                             tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
5019                             pinfo->pr_user, (int)*pids, pinfo->pr_fname,
5020                             tp->tcpConnEntryInfo.ce_swnd,
5021                             (sq >= 0) ? sq : 0,
5022                             tp->tcpConnEntryInfo.ce_rwnd,
5023                             (rq >= 0) ? rq : 0,
5024                             mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
5025                         i++; pids++;
5026                 } while (i < cpi->cpi_pids_cnt);
5027         }
5028 
5029         print_transport_label(attr);
5030 
5031         return (B_FALSE);
5032 }
5033 
5034 static boolean_t
5035 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, conn_pid_info_t *cpi,
5036     boolean_t first, const mib2_transportMLPEntry_t *attr)
5037 {
5038         /*
5039          * lname and fname below are for the hostname as well as the portname
5040          * There is no limit on portname length so we assume MAXHOSTNAMELEN
5041          * as the limit
5042          */
5043         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5044         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5045         char    ifname[LIFNAMSIZ + 1];
5046         char    *ifnamep;
5047 
5048         if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
5049                 return (first); /* Nothing to print */
5050 
5051         if (first) {
5052                 (void) printf(tcp_hdr_v6);
5053                 if (Uflag)
5054                         (void) printf(Vflag ? tcp_hdr_v6_pid_verbose :
5055                                 tcp_hdr_v6_pid);
5056                 else
5057                         (void) printf(Vflag ? tcp_hdr_v6_verbose :
5058                                 tcp_hdr_v6_normal);
5059         }
5060 
5061         ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
5062             if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
5063         if (ifnamep == NULL)
5064                 ifnamep = "";
5065 
5066         if ((!Uflag) && Vflag) {
5067                 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
5068                     "%5u %5u %-11s %s\n",
5069                     pr_ap6(&tp6->tcp6ConnLocalAddress,
5070                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5071                     pr_ap6(&tp6->tcp6ConnRemAddress,
5072                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5073                     tp6->tcp6ConnEntryInfo.ce_swnd,
5074                     tp6->tcp6ConnEntryInfo.ce_snxt,
5075                     tp6->tcp6ConnEntryInfo.ce_suna,
5076                     tp6->tcp6ConnEntryInfo.ce_rwnd,
5077                     tp6->tcp6ConnEntryInfo.ce_rnxt,
5078                     tp6->tcp6ConnEntryInfo.ce_rack,
5079                     tp6->tcp6ConnEntryInfo.ce_rto,
5080                     tp6->tcp6ConnEntryInfo.ce_mss,
5081                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5082                     ifnamep);
5083         } else if ((!Uflag) && (!Vflag)) {
5084                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5085                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5086                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5087                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
5088 
5089                 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
5090                     pr_ap6(&tp6->tcp6ConnLocalAddress,
5091                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5092                     pr_ap6(&tp6->tcp6ConnRemAddress,
5093                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5094                     tp6->tcp6ConnEntryInfo.ce_swnd,
5095                     (sq >= 0) ? sq : 0,
5096                     tp6->tcp6ConnEntryInfo.ce_rwnd,
5097                     (rq >= 0) ? rq : 0,
5098                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5099                     ifnamep);
5100         } else if (Uflag && Vflag) {
5101                 int i = 0;
5102                 pid_t *pids = cpi->cpi_pids;
5103                 proc_info_t *pinfo;
5104                 do {
5105                         pinfo = get_proc_info(*pids);
5106                         (void) printf("%-33s\n%-33s %7u %08x %08x %7u %08x %08x "
5107                             "%5u %5u %-11s %-5.5s %-8.8s %6u %s\n",
5108                             pr_ap6(&tp6->tcp6ConnLocalAddress,
5109                             tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5110                             pr_ap6(&tp6->tcp6ConnRemAddress,
5111                             tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5112                             tp6->tcp6ConnEntryInfo.ce_swnd,
5113                             tp6->tcp6ConnEntryInfo.ce_snxt,
5114                             tp6->tcp6ConnEntryInfo.ce_suna,
5115                             tp6->tcp6ConnEntryInfo.ce_rwnd,
5116                             tp6->tcp6ConnEntryInfo.ce_rnxt,
5117                             tp6->tcp6ConnEntryInfo.ce_rack,
5118                             tp6->tcp6ConnEntryInfo.ce_rto,
5119                             tp6->tcp6ConnEntryInfo.ce_mss,
5120                             mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5121                             ifnamep, pinfo->pr_user, (int)*pids, pinfo->pr_psargs);
5122                         i++; pids++;
5123                 } while (i < cpi->cpi_pids_cnt);
5124         } else if (Uflag && (!Vflag)) {
5125                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5126                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5127                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5128                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
5129                 int i = 0;
5130                 pid_t *pids = cpi->cpi_pids;
5131                 proc_info_t *pinfo;
5132                 do {
5133                         pinfo = get_proc_info(*pids);
5134                         (void) printf("%-33s %-33s %-8.8s %6u %-14.14s %7d %6u %7d %6d %-11s %s\n",
5135                             pr_ap6(&tp6->tcp6ConnLocalAddress,
5136                             tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5137                             pr_ap6(&tp6->tcp6ConnRemAddress,
5138                             tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5139                             pinfo->pr_user, (int)*pids, pinfo->pr_fname,
5140                             tp6->tcp6ConnEntryInfo.ce_swnd,
5141                             (sq >= 0) ? sq : 0,
5142                             tp6->tcp6ConnEntryInfo.ce_rwnd,
5143                             (rq >= 0) ? rq : 0,
5144                             mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5145                             ifnamep);
5146                         i++; pids++;
5147                 } while (i < cpi->cpi_pids_cnt);
5148         }
5149 
5150         print_transport_label(attr);
5151 
5152         return (B_FALSE);
5153 }
5154 
5155 /* ------------------------------- UDP_REPORT------------------------------- */
5156 
5157 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
5158     conn_pid_info_t *cpi, boolean_t first,
5159     const mib2_transportMLPEntry_t *attr);
5160 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
5161     conn_pid_info_t *cpi, boolean_t first,
5162     const mib2_transportMLPEntry_t *attr);
5163 
5164 static const char udp_hdr_v4[] =
5165 "   Local Address        Remote Address      State\n"
5166 "-------------------- -------------------- ----------\n";
5167 static const char udp_hdr_v4_pid[] =
5168 "   Local Address        Remote Address      User    Pid   "
5169 "   Command       State\n"
5170 "-------------------- -------------------- -------- ------ "
5171 "-------------- ----------\n";
5172 static const char udp_hdr_v4_pid_verbose[] =
5173 "   Local Address        Remote Address      User    Pid     State    "
5174 "   Command\n"
5175 "-------------------- -------------------- -------- ------ ---------- "
5176 "----------------\n";
5177 
5178 static const char udp_hdr_v6[] =
5179 "   Local Address                     Remote Address                 "
5180 "  State      If\n"
5181 "--------------------------------- --------------------------------- "
5182 "---------- -----\n";
5183 static const char udp_hdr_v6_pid[] =
5184 "   Local Address                     Remote Address                 "
5185 "  User    Pid      Command       State      If\n"
5186 "--------------------------------- --------------------------------- "
5187 "-------- ------ -------------- ---------- -----\n";
5188 static const char udp_hdr_v6_pid_verbose[] =
5189 "   Local Address                     Remote Address                 "
5190 "  User    Pid     State      If     Command\n"
5191 "--------------------------------- --------------------------------- "
5192 "-------- ------ ---------- ----- ----------------\n";
5193 
5194 
5195 static void
5196 udp_report(const mib_item_t *item)
5197 {
5198         int                             jtemp = 0;
5199         boolean_t                       print_hdr_once_v4 = B_TRUE;
5200         boolean_t                       print_hdr_once_v6 = B_TRUE;
5201         mib2_udpEntry_t                 *ude;
5202         mib2_udp6Entry_t                *ude6;
5203         mib2_transportMLPEntry_t        **v4_attrs, **v6_attrs;
5204         mib2_transportMLPEntry_t        **v4a, **v6a;
5205         mib2_transportMLPEntry_t        *aptr;
5206         conn_pid_info_t                 *cpi;
5207 
5208         if (!protocol_selected(IPPROTO_UDP))
5209                 return;
5210 
5211         /*
5212          * Preparation pass: the kernel returns separate entries for UDP
5213          * connection table entries and Multilevel Port attributes.  We loop
5214          * through the attributes first and set up an array for each address
5215          * family.
5216          */
5217         v4_attrs = family_selected(AF_INET) && RSECflag ?
5218             gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
5219         v6_attrs = family_selected(AF_INET6) && RSECflag ?
5220             gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
5221             NULL;
5222 
5223         v4a = v4_attrs;
5224         v6a = v6_attrs;
5225         /* 'for' loop 1: */
5226         for (; item; item = item->next_item) {
5227                 if (Xflag) {
5228                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
5229                         (void) printf("Group = %d, mib_id = %d, "
5230                             "length = %d, valp = 0x%p\n",
5231                             item->group, item->mib_id,
5232                             item->length, item->valp);
5233                 }
5234                 if (!((item->group == MIB2_UDP &&
5235                     item->mib_id == MIB2_UDP_ENTRY) ||
5236                     (item->group == MIB2_UDP6 &&
5237                     item->mib_id == MIB2_UDP6_ENTRY) ||
5238                     (item->group == MIB2_UDP &&
5239                     item->mib_id == EXPER_XPORT_PROC_INFO) ||
5240                     (item->group == MIB2_UDP6 &&
5241                     item->mib_id == EXPER_XPORT_PROC_INFO)))
5242                         continue; /* 'for' loop 1 */
5243 
5244                 if (item->group == MIB2_UDP && !family_selected(AF_INET))
5245                         continue; /* 'for' loop 1 */
5246                 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
5247                         continue; /* 'for' loop 1 */
5248 
5249                 /*      xxx.xxx.xxx.xxx,pppp  sss... */
5250                 if ((!Uflag) && item->group == MIB2_UDP &&
5251                     item->mib_id == MIB2_UDP_ENTRY) {
5252                         for (ude = (mib2_udpEntry_t *)item->valp;
5253                             (char *)ude < (char *)item->valp + item->length;
5254                             /* LINTED: (note 1) */
5255                             ude = (mib2_udpEntry_t *)((char *)ude +
5256                             udpEntrySize)) {
5257                                 aptr = v4a == NULL ? NULL : *v4a++;
5258                                 print_hdr_once_v4 = udp_report_item_v4(ude,
5259                                     NULL, print_hdr_once_v4, aptr);
5260                         }
5261                 } else if ((!Uflag) && item->group == MIB2_UDP6 &&
5262                      item->mib_id == MIB2_UDP6_ENTRY) {
5263                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
5264                             (char *)ude6 < (char *)item->valp + item->length;
5265                             /* LINTED: (note 1) */
5266                             ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
5267                             udp6EntrySize)) {
5268                                 aptr = v6a == NULL ? NULL : *v6a++;
5269                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
5270                                     NULL, print_hdr_once_v6, aptr);
5271                         }
5272                 } else if ((Uflag) && item->group == MIB2_UDP &&
5273                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5274                         for (ude = (mib2_udpEntry_t *)item->valp;
5275                             (char *)ude < (char *)item->valp + item->length;
5276                             /* LINTED: (note 1) */
5277                             ude = (mib2_udpEntry_t *)((char *)cpi +
5278                             cpi->cpi_tot_size)) {
5279                                 aptr = v4a == NULL ? NULL : *v4a++;
5280                                 /* LINTED: (note 1) */
5281                                 cpi = (conn_pid_info_t *) ((char *)ude +
5282                                     udpEntrySize);
5283                                 print_hdr_once_v4 = udp_report_item_v4(ude,
5284                                     cpi, print_hdr_once_v4, aptr);
5285                         }
5286                 } else if ((Uflag) && item->group == MIB2_UDP6 &&
5287                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5288                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
5289                             (char *)ude6 < (char *)item->valp + item->length;
5290                             /* LINTED: (note 1) */
5291                             ude6 = (mib2_udp6Entry_t *)((char *)cpi +
5292                             cpi->cpi_tot_size)) {
5293                                 aptr = v6a == NULL ? NULL : *v6a++;
5294                                 /* LINTED: (note 1) */
5295                                 cpi = (conn_pid_info_t *) ((char *)ude6 +
5296                                     udp6EntrySize);
5297                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
5298                                     cpi, print_hdr_once_v6, aptr);
5299                         }
5300                 }
5301         } /* 'for' loop 1 ends */
5302         (void) fflush(stdout);
5303 
5304         if (v4_attrs != NULL)
5305                 free(v4_attrs);
5306         if (v6_attrs != NULL)
5307                 free(v6_attrs);
5308 }
5309 
5310 static boolean_t
5311 udp_report_item_v4(const mib2_udpEntry_t *ude, conn_pid_info_t *cpi,
5312     boolean_t first, const mib2_transportMLPEntry_t *attr)
5313 {
5314         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5315                         /* hostname + portname */
5316 
5317         if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
5318                 return (first); /* Nothing to print */
5319 
5320         if (first) {
5321                 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
5322 
5323                 if (Uflag)
5324                         (void) printf(Vflag ? udp_hdr_v4_pid_verbose :
5325                                 udp_hdr_v4_pid);
5326                 else
5327                         (void) printf(udp_hdr_v4);
5328 
5329                 first = B_FALSE;
5330         }
5331 
5332         (void) printf("%-20s %-20s ",
5333             pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
5334             lname, sizeof (lname)),

5335             ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
5336             pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
5337             ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5338             "");
5339         if (!Uflag) {
5340                 (void) printf("%s\n",
5341                     miudp_state(ude->udpEntryInfo.ue_state, attr));
5342         } else {
5343                 int i = 0;
5344                 pid_t *pids = cpi->cpi_pids;
5345                 proc_info_t *pinfo;
5346                 do {
5347                         pinfo = get_proc_info(*pids);
5348                         (void) printf("%-8.8s %6u ", pinfo->pr_user,
5349                             (int)*pids);
5350                         if (Vflag) {
5351                                 (void) printf("%-10.10s %s\n",
5352                                     miudp_state(ude->udpEntryInfo.ue_state,
5353                                     attr),
5354                                     pinfo->pr_psargs);
5355                         } else {
5356                                 (void) printf("%-14.14s %s\n", pinfo->pr_fname,
5357                                   miudp_state(ude->udpEntryInfo.ue_state,
5358                                   attr));
5359                         }
5360                         i++; pids++;
5361                 } while (i < cpi->cpi_pids_cnt);
5362         }
5363 
5364         print_transport_label(attr);
5365 
5366         return (first);
5367 }
5368 
5369 static boolean_t
5370 udp_report_item_v6(const mib2_udp6Entry_t *ude6, conn_pid_info_t *cpi,
5371     boolean_t first, const mib2_transportMLPEntry_t *attr)
5372 {
5373         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5374                         /* hostname + portname */
5375         char    ifname[LIFNAMSIZ + 1];
5376         const char *ifnamep;
5377 
5378         if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
5379                 return (first); /* Nothing to print */
5380 
5381         if (first) {
5382                 (void) printf("\nUDP: IPv6\n");
5383 
5384                 if (Uflag)
5385                         (void) printf(Vflag ? udp_hdr_v6_pid_verbose :
5386                                 udp_hdr_v6_pid);
5387                 else
5388                         (void) printf(udp_hdr_v6);
5389 
5390                 first = B_FALSE;
5391         }
5392 
5393         ifnamep = (ude6->udp6IfIndex != 0) ?
5394             if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
5395 
5396         (void) printf("%-33s %-33s ",
5397             pr_ap6(&ude6->udp6LocalAddress,
5398             ude6->udp6LocalPort, "udp", lname, sizeof (lname)),

5399             ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
5400             pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
5401             ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5402             "");
5403         if (!Uflag) {
5404                 (void) printf("%-10s %s\n",
5405                     miudp_state(ude6->udp6EntryInfo.ue_state, attr),
5406                     ifnamep == NULL ? "" : ifnamep);
5407         } else {
5408                 int i = 0;
5409                 pid_t *pids = cpi->cpi_pids;
5410                 proc_info_t *pinfo;
5411                 do {
5412                         pinfo = get_proc_info(*pids);
5413                         (void) printf("%-8.8s %6u ", pinfo->pr_user,
5414                             (int)*pids);
5415                         if (Vflag) {
5416                                 (void) printf("%-10.10s %-5.5s %s\n",
5417                                     miudp_state(ude6->udp6EntryInfo.ue_state,
5418                                     attr),
5419                                     ifnamep == NULL ? "" : ifnamep,
5420                                     pinfo->pr_psargs);
5421                         } else {
5422                                 (void) printf("%-14.14s %-10.10s %s\n",
5423                                     pinfo->pr_fname,
5424                                     miudp_state(ude6->udp6EntryInfo.ue_state,
5425                                     attr),
5426                                     ifnamep == NULL ? "" : ifnamep);
5427                         }
5428                         i++; pids++;
5429                 } while (i < cpi->cpi_pids_cnt);
5430         }
5431 
5432         print_transport_label(attr);
5433 
5434         return (first);
5435 }
5436 
5437 /* ------------------------------ SCTP_REPORT------------------------------- */
5438 
5439 static const char sctp_hdr[] =
5440 "\nSCTP:";
5441 static const char sctp_hdr_normal[] =
5442 "        Local Address                   Remote Address          "
5443 "Swind  Send-Q Rwind  Recv-Q StrsI/O  State\n"
5444 "------------------------------- ------------------------------- "
5445 "------ ------ ------ ------ ------- -----------";
5446 static const char sctp_hdr_pid[] =
5447 "        Local Address                   Remote Address          "
5448 "Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid      Command      State\n"
5449 "------------------------------- ------------------------------- ------ "
5450 "------ ------ ------ ------- -------- ------ -------------- -----------";
5451 static const char sctp_hdr_pid_verbose[] =
5452 "        Local Address                   Remote Address          "
5453 "Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid    State         Command\n"
5454 "------------------------------- ------------------------------- ------ "
5455 "------ ------ ------ ------- -------- ------ ----------- --------------";
5456 
5457 static const char *
5458 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
5459 {
5460         static char sctpsbuf[50];
5461         const char *cp;
5462 
5463         switch (state) {
5464         case MIB2_SCTP_closed:
5465                 cp = "CLOSED";
5466                 break;
5467         case MIB2_SCTP_cookieWait:
5468                 cp = "COOKIE_WAIT";
5469                 break;
5470         case MIB2_SCTP_cookieEchoed:
5471                 cp = "COOKIE_ECHOED";
5472                 break;
5473         case MIB2_SCTP_established:
5474                 cp = "ESTABLISHED";
5475                 break;


5602                 } else {
5603                         (void) pr_addr(v4addr, name, namelen);
5604                 }
5605                 break;
5606 
5607         case MIB2_SCTP_ADDR_V6:
5608                 /* v6 */
5609                 if (port > 0) {
5610                         (void) pr_ap6(addr, port, "sctp", name, namelen);
5611                 } else {
5612                         (void) pr_addr6(addr, name, namelen);
5613                 }
5614                 break;
5615 
5616         default:
5617                 (void) snprintf(name, namelen, "<unknown addr type>");
5618                 break;
5619         }
5620 }
5621 
5622 static boolean_t
5623 sctp_conn_report_item(const mib_item_t *head, conn_pid_info_t * cpi,
5624     boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp,
5625     const mib2_transportMLPEntry_t *attr)
5626 {
5627         char            lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5628         char            fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5629         const mib2_sctpConnRemoteEntry_t        *sre = NULL;
5630         const mib2_sctpConnLocalEntry_t *sle = NULL;
5631         const mib_item_t *local = head;
5632         const mib_item_t *remote = head;
5633         uint32_t        id = sp->sctpAssocId;
5634         boolean_t       printfirst = B_TRUE;
5635 
5636         if (print_sctp_hdr == B_TRUE) {
5637                 (void) puts(sctp_hdr);
5638                 if (Uflag)
5639                         (void) puts(Vflag? sctp_hdr_pid_verbose: sctp_hdr_pid);
5640                 else
5641                         (void) puts(sctp_hdr_normal);
5642 
5643                 print_sctp_hdr = B_FALSE;
5644         }
5645 
5646         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5647             &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5648         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5649             &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5650 
5651         if (Uflag) {
5652                 int i = 0;
5653                 pid_t *pids = cpi->cpi_pids;
5654                 proc_info_t *pinfo;
5655                 do {
5656                         pinfo = get_proc_info(*pids);
5657                         (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %-8.8s %6u ",
5658                             lname, fname,
5659                             sp->sctpConnEntryInfo.ce_swnd,
5660                             sp->sctpConnEntryInfo.ce_sendq,
5661                             sp->sctpConnEntryInfo.ce_rwnd,
5662                             sp->sctpConnEntryInfo.ce_recvq,
5663                             sp->sctpAssocInStreams,
5664                             sp->sctpAssocOutStreams,
5665                             pinfo->pr_user, (int)*pids);
5666                         if (Vflag) {
5667                                 (void) printf("%-11.11s %s\n",
5668                                     nssctp_state(sp->sctpAssocState, attr),
5669                                     pinfo->pr_psargs);
5670                         } else {
5671                                 (void) printf("%-14.14s %s\n",
5672                                     pinfo->pr_fname,
5673                                     nssctp_state(sp->sctpAssocState, attr));
5674                         }
5675                         i++; pids++;
5676                 } while (i < cpi->cpi_pids_cnt);
5677 
5678         } else {
5679 
5680                 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5681                     lname, fname,
5682                     sp->sctpConnEntryInfo.ce_swnd,
5683                     sp->sctpConnEntryInfo.ce_sendq,
5684                     sp->sctpConnEntryInfo.ce_rwnd,
5685                     sp->sctpConnEntryInfo.ce_recvq,
5686                     sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5687                     nssctp_state(sp->sctpAssocState, attr));
5688         }
5689 
5690         print_transport_label(attr);
5691 
5692         if (!Vflag) {
5693                 return (print_sctp_hdr);
5694         }
5695 
5696         /* Print remote addresses/local addresses on following lines */
5697         while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5698                 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5699                     &sp->sctpAssocRemPrimAddr)) {
5700                         if (printfirst == B_TRUE) {
5701                                 (void) fputs("\t<Remote: ", stdout);
5702                                 printfirst = B_FALSE;
5703                         } else {
5704                                 (void) fputs(", ", stdout);
5705                         }
5706                         sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5707                             sizeof (fname), &sre->sctpAssocRemAddr, -1);
5708                         if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5709                                 (void) fputs(fname, stdout);
5710                         } else {
5711                                 (void) printf("(%s)", fname);
5712                         }
5713                 }


5716                 (void) puts(">");
5717                 printfirst = B_TRUE;
5718         }
5719         while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5720                 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5721                     &sp->sctpAssocLocPrimAddr)) {
5722                         if (printfirst == B_TRUE) {
5723                                 (void) fputs("\t<Local: ", stdout);
5724                                 printfirst = B_FALSE;
5725                         } else {
5726                                 (void) fputs(", ", stdout);
5727                         }
5728                         sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5729                             sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5730                         (void) fputs(lname, stdout);
5731                 }
5732         }
5733         if (printfirst == B_FALSE) {
5734                 (void) puts(">");
5735         }
5736 
5737         return (print_sctp_hdr);
5738 }
5739 
5740 static void
5741 sctp_report(const mib_item_t *item)
5742 {
5743         const mib_item_t                *head;
5744         const mib2_sctpConnEntry_t      *sp;
5745         boolean_t                       print_sctp_hdr_once = B_TRUE;
5746         mib2_transportMLPEntry_t        **attrs, **aptr;
5747         mib2_transportMLPEntry_t        *attr;
5748         conn_pid_info_t                 *cpi;
5749 
5750         /*
5751          * Preparation pass: the kernel returns separate entries for SCTP
5752          * connection table entries and Multilevel Port attributes.  We loop
5753          * through the attributes first and set up an array for each address
5754          * family.
5755          */
5756         attrs = RSECflag ?
5757             gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5758             NULL;
5759 
5760         aptr = attrs;
5761         head = item;
5762         for (; item != NULL; item = item->next_item) {
5763 
5764                 if (!((item->group == MIB2_SCTP &&
5765                     item->mib_id == MIB2_SCTP_CONN) ||
5766                     (item->group == MIB2_SCTP &&
5767                     item->mib_id == EXPER_XPORT_PROC_INFO)))
5768                         continue;
5769 
5770                 if ((!Uflag) && item->group == MIB2_SCTP
5771                     && item->mib_id == MIB2_SCTP_CONN) {
5772                         for (sp = item->valp;
5773                             (char *)sp < (char *)item->valp + item->length;
5774                             /* LINTED: (note 1) */
5775                             sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
5776                                 if (!(Aflag ||
5777                                   sp->sctpAssocState >= MIB2_SCTP_established))
5778                                         continue;
5779                                 attr = aptr == NULL ? NULL : *aptr++;
5780                                 print_sctp_hdr_once = sctp_conn_report_item(head, NULL,
5781                                                         print_sctp_hdr_once, sp,
5782                                                         attr);
5783                         }
5784                 } else if ((Uflag) && item->group == MIB2_SCTP &&
5785                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5786                         for (sp = (mib2_sctpConnEntry_t *)item->valp;
5787                             (char *)sp < (char *)item->valp + item->length;
5788                             /* LINTED: (note 1) */
5789                             sp = (mib2_sctpConnEntry_t *)((char *)cpi +
5790                             cpi->cpi_tot_size)) {
5791                                 /* LINTED: (note 1) */
5792                                 cpi = (conn_pid_info_t *) ((char *)sp +
5793                                     sctpEntrySize);
5794                                 if (!(Aflag ||
5795                                   sp->sctpAssocState >= MIB2_SCTP_established))
5796                                         continue;
5797                                 attr = aptr == NULL ? NULL : *aptr++;
5798                                 print_sctp_hdr_once =
5799                                     sctp_conn_report_item(head, cpi,
5800                                         print_sctp_hdr_once, sp, attr);
5801                         }
5802                 }
5803         }
5804         if (attrs != NULL)
5805                 free(attrs);
5806 }
5807 
5808 static char *
5809 plural(int n)
5810 {
5811         return (n != 1 ? "s" : "");
5812 }
5813 
5814 static char *
5815 pluraly(int n)
5816 {
5817         return (n != 1 ? "ies" : "y");
5818 }
5819 
5820 static char *


6768         }
6769         return (B_FALSE);
6770 }
6771 
6772 /*
6773  * Convert the interface index to a string using the buffer `ifname', which
6774  * must be at least LIFNAMSIZ bytes.  We first try to map it to name.  If that
6775  * fails (e.g., because we're inside a zone and it does not have access to
6776  * interface for the index in question), just return "if#<num>".
6777  */
6778 static char *
6779 ifindex2str(uint_t ifindex, char *ifname)
6780 {
6781         if (if_indextoname(ifindex, ifname) == NULL)
6782                 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6783 
6784         return (ifname);
6785 }
6786 
6787 /*
6788  * Gets proc info in (proc_info_t) given pid. It doesn't return NULL.
6789  */
6790 proc_info_t *
6791 get_proc_info(pid_t pid)
6792 {
6793         static pid_t saved_pid = 0;
6794         static proc_info_t saved_proc_info;
6795         static proc_info_t unknown_proc_info = {"<unknown>","",""};
6796         static psinfo_t pinfo;
6797         char path[128];
6798         int fd;
6799 
6800         /* hardcode pid = 0 */
6801         if (pid == 0) {
6802                 saved_proc_info.pr_user = "root";
6803                 saved_proc_info.pr_fname = "sched";
6804                 saved_proc_info.pr_psargs = "sched";
6805                 saved_pid = 0;
6806                 return &saved_proc_info;
6807         }
6808 
6809         if (pid == saved_pid)
6810                 return &saved_proc_info;
6811         if ((snprintf(path, 128, "/proc/%u/psinfo",(int)pid) > 0) &&
6812             ((fd = open(path, O_RDONLY)) != -1)) {
6813                 if (read(fd, &pinfo, sizeof(pinfo)) == sizeof(pinfo)){
6814                         saved_proc_info.pr_user = get_username(pinfo.pr_uid);
6815                         saved_proc_info.pr_fname = pinfo.pr_fname;
6816                         saved_proc_info.pr_psargs = pinfo.pr_psargs;
6817                         saved_pid = pid;
6818                         (void) close(fd);
6819                         return &saved_proc_info;
6820                 } else {
6821                         (void) close(fd);
6822                 }
6823         }
6824 
6825         return (&unknown_proc_info);
6826 }
6827 
6828 /*
6829  * Gets username given uid. It doesn't return NULL.
6830  */
6831 static char *
6832 get_username(uid_t u)
6833 {
6834         static uid_t saved_uid = UINT_MAX;
6835         static char  saved_username[128];
6836         struct passwd *pw = NULL;
6837         if (u == UINT_MAX)
6838                 return "<unknown>";
6839         if (u == saved_uid && saved_username[0] != '\0')
6840                 return  (saved_username);
6841         setpwent();
6842         if ((pw = getpwuid(u)) != NULL)
6843                 (void) strlcpy(saved_username, pw->pw_name, 128);
6844         else
6845                 (void) snprintf(saved_username, 128, "%u", u);
6846         saved_uid = u;
6847         return saved_username;
6848 }
6849 
6850 /*
6851  * print the usage line
6852  */
6853 static void
6854 usage(char *cmdname)
6855 {
6856         (void) fprintf(stderr, "usage: %s [-anuv] [-f address_family] "
6857             "[-T d|u]\n", cmdname);
6858         (void) fprintf(stderr, "       %s [-n] [-f address_family] "
6859             "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6860             cmdname);
6861         (void) fprintf(stderr, "       %s -m [-v] [-T d|u] "
6862             "[interval [count]]\n", cmdname);
6863         (void) fprintf(stderr, "       %s -i [-I interface] [-an] "
6864             "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6865         (void) fprintf(stderr, "       %s -r [-anv] "
6866             "[-f address_family|filter] [-T d|u]\n", cmdname);
6867         (void) fprintf(stderr, "       %s -M [-ns] [-f address_family] "
6868             "[-T d|u]\n", cmdname);
6869         (void) fprintf(stderr, "       %s -D [-I interface] "
6870             "[-f address_family] [-T d|u]\n", cmdname);
6871         exit(EXIT_FAILURE);
6872 }
6873 
6874 /*
6875  * fatal: print error message to stderr and
6876  * call exit(errcode)
6877  */
6878 /*PRINTFLIKE2*/
6879 static void
6880 fatal(int errcode, char *format, ...)
6881 {
6882         va_list argp;
6883 
6884         if (format == NULL)
6885                 return;
6886 
6887         va_start(argp, format);
6888         (void) vfprintf(stderr, format, argp);
6889         va_end(argp);
6890 
6891         exit(errcode);
6892 }
6893 
6894 
6895 /* -------------------UNIX Domain Sockets Report---------------------------- */
6896 
6897 
6898 #define NO_ADDR         "                                       "
6899 #define SO_PAIR         " (socketpair)                          "
6900 
6901 static char             *typetoname(t_scalar_t);
6902 static boolean_t        uds_report_item(struct sockinfo *, boolean_t);
6903 
6904 
6905 static char uds_hdr[] = "\nActive UNIX domain sockets\n";
6906 
6907 static char uds_hdr_normal[] =
6908 " Type       Local Adress                           "
6909 " Remote Address\n"
6910 "---------- --------------------------------------- "
6911 "---------------------------------------\n";
6912 
6913 static char uds_hdr_pid[] =
6914 " Type       User     Pid     Command       "
6915 " Local Address                         "
6916 " Remote Address\n"
6917 "---------- -------- ------ -------------- "
6918 "--------------------------------------- "
6919 "---------------------------------------\n";
6920 static char uds_hdr_pid_verbose[] =
6921 " Type       User     Pid    Local Address                          "
6922 " Remote Address                          Command\n"
6923 "---------- -------- ------ --------------------------------------- "
6924 "--------------------------------------- --------------\n";
6925 
6926 /*
6927  * Print a summary of connections related to unix protocols.
6928  */
6929 static void
6930 uds_report(kstat_ctl_t  *kc)
6931 {
6932         int             i;
6933         kstat_t         *ksp;
6934         struct sockinfo *psi;
6935         boolean_t       print_uds_hdr_once = B_TRUE;
6936 
6937         if (kc == NULL) {
6938                 fail(0, "uds_report: No kstat");
6939                 exit(3);
6940         }
6941 
6942         if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) ==
6943             (kstat_t *)NULL) {
6944                 fail(0, "kstat_data_lookup failed\n");
6945         }
6946 
6947         if (kstat_read(kc, ksp, NULL) == -1) {
6948                 fail(0, "kstat_read failed for sock_unix_list\n");
6949         }
6950 
6951         if (ksp->ks_ndata == 0) {
6952                 return;                 /* no AF_UNIX sockets found     */
6953         }
6954 
6955         /*
6956          * Having ks_data set with ks_data == NULL shouldn't happen;
6957          * If it does, the sockfs kstat is seriously broken.
6958          */
6959         if ((psi = ksp->ks_data) == NULL) {
6960                 fail(0, "uds_report: no kstat data\n");
6961         }
6962 
6963         for (i = 0; i < ksp->ks_ndata; i++) {
6964 
6965                 print_uds_hdr_once = uds_report_item(psi, print_uds_hdr_once);
6966 
6967                 /* if si_size didn't get filled in, then we're done     */
6968                 if (psi->si_size == 0 ||
6969                     !IS_P2ALIGNED(psi->si_size, sizeof (psi))) {
6970                         break;
6971                 }
6972 
6973                 /* point to the next sockinfo in the array */
6974                 /* LINTED: (note 1) */
6975                 psi = (struct sockinfo *)(((char *)psi) + psi->si_size);
6976         }
6977 }
6978 
6979 static boolean_t
6980 uds_report_item(struct sockinfo *psi, boolean_t first)
6981 {
6982         int             i = 0;
6983         pid_t           *pids;
6984         proc_info_t     *pinfo;
6985         char            *laddr, *raddr;
6986 
6987         if(first) {
6988                 (void) printf("%s", uds_hdr);
6989                 if (Uflag)
6990                         (void) printf("%s", Vflag?uds_hdr_pid_verbose:
6991                             uds_hdr_pid);
6992                 else
6993                         (void) printf("%s", uds_hdr_normal);
6994 
6995                 first = B_FALSE;
6996         }
6997 
6998         pids = psi->si_pids;
6999 
7000         do {
7001                 pinfo = get_proc_info(*pids);
7002                 raddr = laddr = NO_ADDR;
7003 
7004                 /* Try to fill laddr */
7005                 if ((psi->si_state & SS_ISBOUND) &&
7006                     strlen(psi->si_laddr_sun_path) != 0 &&
7007                     psi->si_laddr_soa_len != 0) {
7008                         if (psi->si_faddr_noxlate) {
7009                                 laddr = SO_PAIR;
7010                         } else {
7011                                 if (psi->si_laddr_soa_len >
7012                                     sizeof (psi->si_laddr_family))
7013                                         laddr = psi->si_laddr_sun_path;
7014                         }
7015                 }
7016 
7017                 /* Try to fill raddr */
7018                 if ((psi->si_state & SS_ISCONNECTED) &&
7019                     strlen(psi->si_faddr_sun_path) != 0 &&
7020                     psi->si_faddr_soa_len != 0) {
7021 
7022                         if (psi->si_faddr_noxlate) {
7023                                 raddr = SO_PAIR;
7024                         } else {
7025                                 if (psi->si_faddr_soa_len >
7026                                     sizeof (psi->si_faddr_family))
7027                                         raddr = psi->si_faddr_sun_path;
7028                         }
7029                 }
7030 
7031                 if (Uflag && Vflag) {
7032                         (void) printf("%-10.10s %-8.8s %6u "
7033                                 "%-39.39s %-39.39s %s\n",
7034                                 typetoname(psi->si_serv_type), pinfo->pr_user,
7035                                 (int)*pids, laddr, raddr, pinfo->pr_psargs);
7036                 } else if (Uflag && (!Vflag)) {
7037                         (void) printf("%-10.10s %-8.8s %6u %-14.14s"
7038                                 "%-39.39s %-39.39s\n",
7039                                 typetoname(psi->si_serv_type), pinfo->pr_user,
7040                                 (int)*pids, pinfo->pr_fname, laddr, raddr);
7041                 } else {
7042                         (void) printf("%-10.10s %s %s\n",
7043                                 typetoname(psi->si_serv_type), laddr, raddr);
7044                 }
7045 
7046                 i++; pids++;
7047         } while (i < psi->si_pn_cnt);
7048 
7049         return (first);
7050 }
7051 
7052 static char *
7053 typetoname(t_scalar_t type)
7054 {
7055         switch (type) {
7056         case T_CLTS:
7057                 return ("dgram");
7058 
7059         case T_COTS:
7060                 return ("stream");
7061 
7062         case T_COTS_ORD:
7063                 return ("stream-ord");
7064 
7065         default:
7066                 return ("");
7067         }
7068 }