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(uint32_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_node_list_hdr_t *, boolean_t first,
4799     const mib2_transportMLPEntry_t *);
4800 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4801     conn_pid_node_list_hdr_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_node_list_hdr_t        *cph;
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 *)cph +
4889                             cph->cph_tot_size)) {
4890                                 aptr = v4a == NULL ? NULL : *v4a++;
4891                                 /* LINTED: (note 1) */
4892                                 cph = (conn_pid_node_list_hdr_t *)
4893                                         ((char *)tp + tcpConnEntrySize);
4894                                 print_hdr_once_v4 = tcp_report_item_v4(tp,
4895                                     cph, 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 *)cph +
4903                             cph->cph_tot_size)) {
4904                                 aptr = v6a == NULL ? NULL : *v6a++;
4905                                 /* LINTED: (note 1) */
4906                                 cph = (conn_pid_node_list_hdr_t *)
4907                                         ((char *)tp6 + tcp6ConnEntrySize);
4908                                 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4909                                     cph, 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,
4924     conn_pid_node_list_hdr_t * cph, boolean_t first,
4925     const mib2_transportMLPEntry_t *attr)
4926 {
4927         /*
4928          * lname and fname below are for the hostname as well as the portname
4929          * There is no limit on portname length so we assume MAXHOSTNAMELEN
4930          * as the limit
4931          */
4932         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4933         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4934 
4935 
4936         if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4937                 return (first); /* Nothing to print */
4938 
4939         if (first) {
4940                 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4941                 if (Uflag)
4942                         (void) printf(Vflag ? tcp_hdr_v4_pid_verbose :
4943                                 tcp_hdr_v4_pid);
4944                 else
4945                         (void) printf(Vflag ? tcp_hdr_v4_verbose :
4946                                 tcp_hdr_v4_normal);
4947         }
4948 
4949         if ((!Uflag) && Vflag) {
4950                 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4951                     "%5u %5u %s\n",
4952                     pr_ap(tp->tcpConnLocalAddress,
4953                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4954                     pr_ap(tp->tcpConnRemAddress,
4955                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4956                     tp->tcpConnEntryInfo.ce_swnd,
4957                     tp->tcpConnEntryInfo.ce_snxt,
4958                     tp->tcpConnEntryInfo.ce_suna,
4959                     tp->tcpConnEntryInfo.ce_rwnd,
4960                     tp->tcpConnEntryInfo.ce_rnxt,
4961                     tp->tcpConnEntryInfo.ce_rack,
4962                     tp->tcpConnEntryInfo.ce_rto,
4963                     tp->tcpConnEntryInfo.ce_mss,
4964                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4965         } else if ((!Uflag) && (!Vflag)) {
4966                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4967                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
4968                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4969                     (int)tp->tcpConnEntryInfo.ce_rack;
4970 
4971                 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
4972                     pr_ap(tp->tcpConnLocalAddress,
4973                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4974                     pr_ap(tp->tcpConnRemAddress,
4975                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4976                     tp->tcpConnEntryInfo.ce_swnd,
4977                     (sq >= 0) ? sq : 0,
4978                     tp->tcpConnEntryInfo.ce_rwnd,
4979                     (rq >= 0) ? rq : 0,
4980                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4981         } else if (Uflag && Vflag) {
4982                 int i = 0;
4983                 conn_pid_node_t *cpn = cph->cph_cpns;
4984                 proc_info_t *pinfo;
4985 
4986                 do {
4987                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
4988                         pinfo = get_proc_info(cpn->cpn_pid);
4989 
4990                         (void) printf("%-20s\n%-20s %7u %08x %08x %7u %08x %08x "
4991                             "%5u %5u %-11s %-8.8s %6u %s\n",
4992                             pr_ap(tp->tcpConnLocalAddress,
4993                             tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4994                             pr_ap(tp->tcpConnRemAddress,
4995                             tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4996                             tp->tcpConnEntryInfo.ce_swnd,
4997                             tp->tcpConnEntryInfo.ce_snxt,
4998                             tp->tcpConnEntryInfo.ce_suna,
4999                             tp->tcpConnEntryInfo.ce_rwnd,
5000                             tp->tcpConnEntryInfo.ce_rnxt,
5001                             tp->tcpConnEntryInfo.ce_rack,
5002                             tp->tcpConnEntryInfo.ce_rto,
5003                             tp->tcpConnEntryInfo.ce_mss,
5004                             mitcp_state(tp->tcpConnEntryInfo.ce_state, attr),
5005                             pinfo->pr_user, pid, pinfo->pr_psargs);
5006                         i++; cpn++;
5007                 } while (i < cph->cph_pn_cnt);
5008         } else if (Uflag && (!Vflag)) {
5009                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
5010                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
5011                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
5012                    (int)tp->tcpConnEntryInfo.ce_rack;
5013                 int i = 0;
5014                 conn_pid_node_t *cpn = cph->cph_cpns;
5015                 proc_info_t *pinfo;
5016 
5017                 do {
5018                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5019                         pinfo = get_proc_info(cpn->cpn_pid);
5020 
5021                         (void) printf("%-20s %-20s %-8.8s %6u %-13.13s %7u %6d %7u %6d %s\n",
5022                             pr_ap(tp->tcpConnLocalAddress,
5023                             tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
5024                             pr_ap(tp->tcpConnRemAddress,
5025                             tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
5026                             pinfo->pr_user, pid, pinfo->pr_fname,
5027                             tp->tcpConnEntryInfo.ce_swnd,
5028                             (sq >= 0) ? sq : 0,
5029                             tp->tcpConnEntryInfo.ce_rwnd,
5030                             (rq >= 0) ? rq : 0,
5031                             mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
5032 
5033                         i++; cpn++;
5034                 } while (i < cph->cph_pn_cnt);
5035         }
5036 
5037         print_transport_label(attr);
5038 
5039         return (B_FALSE);
5040 }
5041 
5042 static boolean_t
5043 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6,
5044     conn_pid_node_list_hdr_t *cph, boolean_t first,
5045     const mib2_transportMLPEntry_t *attr)
5046 {
5047         /*
5048          * lname and fname below are for the hostname as well as the portname
5049          * There is no limit on portname length so we assume MAXHOSTNAMELEN
5050          * as the limit
5051          */
5052         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5053         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5054         char    ifname[LIFNAMSIZ + 1];
5055         char    *ifnamep;
5056 
5057         if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
5058                 return (first); /* Nothing to print */
5059 
5060         if (first) {
5061                 (void) printf(tcp_hdr_v6);
5062                 if (Uflag)
5063                         (void) printf(Vflag ? tcp_hdr_v6_pid_verbose :
5064                                 tcp_hdr_v6_pid);
5065                 else
5066                         (void) printf(Vflag ? tcp_hdr_v6_verbose :
5067                                 tcp_hdr_v6_normal);
5068         }
5069 
5070         ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
5071             if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
5072         if (ifnamep == NULL)
5073                 ifnamep = "";
5074 
5075         if ((!Uflag) && Vflag) {
5076                 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
5077                     "%5u %5u %-11s %s\n",
5078                     pr_ap6(&tp6->tcp6ConnLocalAddress,
5079                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5080                     pr_ap6(&tp6->tcp6ConnRemAddress,
5081                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5082                     tp6->tcp6ConnEntryInfo.ce_swnd,
5083                     tp6->tcp6ConnEntryInfo.ce_snxt,
5084                     tp6->tcp6ConnEntryInfo.ce_suna,
5085                     tp6->tcp6ConnEntryInfo.ce_rwnd,
5086                     tp6->tcp6ConnEntryInfo.ce_rnxt,
5087                     tp6->tcp6ConnEntryInfo.ce_rack,
5088                     tp6->tcp6ConnEntryInfo.ce_rto,
5089                     tp6->tcp6ConnEntryInfo.ce_mss,
5090                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5091                     ifnamep);
5092         } else if ((!Uflag) && (!Vflag)) {
5093                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5094                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5095                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5096                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
5097 
5098                 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
5099                     pr_ap6(&tp6->tcp6ConnLocalAddress,
5100                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5101                     pr_ap6(&tp6->tcp6ConnRemAddress,
5102                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5103                     tp6->tcp6ConnEntryInfo.ce_swnd,
5104                     (sq >= 0) ? sq : 0,
5105                     tp6->tcp6ConnEntryInfo.ce_rwnd,
5106                     (rq >= 0) ? rq : 0,
5107                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5108                     ifnamep);
5109         } else if (Uflag && Vflag) {
5110                 int i = 0;
5111                 conn_pid_node_t *cpn = cph->cph_cpns;
5112                 proc_info_t *pinfo;
5113 
5114                 do {
5115                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5116                         pinfo = get_proc_info(cpn->cpn_pid);
5117 
5118                         (void) printf("%-33s\n%-33s %7u %08x %08x %7u %08x %08x "
5119                             "%5u %5u %-11s %-5.5s %-8.8s %6u %s\n",
5120                             pr_ap6(&tp6->tcp6ConnLocalAddress,
5121                             tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5122                             pr_ap6(&tp6->tcp6ConnRemAddress,
5123                             tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5124                             tp6->tcp6ConnEntryInfo.ce_swnd,
5125                             tp6->tcp6ConnEntryInfo.ce_snxt,
5126                             tp6->tcp6ConnEntryInfo.ce_suna,
5127                             tp6->tcp6ConnEntryInfo.ce_rwnd,
5128                             tp6->tcp6ConnEntryInfo.ce_rnxt,
5129                             tp6->tcp6ConnEntryInfo.ce_rack,
5130                             tp6->tcp6ConnEntryInfo.ce_rto,
5131                             tp6->tcp6ConnEntryInfo.ce_mss,
5132                             mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5133                             ifnamep, pinfo->pr_user, pid, pinfo->pr_psargs);
5134                         i++; cpn++;
5135                 } while (i < cph->cph_pn_cnt);
5136         } else if (Uflag && (!Vflag)) {
5137                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
5138                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
5139                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
5140                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
5141                 int i = 0;
5142                 conn_pid_node_t *cpn = cph->cph_cpns;
5143                 proc_info_t *pinfo;
5144 
5145                 do {
5146                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5147                         pinfo = get_proc_info(cpn->cpn_pid);
5148 
5149                         (void) printf("%-33s %-33s %-8.8s %6u %-14.14s %7d %6u %7d %6d %-11s %s\n",
5150                             pr_ap6(&tp6->tcp6ConnLocalAddress,
5151                             tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
5152                             pr_ap6(&tp6->tcp6ConnRemAddress,
5153                             tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
5154                             pinfo->pr_user, pid, pinfo->pr_fname,
5155                             tp6->tcp6ConnEntryInfo.ce_swnd,
5156                             (sq >= 0) ? sq : 0,
5157                             tp6->tcp6ConnEntryInfo.ce_rwnd,
5158                             (rq >= 0) ? rq : 0,
5159                             mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
5160                             ifnamep);
5161 
5162                         i++; cpn++;
5163                 } while (i < cph->cph_pn_cnt);
5164         }
5165 
5166         print_transport_label(attr);
5167 
5168         return (B_FALSE);
5169 }
5170 
5171 /* ------------------------------- UDP_REPORT------------------------------- */
5172 
5173 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
5174     conn_pid_node_list_hdr_t *cph, boolean_t first,
5175     const mib2_transportMLPEntry_t *attr);
5176 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
5177     conn_pid_node_list_hdr_t *cph, boolean_t first,
5178     const mib2_transportMLPEntry_t *attr);
5179 
5180 static const char udp_hdr_v4[] =
5181 "   Local Address        Remote Address      State\n"
5182 "-------------------- -------------------- ----------\n";
5183 static const char udp_hdr_v4_pid[] =
5184 "   Local Address        Remote Address      User    Pid   "
5185 "   Command       State\n"
5186 "-------------------- -------------------- -------- ------ "
5187 "-------------- ----------\n";
5188 static const char udp_hdr_v4_pid_verbose[] =
5189 "   Local Address        Remote Address      User    Pid     State    "
5190 "   Command\n"
5191 "-------------------- -------------------- -------- ------ ---------- "
5192 "----------------\n";
5193 
5194 static const char udp_hdr_v6[] =
5195 "   Local Address                     Remote Address                 "
5196 "  State      If\n"
5197 "--------------------------------- --------------------------------- "
5198 "---------- -----\n";
5199 static const char udp_hdr_v6_pid[] =
5200 "   Local Address                     Remote Address                 "
5201 "  User    Pid      Command       State      If\n"
5202 "--------------------------------- --------------------------------- "
5203 "-------- ------ -------------- ---------- -----\n";
5204 static const char udp_hdr_v6_pid_verbose[] =
5205 "   Local Address                     Remote Address                 "
5206 "  User    Pid     State      If     Command\n"
5207 "--------------------------------- --------------------------------- "
5208 "-------- ------ ---------- ----- ----------------\n";
5209 
5210 
5211 static void
5212 udp_report(const mib_item_t *item)
5213 {
5214         int                             jtemp = 0;
5215         boolean_t                       print_hdr_once_v4 = B_TRUE;
5216         boolean_t                       print_hdr_once_v6 = B_TRUE;
5217         mib2_udpEntry_t                 *ude;
5218         mib2_udp6Entry_t                *ude6;
5219         mib2_transportMLPEntry_t        **v4_attrs, **v6_attrs;
5220         mib2_transportMLPEntry_t        **v4a, **v6a;
5221         mib2_transportMLPEntry_t        *aptr;
5222         conn_pid_node_list_hdr_t        *cph;
5223 
5224         if (!protocol_selected(IPPROTO_UDP))
5225                 return;
5226 
5227         /*
5228          * Preparation pass: the kernel returns separate entries for UDP
5229          * connection table entries and Multilevel Port attributes.  We loop
5230          * through the attributes first and set up an array for each address
5231          * family.
5232          */
5233         v4_attrs = family_selected(AF_INET) && RSECflag ?
5234             gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
5235         v6_attrs = family_selected(AF_INET6) && RSECflag ?
5236             gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
5237             NULL;
5238 
5239         v4a = v4_attrs;
5240         v6a = v6_attrs;
5241         /* 'for' loop 1: */
5242         for (; item; item = item->next_item) {
5243                 if (Xflag) {
5244                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
5245                         (void) printf("Group = %d, mib_id = %d, "
5246                             "length = %d, valp = 0x%p\n",
5247                             item->group, item->mib_id,
5248                             item->length, item->valp);
5249                 }
5250                 if (!((item->group == MIB2_UDP &&
5251                     item->mib_id == MIB2_UDP_ENTRY) ||
5252                     (item->group == MIB2_UDP6 &&
5253                     item->mib_id == MIB2_UDP6_ENTRY) ||
5254                     (item->group == MIB2_UDP &&
5255                     item->mib_id == EXPER_XPORT_PROC_INFO) ||
5256                     (item->group == MIB2_UDP6 &&
5257                     item->mib_id == EXPER_XPORT_PROC_INFO)))
5258                         continue; /* 'for' loop 1 */
5259 
5260                 if (item->group == MIB2_UDP && !family_selected(AF_INET))
5261                         continue; /* 'for' loop 1 */
5262                 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
5263                         continue; /* 'for' loop 1 */
5264 
5265                 /*      xxx.xxx.xxx.xxx,pppp  sss... */
5266                 if ((!Uflag) && item->group == MIB2_UDP &&
5267                     item->mib_id == MIB2_UDP_ENTRY) {
5268                         for (ude = (mib2_udpEntry_t *)item->valp;
5269                             (char *)ude < (char *)item->valp + item->length;
5270                             /* LINTED: (note 1) */
5271                             ude = (mib2_udpEntry_t *)((char *)ude +
5272                             udpEntrySize)) {
5273                                 aptr = v4a == NULL ? NULL : *v4a++;
5274                                 print_hdr_once_v4 = udp_report_item_v4(ude,
5275                                     NULL, print_hdr_once_v4, aptr);
5276                         }
5277                 } else if ((!Uflag) && item->group == MIB2_UDP6 &&
5278                      item->mib_id == MIB2_UDP6_ENTRY) {
5279                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
5280                             (char *)ude6 < (char *)item->valp + item->length;
5281                             /* LINTED: (note 1) */
5282                             ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
5283                             udp6EntrySize)) {
5284                                 aptr = v6a == NULL ? NULL : *v6a++;
5285                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
5286                                     NULL, print_hdr_once_v6, aptr);
5287                         }
5288                 } else if ((Uflag) && item->group == MIB2_UDP &&
5289                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5290                         for (ude = (mib2_udpEntry_t *)item->valp;
5291                             (char *)ude < (char *)item->valp + item->length;
5292                             /* LINTED: (note 1) */
5293                             ude = (mib2_udpEntry_t *)((char *)cph +
5294                             cph->cph_tot_size)) {
5295                                 aptr = v4a == NULL ? NULL : *v4a++;
5296                                 /* LINTED: (note 1) */
5297                                 cph = (conn_pid_node_list_hdr_t *)
5298                                         ((char *)ude + udpEntrySize);
5299                                 print_hdr_once_v4 = udp_report_item_v4(ude,
5300                                     cph, print_hdr_once_v4, aptr);
5301                         }
5302                 } else if ((Uflag) && item->group == MIB2_UDP6 &&
5303                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5304                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
5305                             (char *)ude6 < (char *)item->valp + item->length;
5306                             /* LINTED: (note 1) */
5307                             ude6 = (mib2_udp6Entry_t *)((char *)cph +
5308                             cph->cph_tot_size)) {
5309                                 aptr = v6a == NULL ? NULL : *v6a++;
5310                                 /* LINTED: (note 1) */
5311                                 cph = (conn_pid_node_list_hdr_t *)
5312                                         ((char *)ude6 + udp6EntrySize);
5313                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
5314                                     cph, print_hdr_once_v6, aptr);
5315                         }
5316                 }
5317         } /* 'for' loop 1 ends */
5318         (void) fflush(stdout);
5319 
5320         if (v4_attrs != NULL)
5321                 free(v4_attrs);
5322         if (v6_attrs != NULL)
5323                 free(v6_attrs);
5324 }
5325 
5326 static boolean_t
5327 udp_report_item_v4(const mib2_udpEntry_t *ude, conn_pid_node_list_hdr_t *cph,
5328     boolean_t first, const mib2_transportMLPEntry_t *attr)
5329 {
5330         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5331                         /* hostname + portname */
5332 
5333         if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
5334                 return (first); /* Nothing to print */
5335 
5336         if (first) {
5337                 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
5338 
5339                 if (Uflag)
5340                         (void) printf(Vflag ? udp_hdr_v4_pid_verbose :
5341                                 udp_hdr_v4_pid);
5342                 else
5343                         (void) printf(udp_hdr_v4);
5344 
5345                 first = B_FALSE;
5346         }
5347 
5348         (void) printf("%-20s %-20s ",
5349             pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
5350             lname, sizeof (lname)),

5351             ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
5352             pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
5353             ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5354             "");
5355         if (!Uflag) {
5356                 (void) printf("%s\n",
5357                     miudp_state(ude->udpEntryInfo.ue_state, attr));
5358         } else {
5359                 int i = 0;
5360                 conn_pid_node_t *cpn = cph->cph_cpns;
5361                 proc_info_t *pinfo;
5362 
5363                 do {
5364                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5365                         pinfo = get_proc_info(cpn->cpn_pid);
5366                         (void) printf("%-8.8s %6u ", pinfo->pr_user, pid);
5367 
5368                         if (Vflag) {
5369                                 (void) printf("%-10.10s %s\n",
5370                                     miudp_state(ude->udpEntryInfo.ue_state,
5371                                     attr),
5372                                     pinfo->pr_psargs);
5373                         } else {
5374                                 (void) printf("%-14.14s %s\n", pinfo->pr_fname,
5375                                   miudp_state(ude->udpEntryInfo.ue_state,
5376                                   attr));
5377                         }
5378                         i++; cpn++;
5379                 } while (i < cph->cph_pn_cnt);
5380         }
5381 
5382         print_transport_label(attr);
5383 
5384         return (first);
5385 }
5386 
5387 static boolean_t
5388 udp_report_item_v6(const mib2_udp6Entry_t *ude6, conn_pid_node_list_hdr_t *cph,
5389     boolean_t first, const mib2_transportMLPEntry_t *attr)
5390 {
5391         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5392                         /* hostname + portname */
5393         char    ifname[LIFNAMSIZ + 1];
5394         const char *ifnamep;
5395 
5396         if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
5397                 return (first); /* Nothing to print */
5398 
5399         if (first) {
5400                 (void) printf("\nUDP: IPv6\n");
5401 
5402                 if (Uflag)
5403                         (void) printf(Vflag ? udp_hdr_v6_pid_verbose :
5404                                 udp_hdr_v6_pid);
5405                 else
5406                         (void) printf(udp_hdr_v6);
5407 
5408                 first = B_FALSE;
5409         }
5410 
5411         ifnamep = (ude6->udp6IfIndex != 0) ?
5412             if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
5413 
5414         (void) printf("%-33s %-33s ",
5415             pr_ap6(&ude6->udp6LocalAddress,
5416             ude6->udp6LocalPort, "udp", lname, sizeof (lname)),

5417             ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
5418             pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
5419             ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5420             "");
5421         if (!Uflag) {
5422                 (void) printf("%-10s %s\n",
5423                     miudp_state(ude6->udp6EntryInfo.ue_state, attr),
5424                     ifnamep == NULL ? "" : ifnamep);
5425         } else {
5426                 int i = 0;
5427                 conn_pid_node_t *cpn = cph->cph_cpns;
5428                 proc_info_t *pinfo;
5429 
5430                 do {
5431                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5432                         pinfo = get_proc_info(cpn->cpn_pid);
5433                         (void) printf("%-8.8s %6u ", pinfo->pr_user, pid);
5434 
5435                         if (Vflag) {
5436                                 (void) printf("%-10.10s %-5.5s %s\n",
5437                                     miudp_state(ude6->udp6EntryInfo.ue_state,
5438                                     attr),
5439                                     ifnamep == NULL ? "" : ifnamep,
5440                                     pinfo->pr_psargs);
5441                         } else {
5442                                 (void) printf("%-14.14s %-10.10s %s\n",
5443                                     pinfo->pr_fname,
5444                                     miudp_state(ude6->udp6EntryInfo.ue_state,
5445                                     attr),
5446                                     ifnamep == NULL ? "" : ifnamep);
5447                         }
5448                         i++; cpn++;
5449                 } while (i < cph->cph_pn_cnt);
5450         }
5451 
5452         print_transport_label(attr);
5453 
5454         return (first);
5455 }
5456 
5457 /* ------------------------------ SCTP_REPORT------------------------------- */
5458 
5459 static const char sctp_hdr[] =
5460 "\nSCTP:";
5461 static const char sctp_hdr_normal[] =
5462 "        Local Address                   Remote Address          "
5463 "Swind  Send-Q Rwind  Recv-Q StrsI/O  State\n"
5464 "------------------------------- ------------------------------- "
5465 "------ ------ ------ ------ ------- -----------";
5466 static const char sctp_hdr_pid[] =
5467 "        Local Address                   Remote Address          "
5468 "Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid      Command      State\n"
5469 "------------------------------- ------------------------------- ------ "
5470 "------ ------ ------ ------- -------- ------ -------------- -----------";
5471 static const char sctp_hdr_pid_verbose[] =
5472 "        Local Address                   Remote Address          "
5473 "Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid    State         Command\n"
5474 "------------------------------- ------------------------------- ------ "
5475 "------ ------ ------ ------- -------- ------ ----------- --------------";
5476 
5477 static const char *
5478 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
5479 {
5480         static char sctpsbuf[50];
5481         const char *cp;
5482 
5483         switch (state) {
5484         case MIB2_SCTP_closed:
5485                 cp = "CLOSED";
5486                 break;
5487         case MIB2_SCTP_cookieWait:
5488                 cp = "COOKIE_WAIT";
5489                 break;
5490         case MIB2_SCTP_cookieEchoed:
5491                 cp = "COOKIE_ECHOED";
5492                 break;
5493         case MIB2_SCTP_established:
5494                 cp = "ESTABLISHED";
5495                 break;


5622                 } else {
5623                         (void) pr_addr(v4addr, name, namelen);
5624                 }
5625                 break;
5626 
5627         case MIB2_SCTP_ADDR_V6:
5628                 /* v6 */
5629                 if (port > 0) {
5630                         (void) pr_ap6(addr, port, "sctp", name, namelen);
5631                 } else {
5632                         (void) pr_addr6(addr, name, namelen);
5633                 }
5634                 break;
5635 
5636         default:
5637                 (void) snprintf(name, namelen, "<unknown addr type>");
5638                 break;
5639         }
5640 }
5641 
5642 static boolean_t
5643 sctp_conn_report_item(const mib_item_t *head, conn_pid_node_list_hdr_t * cph,
5644     boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp,
5645     const mib2_transportMLPEntry_t *attr)
5646 {
5647         char            lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5648         char            fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5649         const mib2_sctpConnRemoteEntry_t        *sre = NULL;
5650         const mib2_sctpConnLocalEntry_t *sle = NULL;
5651         const mib_item_t *local = head;
5652         const mib_item_t *remote = head;
5653         uint32_t        id = sp->sctpAssocId;
5654         boolean_t       printfirst = B_TRUE;
5655 
5656         if (print_sctp_hdr == B_TRUE) {
5657                 (void) puts(sctp_hdr);
5658                 if (Uflag)
5659                         (void) puts(Vflag? sctp_hdr_pid_verbose: sctp_hdr_pid);
5660                 else
5661                         (void) puts(sctp_hdr_normal);
5662 
5663                 print_sctp_hdr = B_FALSE;
5664         }
5665 
5666         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5667             &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5668         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5669             &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5670 
5671         if (Uflag) {
5672                 int i = 0;
5673                 conn_pid_node_t *cpn = cph->cph_cpns;
5674                 proc_info_t *pinfo;
5675 
5676                 do {
5677                         int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
5678                         pinfo = get_proc_info(cpn->cpn_pid);
5679                         (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %-8.8s %6u ",
5680                             lname, fname,
5681                             sp->sctpConnEntryInfo.ce_swnd,
5682                             sp->sctpConnEntryInfo.ce_sendq,
5683                             sp->sctpConnEntryInfo.ce_rwnd,
5684                             sp->sctpConnEntryInfo.ce_recvq,
5685                             sp->sctpAssocInStreams,
5686                             sp->sctpAssocOutStreams,
5687                             pinfo->pr_user, pid);
5688 
5689                         if (Vflag) {
5690                                 (void) printf("%-11.11s %s\n",
5691                                     nssctp_state(sp->sctpAssocState, attr),
5692                                     pinfo->pr_psargs);
5693                         } else {
5694                                 (void) printf("%-14.14s %s\n",
5695                                     pinfo->pr_fname,
5696                                     nssctp_state(sp->sctpAssocState, attr));
5697                         }
5698 
5699                         i++; cpn++;
5700                 } while (i < cph->cph_pn_cnt);
5701 
5702         } else {
5703 
5704                 (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5705                     lname, fname,
5706                     sp->sctpConnEntryInfo.ce_swnd,
5707                     sp->sctpConnEntryInfo.ce_sendq,
5708                     sp->sctpConnEntryInfo.ce_rwnd,
5709                     sp->sctpConnEntryInfo.ce_recvq,
5710                     sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5711                     nssctp_state(sp->sctpAssocState, attr));
5712         }
5713 
5714         print_transport_label(attr);
5715 
5716         if (!Vflag) {
5717                 return (print_sctp_hdr);
5718         }
5719 
5720         /* Print remote addresses/local addresses on following lines */
5721         while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5722                 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5723                     &sp->sctpAssocRemPrimAddr)) {
5724                         if (printfirst == B_TRUE) {
5725                                 (void) fputs("\t<Remote: ", stdout);
5726                                 printfirst = B_FALSE;
5727                         } else {
5728                                 (void) fputs(", ", stdout);
5729                         }
5730                         sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5731                             sizeof (fname), &sre->sctpAssocRemAddr, -1);
5732                         if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5733                                 (void) fputs(fname, stdout);
5734                         } else {
5735                                 (void) printf("(%s)", fname);
5736                         }
5737                 }


5740                 (void) puts(">");
5741                 printfirst = B_TRUE;
5742         }
5743         while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5744                 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5745                     &sp->sctpAssocLocPrimAddr)) {
5746                         if (printfirst == B_TRUE) {
5747                                 (void) fputs("\t<Local: ", stdout);
5748                                 printfirst = B_FALSE;
5749                         } else {
5750                                 (void) fputs(", ", stdout);
5751                         }
5752                         sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5753                             sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5754                         (void) fputs(lname, stdout);
5755                 }
5756         }
5757         if (printfirst == B_FALSE) {
5758                 (void) puts(">");
5759         }
5760 
5761         return (print_sctp_hdr);
5762 }
5763 
5764 static void
5765 sctp_report(const mib_item_t *item)
5766 {
5767         const mib_item_t                *head;
5768         const mib2_sctpConnEntry_t      *sp;
5769         boolean_t                       print_sctp_hdr_once = B_TRUE;
5770         mib2_transportMLPEntry_t        **attrs, **aptr;
5771         mib2_transportMLPEntry_t        *attr;
5772         conn_pid_node_list_hdr_t        *cph;
5773 
5774         /*
5775          * Preparation pass: the kernel returns separate entries for SCTP
5776          * connection table entries and Multilevel Port attributes.  We loop
5777          * through the attributes first and set up an array for each address
5778          * family.
5779          */
5780         attrs = RSECflag ?
5781             gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5782             NULL;
5783 
5784         aptr = attrs;
5785         head = item;
5786         for (; item != NULL; item = item->next_item) {
5787 
5788                 if (!((item->group == MIB2_SCTP &&
5789                     item->mib_id == MIB2_SCTP_CONN) ||
5790                     (item->group == MIB2_SCTP &&
5791                     item->mib_id == EXPER_XPORT_PROC_INFO)))
5792                         continue;
5793 
5794                 if ((!Uflag) && item->group == MIB2_SCTP
5795                     && item->mib_id == MIB2_SCTP_CONN) {
5796                         for (sp = item->valp;
5797                             (char *)sp < (char *)item->valp + item->length;
5798                             /* LINTED: (note 1) */
5799                             sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
5800                                 if (!(Aflag ||
5801                                   sp->sctpAssocState >= MIB2_SCTP_established))
5802                                         continue;
5803                                 attr = aptr == NULL ? NULL : *aptr++;
5804                                 print_sctp_hdr_once = sctp_conn_report_item(head, NULL,
5805                                                         print_sctp_hdr_once, sp,
5806                                                         attr);
5807                         }
5808                 } else if ((Uflag) && item->group == MIB2_SCTP &&
5809                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5810                         for (sp = (mib2_sctpConnEntry_t *)item->valp;
5811                             (char *)sp < (char *)item->valp + item->length;
5812                             /* LINTED: (note 1) */
5813                             sp = (mib2_sctpConnEntry_t *)((char *)cph +
5814                             cph->cph_tot_size)) {
5815                                 /* LINTED: (note 1) */
5816                                 cph = (conn_pid_node_list_hdr_t *)
5817                                         ((char *)sp + sctpEntrySize);
5818                                 if (!(Aflag ||
5819                                   sp->sctpAssocState >= MIB2_SCTP_established))
5820                                         continue;
5821                                 attr = aptr == NULL ? NULL : *aptr++;
5822                                 print_sctp_hdr_once =
5823                                     sctp_conn_report_item(head, cph,
5824                                         print_sctp_hdr_once, sp, attr);
5825                         }
5826                 }
5827         }
5828         if (attrs != NULL)
5829                 free(attrs);
5830 }
5831 
5832 static char *
5833 plural(int n)
5834 {
5835         return (n != 1 ? "s" : "");
5836 }
5837 
5838 static char *
5839 pluraly(int n)
5840 {
5841         return (n != 1 ? "ies" : "y");
5842 }
5843 
5844 static char *


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