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


 955                             item->length);
 956                         tempp = &(localp[c]);
 957                         if (c > 0)
 958                                 (localp[c - 1]).next_item = tempp;
 959                         c++;
 960                 }
 961         }
 962         return (localp);
 963 }
 964 
 965 /*
 966  * mib_item_diff: takes two (mib_item_t *) linked lists
 967  * item1 and item2 and computes the difference between
 968  * differentiable values in item2 against item1 for every
 969  * given member of item2; returns an mib_item_t * linked
 970  * list of diff's, or a copy of item2 if item1 is NULL;
 971  * will return NULL if system out of memory; works only
 972  * for item->mib_id == 0
 973  */
 974 static mib_item_t *
 975 mib_item_diff(mib_item_t *item1, mib_item_t *item2) {

 976         int     nitems  = 0; /* no. of items in item2 */
 977         mib_item_t *tempp2;  /* walking copy of item2 */
 978         mib_item_t *tempp1;  /* walking copy of item1 */
 979         mib_item_t *diffp;
 980         mib_item_t *diffptr; /* walking copy of diffp */
 981         mib_item_t *prevp = NULL;
 982 
 983         if (item1 == NULL) {
 984                 diffp = mib_item_dup(item2);
 985                 return (diffp);
 986         }
 987 
 988         for (tempp2 = item2;
 989             tempp2;
 990             tempp2 = tempp2->next_item) {
 991                 if (tempp2->mib_id == 0)
 992                         switch (tempp2->group) {
 993                         /*
 994                          * upon adding a case here, the same
 995                          * must also be added in the next


1481                         }
1482                 } /* 'for' loop 2 ends */
1483                 tempp1 = NULL;
1484         } /* 'for' loop 1 ends */
1485         tempp2 = NULL;
1486         diffptr--;
1487         diffptr->next_item = NULL;
1488         return (diffp);
1489 
1490 mibdiff_out_of_memory:;
1491         mib_item_destroy(&diffp);
1492         return (NULL);
1493 }
1494 
1495 /*
1496  * mib_item_destroy: cleans up a mib_item_t *
1497  * that was created by calling mib_item_dup or
1498  * mib_item_diff
1499  */
1500 static void
1501 mib_item_destroy(mib_item_t **itemp) {

1502         int     nitems = 0;
1503         int     c = 0;
1504         mib_item_t *tempp;
1505 
1506         if (itemp == NULL || *itemp == NULL)
1507                 return;
1508 
1509         for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1510                 if (tempp->mib_id == 0)
1511                         nitems++;
1512                 else
1513                         return; /* cannot destroy! */
1514 
1515         if (nitems == 0)
1516                 return;         /* cannot destroy! */
1517 
1518         for (c = nitems - 1; c >= 0; c--) {
1519                 if ((itemp[0][c]).valp != NULL)
1520                         free((itemp[0][c]).valp);
1521         }


3246                                 old6 = new6;
3247                                 cleanlist = oldlist6;
3248                                 oldlist6 = newlist6;
3249                                 while (cleanlist != NULL) {
3250                                         tlp = cleanlist->next_if;
3251                                         free(cleanlist);
3252                                         cleanlist = tlp;
3253                                 }
3254                         }
3255                         break;
3256                 }
3257                 }
3258                 (void) fflush(stdout);
3259         } /* 'for' loop 1 ends */
3260         if ((Iflag_only == 0) && (!once_only))
3261                 (void) putchar('\n');
3262         reentry = B_TRUE;
3263 }
3264 
3265 static void
3266 if_report_ip4(mib2_ipAddrEntry_t *ap,
3267         char ifname[], char logintname[], struct ifstat *statptr,
3268         boolean_t ksp_not_null) {
3269 
3270         char abuf[MAXHOSTNAMELEN + 1];
3271         char dstbuf[MAXHOSTNAMELEN + 1];
3272 
3273         if (ksp_not_null) {
3274                 (void) printf("%-5s %-4u ",
3275                     ifname, ap->ipAdEntInfo.ae_mtu);
3276                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3277                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3278                             abuf, sizeof (abuf));
3279                 else
3280                         (void) pr_netaddr(ap->ipAdEntAddr,
3281                             ap->ipAdEntNetMask, abuf, sizeof (abuf));
3282                 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3283                     "%-6llu %-6llu\n",
3284                     abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3285                     statptr->ipackets, statptr->ierrors,
3286                     statptr->opackets, statptr->oerrors,
3287                     statptr->collisions, 0LL);
3288         }


3294                 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3295                 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3296 
3297                 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3298                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3299                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3300                         sizeof (abuf));
3301                 else
3302                         (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3303                             abuf, sizeof (abuf));
3304 
3305                 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3306                     "%-5s %-6s %-6llu\n", abuf,
3307                     pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3308                     statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3309                     0LL);
3310         }
3311 }
3312 
3313 static void
3314 if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
3315         char ifname[], char logintname[], struct ifstat *statptr,
3316         boolean_t ksp_not_null) {
3317 
3318         char abuf[MAXHOSTNAMELEN + 1];
3319         char dstbuf[MAXHOSTNAMELEN + 1];
3320 
3321         if (ksp_not_null) {
3322                 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3323                 if (ap6->ipv6AddrInfo.ae_flags &
3324                     IFF_POINTOPOINT) {
3325                         (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3326                             abuf, sizeof (abuf));
3327                 } else {
3328                         (void) pr_prefix6(&ap6->ipv6AddrAddress,
3329                             ap6->ipv6AddrPfxLength, abuf,
3330                             sizeof (abuf));
3331                 }
3332                 (void) printf("%-27s %-27s %-6llu %-5llu "
3333                     "%-6llu %-5llu %-6llu\n",
3334                     abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3335                     sizeof (dstbuf)),
3336                     statptr->ipackets, statptr->ierrors, statptr->opackets,


4725                 free(sl_str);
4726         }
4727 }
4728 
4729 /* ------------------------------ TCP_REPORT------------------------------- */
4730 
4731 static const char tcp_hdr_v4[] =
4732 "\nTCP: IPv4\n";
4733 static const char tcp_hdr_v4_compat[] =
4734 "\nTCP\n";
4735 static const char tcp_hdr_v4_verbose[] =
4736 "Local/Remote Address Swind  Snext     Suna   Rwind  Rnext     Rack   "
4737 " Rto   Mss     State\n"
4738 "-------------------- ----- -------- -------- ----- -------- -------- "
4739 "----- ----- -----------\n";
4740 static const char tcp_hdr_v4_normal[] =
4741 "   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q "
4742 "   State\n"
4743 "-------------------- -------------------- ----- ------ ----- ------ "
4744 "-----------\n";










4745 
4746 static const char tcp_hdr_v6[] =
4747 "\nTCP: IPv6\n";
4748 static const char tcp_hdr_v6_verbose[] =
4749 "Local/Remote Address              Swind  Snext     Suna   Rwind  Rnext   "
4750 "  Rack    Rto   Mss    State      If\n"
4751 "--------------------------------- ----- -------- -------- ----- -------- "
4752 "-------- ----- ----- ----------- -----\n";
4753 static const char tcp_hdr_v6_normal[] =
4754 "   Local Address                     Remote Address                 "
4755 "Swind Send-Q Rwind Recv-Q   State      If\n"
4756 "--------------------------------- --------------------------------- "
4757 "----- ------ ----- ------ ----------- -----\n";










4758 
4759 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
4760     boolean_t first, const mib2_transportMLPEntry_t *);

4761 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
4762     boolean_t first, const mib2_transportMLPEntry_t *);


4763 
4764 static void
4765 tcp_report(const mib_item_t *item)
4766 {
4767         int                     jtemp = 0;
4768         boolean_t               print_hdr_once_v4 = B_TRUE;
4769         boolean_t               print_hdr_once_v6 = B_TRUE;
4770         mib2_tcpConnEntry_t     *tp;
4771         mib2_tcp6ConnEntry_t    *tp6;
4772         mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
4773         mib2_transportMLPEntry_t **v4a, **v6a;
4774         mib2_transportMLPEntry_t *aptr;

4775 
4776         if (!protocol_selected(IPPROTO_TCP))
4777                 return;
4778 
4779         /*
4780          * Preparation pass: the kernel returns separate entries for TCP
4781          * connection table entries and Multilevel Port attributes.  We loop
4782          * through the attributes first and set up an array for each address
4783          * family.
4784          */
4785         v4_attrs = family_selected(AF_INET) && RSECflag ?
4786             gather_attrs(item, MIB2_TCP, MIB2_TCP_CONN, tcpConnEntrySize) :
4787             NULL;
4788         v6_attrs = family_selected(AF_INET6) && RSECflag ?
4789             gather_attrs(item, MIB2_TCP6, MIB2_TCP6_CONN, tcp6ConnEntrySize) :
4790             NULL;
4791 
4792         /* 'for' loop 1: */
4793         v4a = v4_attrs;
4794         v6a = v6_attrs;
4795         for (; item != NULL; item = item->next_item) {
4796                 if (Xflag) {
4797                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
4798                         (void) printf("Group = %d, mib_id = %d, "
4799                             "length = %d, valp = 0x%p\n",
4800                             item->group, item->mib_id,
4801                             item->length, item->valp);
4802                 }
4803 
4804                 if (!((item->group == MIB2_TCP &&
4805                     item->mib_id == MIB2_TCP_CONN) ||
4806                     (item->group == MIB2_TCP6 &&
4807                     item->mib_id == MIB2_TCP6_CONN)))




4808                         continue; /* 'for' loop 1 */
4809 
4810                 if (item->group == MIB2_TCP && !family_selected(AF_INET))
4811                         continue; /* 'for' loop 1 */
4812                 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
4813                         continue; /* 'for' loop 1 */
4814 
4815                 if (item->group == MIB2_TCP) {

4816                         for (tp = (mib2_tcpConnEntry_t *)item->valp;
4817                             (char *)tp < (char *)item->valp + item->length;
4818                             /* LINTED: (note 1) */
4819                             tp = (mib2_tcpConnEntry_t *)((char *)tp +
4820                             tcpConnEntrySize)) {
4821                                 aptr = v4a == NULL ? NULL : *v4a++;
4822                                 print_hdr_once_v4 = tcp_report_item_v4(tp,
4823                                     print_hdr_once_v4, aptr);
4824                         }
4825                 } else {

4826                         for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
4827                             (char *)tp6 < (char *)item->valp + item->length;
4828                             /* LINTED: (note 1) */
4829                             tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
4830                             tcp6ConnEntrySize)) {
4831                                 aptr = v6a == NULL ? NULL : *v6a++;
4832                                 print_hdr_once_v6 = tcp_report_item_v6(tp6,
4833                                     print_hdr_once_v6, aptr);




























4834                         }
4835                 }

4836         } /* 'for' loop 1 ends */
4837         (void) fflush(stdout);
4838 
4839         if (v4_attrs != NULL)
4840                 free(v4_attrs);
4841         if (v6_attrs != NULL)
4842                 free(v6_attrs);
4843 }
4844 
4845 static boolean_t
4846 tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first,
4847     const mib2_transportMLPEntry_t *attr)
4848 {
4849         /*
4850          * lname and fname below are for the hostname as well as the portname
4851          * There is no limit on portname length so we assume MAXHOSTNAMELEN
4852          * as the limit
4853          */
4854         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4855         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4856 

4857         if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4858                 return (first); /* Nothing to print */
4859 
4860         if (first) {
4861                 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
4862                 (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);





4863         }
4864 
4865         if (Vflag) {
4866                 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
4867                     "%5u %5u %s\n",
4868                     pr_ap(tp->tcpConnLocalAddress,
4869                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4870                     pr_ap(tp->tcpConnRemAddress,
4871                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4872                     tp->tcpConnEntryInfo.ce_swnd,
4873                     tp->tcpConnEntryInfo.ce_snxt,
4874                     tp->tcpConnEntryInfo.ce_suna,
4875                     tp->tcpConnEntryInfo.ce_rwnd,
4876                     tp->tcpConnEntryInfo.ce_rnxt,
4877                     tp->tcpConnEntryInfo.ce_rack,
4878                     tp->tcpConnEntryInfo.ce_rto,
4879                     tp->tcpConnEntryInfo.ce_mss,
4880                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
4881         } else {
4882                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
4883                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
4884                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
4885                     (int)tp->tcpConnEntryInfo.ce_rack;
4886 
4887                 (void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
4888                     pr_ap(tp->tcpConnLocalAddress,
4889                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
4890                     pr_ap(tp->tcpConnRemAddress,
4891                     tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
4892                     tp->tcpConnEntryInfo.ce_swnd,
4893                     (sq >= 0) ? sq : 0,
4894                     tp->tcpConnEntryInfo.ce_rwnd,
4895                     (rq >= 0) ? rq : 0,
4896                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
















































4897         }
4898 
4899         print_transport_label(attr);
4900 
4901         return (B_FALSE);
4902 }
4903 
4904 static boolean_t
4905 tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first,
4906     const mib2_transportMLPEntry_t *attr)
4907 {
4908         /*
4909          * lname and fname below are for the hostname as well as the portname
4910          * There is no limit on portname length so we assume MAXHOSTNAMELEN
4911          * as the limit
4912          */
4913         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4914         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
4915         char    ifname[LIFNAMSIZ + 1];
4916         char    *ifnamep;
4917 
4918         if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
4919                 return (first); /* Nothing to print */
4920 
4921         if (first) {
4922                 (void) printf(tcp_hdr_v6);
4923                 (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);





4924         }
4925 
4926         ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
4927             if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
4928         if (ifnamep == NULL)
4929                 ifnamep = "";
4930 
4931         if (Vflag) {
4932                 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
4933                     "%5u %5u %-11s %s\n",
4934                     pr_ap6(&tp6->tcp6ConnLocalAddress,
4935                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4936                     pr_ap6(&tp6->tcp6ConnRemAddress,
4937                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4938                     tp6->tcp6ConnEntryInfo.ce_swnd,
4939                     tp6->tcp6ConnEntryInfo.ce_snxt,
4940                     tp6->tcp6ConnEntryInfo.ce_suna,
4941                     tp6->tcp6ConnEntryInfo.ce_rwnd,
4942                     tp6->tcp6ConnEntryInfo.ce_rnxt,
4943                     tp6->tcp6ConnEntryInfo.ce_rack,
4944                     tp6->tcp6ConnEntryInfo.ce_rto,
4945                     tp6->tcp6ConnEntryInfo.ce_mss,
4946                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
4947                     ifnamep);
4948         } else {
4949                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
4950                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
4951                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
4952                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
4953 
4954                 (void) printf("%-33s %-33s %5u %6d %5u %6d %-11s %s\n",
4955                     pr_ap6(&tp6->tcp6ConnLocalAddress,
4956                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
4957                     pr_ap6(&tp6->tcp6ConnRemAddress,
4958                     tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
4959                     tp6->tcp6ConnEntryInfo.ce_swnd,
4960                     (sq >= 0) ? sq : 0,
4961                     tp6->tcp6ConnEntryInfo.ce_rwnd,
4962                     (rq >= 0) ? rq : 0,
4963                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
4964                     ifnamep);





















































4965         }
4966 
4967         print_transport_label(attr);
4968 
4969         return (B_FALSE);
4970 }
4971 
4972 /* ------------------------------- UDP_REPORT------------------------------- */
4973 
4974 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
4975     boolean_t first, const mib2_transportMLPEntry_t *attr);

4976 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
4977     boolean_t first, const mib2_transportMLPEntry_t *attr);

4978 
4979 static const char udp_hdr_v4[] =
4980 "   Local Address        Remote Address      State\n"
4981 "-------------------- -------------------- ----------\n";










4982 
4983 static const char udp_hdr_v6[] =
4984 "   Local Address                     Remote Address                 "
4985 "  State      If\n"
4986 "--------------------------------- --------------------------------- "
4987 "---------- -----\n";











4988 
4989 static void
4990 udp_report(const mib_item_t *item)
4991 {
4992         int                     jtemp = 0;
4993         boolean_t               print_hdr_once_v4 = B_TRUE;
4994         boolean_t               print_hdr_once_v6 = B_TRUE;
4995         mib2_udpEntry_t         *ude;
4996         mib2_udp6Entry_t        *ude6;
4997         mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
4998         mib2_transportMLPEntry_t **v4a, **v6a;
4999         mib2_transportMLPEntry_t *aptr;

5000 
5001         if (!protocol_selected(IPPROTO_UDP))
5002                 return;
5003 
5004         /*
5005          * Preparation pass: the kernel returns separate entries for UDP
5006          * connection table entries and Multilevel Port attributes.  We loop
5007          * through the attributes first and set up an array for each address
5008          * family.
5009          */
5010         v4_attrs = family_selected(AF_INET) && RSECflag ?
5011             gather_attrs(item, MIB2_UDP, MIB2_UDP_ENTRY, udpEntrySize) : NULL;
5012         v6_attrs = family_selected(AF_INET6) && RSECflag ?
5013             gather_attrs(item, MIB2_UDP6, MIB2_UDP6_ENTRY, udp6EntrySize) :
5014             NULL;
5015 
5016         v4a = v4_attrs;
5017         v6a = v6_attrs;
5018         /* 'for' loop 1: */
5019         for (; item; item = item->next_item) {
5020                 if (Xflag) {
5021                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
5022                         (void) printf("Group = %d, mib_id = %d, "
5023                             "length = %d, valp = 0x%p\n",
5024                             item->group, item->mib_id,
5025                             item->length, item->valp);
5026                 }
5027                 if (!((item->group == MIB2_UDP &&
5028                     item->mib_id == MIB2_UDP_ENTRY) ||
5029                     (item->group == MIB2_UDP6 &&
5030                     item->mib_id == MIB2_UDP6_ENTRY)))




5031                         continue; /* 'for' loop 1 */
5032 
5033                 if (item->group == MIB2_UDP && !family_selected(AF_INET))
5034                         continue; /* 'for' loop 1 */
5035                 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
5036                         continue; /* 'for' loop 1 */
5037 
5038                 /*      xxx.xxx.xxx.xxx,pppp  sss... */
5039                 if (item->group == MIB2_UDP) {

5040                         for (ude = (mib2_udpEntry_t *)item->valp;
5041                             (char *)ude < (char *)item->valp + item->length;
5042                             /* LINTED: (note 1) */
5043                             ude = (mib2_udpEntry_t *)((char *)ude +
5044                             udpEntrySize)) {
5045                                 aptr = v4a == NULL ? NULL : *v4a++;
5046                                 print_hdr_once_v4 = udp_report_item_v4(ude,
5047                                     print_hdr_once_v4, aptr);
5048                         }
5049                 } else {

5050                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
5051                             (char *)ude6 < (char *)item->valp + item->length;
5052                             /* LINTED: (note 1) */
5053                             ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
5054                             udp6EntrySize)) {
5055                                 aptr = v6a == NULL ? NULL : *v6a++;
5056                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
5057                                     print_hdr_once_v6, aptr);




























5058                         }
5059                 }
5060         } /* 'for' loop 1 ends */
5061         (void) fflush(stdout);
5062 
5063         if (v4_attrs != NULL)
5064                 free(v4_attrs);
5065         if (v6_attrs != NULL)
5066                 free(v6_attrs);
5067 }
5068 
5069 static boolean_t
5070 udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first,
5071     const mib2_transportMLPEntry_t *attr)
5072 {
5073         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5074                         /* hostname + portname */
5075 
5076         if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
5077                 return (first); /* Nothing to print */
5078 
5079         if (first) {
5080                 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");





5081                 (void) printf(udp_hdr_v4);

5082                 first = B_FALSE;
5083         }
5084 
5085         (void) printf("%-20s ",
5086             pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
5087             lname, sizeof (lname)));
5088         (void) printf("%-20s %s\n",
5089             ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
5090             pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
5091             ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5092             "",


5093             miudp_state(ude->udpEntryInfo.ue_state, attr));





















5094 
5095         print_transport_label(attr);
5096 
5097         return (first);
5098 }
5099 
5100 static boolean_t
5101 udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first,
5102     const mib2_transportMLPEntry_t *attr)
5103 {
5104         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5105                         /* hostname + portname */
5106         char    ifname[LIFNAMSIZ + 1];
5107         const char *ifnamep;
5108 
5109         if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
5110                 return (first); /* Nothing to print */
5111 
5112         if (first) {
5113                 (void) printf("\nUDP: IPv6\n");





5114                 (void) printf(udp_hdr_v6);

5115                 first = B_FALSE;
5116         }
5117 
5118         ifnamep = (ude6->udp6IfIndex != 0) ?
5119             if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
5120 
5121         (void) printf("%-33s ",
5122             pr_ap6(&ude6->udp6LocalAddress,
5123             ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
5124         (void) printf("%-33s %-10s %s\n",
5125             ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
5126             pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
5127             ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
5128             "",


5129             miudp_state(ude6->udp6EntryInfo.ue_state, attr),
5130             ifnamep == NULL ? "" : ifnamep);
























5131 
5132         print_transport_label(attr);
5133 
5134         return (first);
5135 }
5136 
5137 /* ------------------------------ SCTP_REPORT------------------------------- */
5138 
5139 static const char sctp_hdr[] =
5140 "\nSCTP:";
5141 static const char sctp_hdr_normal[] =
5142 "        Local Address                   Remote Address          "
5143 "Swind  Send-Q Rwind  Recv-Q StrsI/O  State\n"
5144 "------------------------------- ------------------------------- "
5145 "------ ------ ------ ------ ------- -----------";










5146 
5147 static const char *
5148 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
5149 {
5150         static char sctpsbuf[50];
5151         const char *cp;
5152 
5153         switch (state) {
5154         case MIB2_SCTP_closed:
5155                 cp = "CLOSED";
5156                 break;
5157         case MIB2_SCTP_cookieWait:
5158                 cp = "COOKIE_WAIT";
5159                 break;
5160         case MIB2_SCTP_cookieEchoed:
5161                 cp = "COOKIE_ECHOED";
5162                 break;
5163         case MIB2_SCTP_established:
5164                 cp = "ESTABLISHED";
5165                 break;


5292                 } else {
5293                         (void) pr_addr(v4addr, name, namelen);
5294                 }
5295                 break;
5296 
5297         case MIB2_SCTP_ADDR_V6:
5298                 /* v6 */
5299                 if (port > 0) {
5300                         (void) pr_ap6(addr, port, "sctp", name, namelen);
5301                 } else {
5302                         (void) pr_addr6(addr, name, namelen);
5303                 }
5304                 break;
5305 
5306         default:
5307                 (void) snprintf(name, namelen, "<unknown addr type>");
5308                 break;
5309         }
5310 }
5311 
5312 static void
5313 sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp,

5314     const mib2_transportMLPEntry_t *attr)
5315 {
5316         char            lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5317         char            fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
5318         const mib2_sctpConnRemoteEntry_t        *sre = NULL;
5319         const mib2_sctpConnLocalEntry_t *sle = NULL;
5320         const mib_item_t *local = head;
5321         const mib_item_t *remote = head;
5322         uint32_t        id = sp->sctpAssocId;
5323         boolean_t       printfirst = B_TRUE;
5324 










5325         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
5326             &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
5327         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
5328             &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
5329 






























5330         (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
5331             lname, fname,
5332             sp->sctpConnEntryInfo.ce_swnd,
5333             sp->sctpConnEntryInfo.ce_sendq,
5334             sp->sctpConnEntryInfo.ce_rwnd,
5335             sp->sctpConnEntryInfo.ce_recvq,
5336             sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
5337             nssctp_state(sp->sctpAssocState, attr));

5338 
5339         print_transport_label(attr);
5340 
5341         if (!Vflag) {
5342                 return;
5343         }
5344 
5345         /* Print remote addresses/local addresses on following lines */
5346         while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
5347                 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,
5348                     &sp->sctpAssocRemPrimAddr)) {
5349                         if (printfirst == B_TRUE) {
5350                                 (void) fputs("\t<Remote: ", stdout);
5351                                 printfirst = B_FALSE;
5352                         } else {
5353                                 (void) fputs(", ", stdout);
5354                         }
5355                         sctp_pr_addr(sre->sctpAssocRemAddrType, fname,
5356                             sizeof (fname), &sre->sctpAssocRemAddr, -1);
5357                         if (sre->sctpAssocRemAddrActive == MIB2_SCTP_ACTIVE) {
5358                                 (void) fputs(fname, stdout);
5359                         } else {
5360                                 (void) printf("(%s)", fname);
5361                         }
5362                 }


5365                 (void) puts(">");
5366                 printfirst = B_TRUE;
5367         }
5368         while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5369                 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5370                     &sp->sctpAssocLocPrimAddr)) {
5371                         if (printfirst == B_TRUE) {
5372                                 (void) fputs("\t<Local: ", stdout);
5373                                 printfirst = B_FALSE;
5374                         } else {
5375                                 (void) fputs(", ", stdout);
5376                         }
5377                         sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5378                             sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5379                         (void) fputs(lname, stdout);
5380                 }
5381         }
5382         if (printfirst == B_FALSE) {
5383                 (void) puts(">");
5384         }


5385 }
5386 
5387 static void
5388 sctp_report(const mib_item_t *item)
5389 {
5390         const mib_item_t                *head;
5391         const mib2_sctpConnEntry_t      *sp;
5392         boolean_t               first = B_TRUE;
5393         mib2_transportMLPEntry_t **attrs, **aptr;
5394         mib2_transportMLPEntry_t *attr;

5395 
5396         /*
5397          * Preparation pass: the kernel returns separate entries for SCTP
5398          * connection table entries and Multilevel Port attributes.  We loop
5399          * through the attributes first and set up an array for each address
5400          * family.
5401          */
5402         attrs = RSECflag ?
5403             gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5404             NULL;
5405 
5406         aptr = attrs;
5407         head = item;
5408         for (; item != NULL; item = item->next_item) {
5409 
5410                 if (!(item->group == MIB2_SCTP &&
5411                     item->mib_id == MIB2_SCTP_CONN))


5412                         continue;
5413 


5414                 for (sp = item->valp;
5415                     (char *)sp < (char *)item->valp + item->length;
5416                     /* LINTED: (note 1) */
5417                     sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {





5418                         attr = aptr == NULL ? NULL : *aptr++;
5419                         if (Aflag ||
5420                             sp->sctpAssocState >= MIB2_SCTP_established) {
5421                                 if (first == B_TRUE) {
5422                                         (void) puts(sctp_hdr);
5423                                         (void) puts(sctp_hdr_normal);
5424                                         first = B_FALSE;
5425                                 }
5426                                 sctp_conn_report_item(head, sp, attr);
















5427                         }
5428                 }
5429         }
5430         if (attrs != NULL)
5431                 free(attrs);
5432 }
5433 
5434 static char *
5435 plural(int n)
5436 {
5437         return (n != 1 ? "s" : "");
5438 }
5439 
5440 static char *
5441 pluraly(int n)
5442 {
5443         return (n != 1 ? "ies" : "y");
5444 }
5445 
5446 static char *
5447 plurales(int n)
5448 {
5449         return (n != 1 ? "es" : "");
5450 }
5451 
5452 static char *
5453 pktscale(n)
5454         int n;
5455 {
5456         static char buf[6];
5457         char t;
5458 
5459         if (n < 1024) {
5460                 t = ' ';
5461         } else if (n < 1024 * 1024) {
5462                 t = 'k';
5463                 n /= 1024;
5464         } else if (n < 1024 * 1024 * 1024) {
5465                 t = 'm';
5466                 n /= 1024 * 1024;
5467         } else {
5468                 t = 'g';
5469                 n /= 1024 * 1024 * 1024;
5470         }
5471 
5472         (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5473         return (buf);
5474 }


6394         }
6395         return (B_FALSE);
6396 }
6397 
6398 /*
6399  * Convert the interface index to a string using the buffer `ifname', which
6400  * must be at least LIFNAMSIZ bytes.  We first try to map it to name.  If that
6401  * fails (e.g., because we're inside a zone and it does not have access to
6402  * interface for the index in question), just return "if#<num>".
6403  */
6404 static char *
6405 ifindex2str(uint_t ifindex, char *ifname)
6406 {
6407         if (if_indextoname(ifindex, ifname) == NULL)
6408                 (void) snprintf(ifname, LIFNAMSIZ, "if#%d", ifindex);
6409 
6410         return (ifname);
6411 }
6412 
6413 /*































































6414  * print the usage line
6415  */
6416 static void
6417 usage(char *cmdname)
6418 {
6419         (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] "
6420             "[-T d|u]\n", cmdname);
6421         (void) fprintf(stderr, "       %s [-n] [-f address_family] "
6422             "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
6423             cmdname);
6424         (void) fprintf(stderr, "       %s -m [-v] [-T d|u] "
6425             "[interval [count]]\n", cmdname);
6426         (void) fprintf(stderr, "       %s -i [-I interface] [-an] "
6427             "[-f address_family] [-T d|u] [interval [count]]\n", cmdname);
6428         (void) fprintf(stderr, "       %s -r [-anv] "
6429             "[-f address_family|filter] [-T d|u]\n", cmdname);
6430         (void) fprintf(stderr, "       %s -M [-ns] [-f address_family] "
6431             "[-T d|u]\n", cmdname);
6432         (void) fprintf(stderr, "       %s -D [-I interface] "
6433             "[-f address_family] [-T d|u]\n", cmdname);
6434         exit(EXIT_FAILURE);
6435 }
6436 
6437 /*
6438  * fatal: print error message to stderr and
6439  * call exit(errcode)
6440  */
6441 /*PRINTFLIKE2*/
6442 static void
6443 fatal(int errcode, char *format, ...)
6444 {
6445         va_list argp;
6446 
6447         if (format == NULL)
6448                 return;
6449 
6450         va_start(argp, format);
6451         (void) vfprintf(stderr, format, argp);
6452         va_end(argp);
6453 
6454         exit(errcode);
















































































































































































6455 }


  38  *    because they have 'continue' or 'break' statements in their
  39  *    bodies. 'continue' statements have been used inside some loops
  40  *    where avoiding them would have led to deep levels of indentation.
  41  *
  42  * TODO:
  43  *      Add ability to request subsets from kernel (with level = MIB2_IP;
  44  *      name = 0 meaning everything for compatibility)
  45  */
  46 
  47 #include <stdio.h>
  48 #include <stdlib.h>
  49 #include <stdarg.h>
  50 #include <unistd.h>
  51 #include <strings.h>
  52 #include <string.h>
  53 #include <errno.h>
  54 #include <ctype.h>
  55 #include <kstat.h>
  56 #include <assert.h>
  57 #include <locale.h>
  58 #include <pwd.h>
  59 #include <limits.h>
  60 
  61 #include <sys/types.h>
  62 #include <sys/stat.h>
  63 #include <sys/stream.h>
  64 #include <stropts.h>
  65 #include <sys/strstat.h>
  66 #include <sys/tihdr.h>
  67 #include <procfs.h>
  68 
  69 #include <sys/socket.h>
  70 #include <sys/socketvar.h>
  71 #include <sys/sockio.h>
  72 #include <netinet/in.h>
  73 #include <net/if.h>
  74 #include <net/route.h>
  75 
  76 #include <inet/mib2.h>
  77 #include <inet/ip.h>
  78 #include <inet/arp.h>
  79 #include <inet/tcp.h>
  80 #include <netinet/igmp_var.h>
  81 #include <netinet/ip_mroute.h>
  82 
  83 #include <arpa/inet.h>
  84 #include <netdb.h>
  85 #include <fcntl.h>
  86 #include <sys/systeminfo.h>
  87 #include <arpa/inet.h>
  88 
  89 #include <netinet/dhcp.h>
  90 #include <dhcpagent_ipc.h>
  91 #include <dhcpagent_util.h>
  92 #include <compat.h>
  93 
  94 #include <libtsnet.h>
  95 #include <tsol/label.h>
  96 
  97 #include "statcommon.h"
  98 

  99 
 100 #define STR_EXPAND      4
 101 
 102 #define V4MASK_TO_V6(v4, v6)    ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
 103                                 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \
 104                                 (v6)._S6_un._S6_u32[2] = 0xfffffffful, \
 105                                 (v6)._S6_un._S6_u32[3] = (v4))
 106 
 107 #define IN6_IS_V4MASK(v6)       ((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
 108                                 (v6)._S6_un._S6_u32[1] == 0xfffffffful && \
 109                                 (v6)._S6_un._S6_u32[2] == 0xfffffffful)
 110 
 111 /*
 112  * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
 113  * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
 114  * possible for an administrator to plumb new interfaces between those two
 115  * calls, resulting in the failure of the latter.  This addition makes that
 116  * less likely.
 117  */
 118 #define LIFN_GUARD_VALUE        10


 122         int                     group;
 123         int                     mib_id;
 124         int                     length;
 125         void                    *valp;
 126 } mib_item_t;
 127 
 128 struct  ifstat {
 129         uint64_t        ipackets;
 130         uint64_t        ierrors;
 131         uint64_t        opackets;
 132         uint64_t        oerrors;
 133         uint64_t        collisions;
 134 };
 135 
 136 struct iflist {
 137         struct iflist   *next_if;
 138         char            ifname[LIFNAMSIZ];
 139         struct ifstat   tot;
 140 };
 141 
 142 typedef struct proc_info {
 143         char *pr_user;
 144         char *pr_fname;
 145         char *pr_psargs;
 146 } proc_info_t;
 147 
 148 static  mib_item_t      *mibget(int sd);
 149 static  void            mibfree(mib_item_t *firstitem);
 150 static  int             mibopen(void);
 151 static void             mib_get_constants(mib_item_t *item);
 152 static mib_item_t       *mib_item_dup(mib_item_t *item);
 153 static mib_item_t       *mib_item_diff(mib_item_t *item1,
 154     mib_item_t *item2);
 155 static void             mib_item_destroy(mib_item_t **item);
 156 
 157 static boolean_t        octetstrmatch(const Octet_t *a, const Octet_t *b);
 158 static char             *octetstr(const Octet_t *op, int code,
 159                             char *dst, uint_t dstlen);
 160 static char             *pr_addr(uint_t addr,
 161                             char *dst, uint_t dstlen);
 162 static char             *pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
 163 static char             *pr_addr6(const in6_addr_t *addr,
 164                             char *dst, uint_t dstlen);
 165 static char             *pr_mask(uint_t addr,
 166                             char *dst, uint_t dstlen);
 167 static char             *pr_prefix6(const struct in6_addr *addr,


 184                             const mib2_transportMLPEntry_t *attr);
 185 
 186 static void             stat_report(mib_item_t *item);
 187 static void             mrt_stat_report(mib_item_t *item);
 188 static void             arp_report(mib_item_t *item);
 189 static void             ndp_report(mib_item_t *item);
 190 static void             mrt_report(mib_item_t *item);
 191 static void             if_stat_total(struct ifstat *oldstats,
 192                             struct ifstat *newstats, struct ifstat *sumstats);
 193 static void             if_report(mib_item_t *item, char *ifname,
 194                             int Iflag_only, boolean_t once_only);
 195 static void             if_report_ip4(mib2_ipAddrEntry_t *ap,
 196                             char ifname[], char logintname[],
 197                             struct ifstat *statptr, boolean_t ksp_not_null);
 198 static void             if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
 199                             char ifname[], char logintname[],
 200                             struct ifstat *statptr, boolean_t ksp_not_null);
 201 static void             ire_report(const mib_item_t *item);
 202 static void             tcp_report(const mib_item_t *item);
 203 static void             udp_report(const mib_item_t *item);
 204 static void             uds_report(kstat_ctl_t *);
 205 static void             group_report(mib_item_t *item);
 206 static void             dce_report(mib_item_t *item);
 207 static void             print_ip_stats(mib2_ip_t *ip);
 208 static void             print_icmp_stats(mib2_icmp_t *icmp);
 209 static void             print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
 210 static void             print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
 211 static void             print_sctp_stats(mib2_sctp_t *tcp);
 212 static void             print_tcp_stats(mib2_tcp_t *tcp);
 213 static void             print_udp_stats(mib2_udp_t *udp);
 214 static void             print_rawip_stats(mib2_rawip_t *rawip);
 215 static void             print_igmp_stats(struct igmpstat *igps);
 216 static void             print_mrt_stats(struct mrtstat *mrts);
 217 static void             sctp_report(const mib_item_t *item);
 218 static void             sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
 219                             mib2_ipv6IfStatsEntry_t *sum6);
 220 static void             sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
 221                             mib2_ipv6IfIcmpEntry_t *sum6);
 222 static void             m_report(void);
 223 static void             dhcp_report(char *);
 224 
 225 static  uint64_t        kstat_named_value(kstat_t *, char *);
 226 static  kid_t           safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
 227 static int              isnum(char *);
 228 static char             *plural(int n);
 229 static char             *pluraly(int n);
 230 static char             *plurales(int n);
 231 static void             process_filter(char *arg);
 232 static char             *ifindex2str(uint_t, char *);
 233 static boolean_t        family_selected(int family);
 234 
 235 static void             usage(char *);
 236 static char             *get_username(uid_t);
 237 proc_info_t             *get_proc_info(pid_t);
 238 static void             fatal(int errcode, char *str1, ...);
 239 
 240 #define PLURAL(n) plural((int)n)
 241 #define PLURALY(n) pluraly((int)n)
 242 #define PLURALES(n) plurales((int)n)
 243 #define IFLAGMOD(flg, val1, val2)       if (flg == val1) flg = val2
 244 #define MDIFF(diff, elem2, elem1, member)       (diff)->member = \
 245         (elem2)->member - (elem1)->member
 246 
 247 
 248 static  boolean_t       Aflag = B_FALSE;        /* All sockets/ifs/rtng-tbls */
 249 static  boolean_t       Dflag = B_FALSE;        /* DCE info */
 250 static  boolean_t       Iflag = B_FALSE;        /* IP Traffic Interfaces */
 251 static  boolean_t       Mflag = B_FALSE;        /* STREAMS Memory Statistics */
 252 static  boolean_t       Nflag = B_FALSE;        /* Numeric Network Addresses */
 253 static  boolean_t       Rflag = B_FALSE;        /* Routing Tables */
 254 static  boolean_t       RSECflag = B_FALSE;     /* Security attributes */
 255 static  boolean_t       Sflag = B_FALSE;        /* Per-protocol Statistics */
 256 static  boolean_t       Vflag = B_FALSE;        /* Verbose */
 257 static  boolean_t       Uflag = B_FALSE;        /* Show PID and UID info. */
 258 static  boolean_t       Pflag = B_FALSE;        /* Net to Media Tables */
 259 static  boolean_t       Gflag = B_FALSE;        /* Multicast group membership */
 260 static  boolean_t       MMflag = B_FALSE;       /* Multicast routing table */
 261 static  boolean_t       DHCPflag = B_FALSE;     /* DHCP statistics */
 262 static  boolean_t       Xflag = B_FALSE;        /* Debug Info */
 263 
 264 static  int     v4compat = 0;   /* Compatible printing format for status */
 265 
 266 static int      proto = IPPROTO_MAX;    /* all protocols */
 267 kstat_ctl_t     *kc = NULL;
 268 
 269 /*
 270  * Sizes of data structures extracted from the base mib.
 271  * This allows the size of the tables entries to grow while preserving
 272  * binary compatibility.
 273  */
 274 static int ipAddrEntrySize;
 275 static int ipRouteEntrySize;
 276 static int ipNetToMediaEntrySize;
 277 static int ipMemberEntrySize;


 382          *  1, IFlag is the only feature-flag enabled
 383          * : trinary variable, modified using IFLAGMOD()
 384          */
 385         int Iflag_only = -1;
 386         boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
 387         extern char     *optarg;
 388         extern int      optind;
 389         char *default_ip_str = NULL;
 390 
 391         name = argv[0];
 392 
 393         v4compat = get_compat_flag(&default_ip_str);
 394         if (v4compat == DEFAULT_PROT_BAD_VALUE)
 395                 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
 396                     default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
 397         free(default_ip_str);
 398 
 399         (void) setlocale(LC_ALL, "");
 400         (void) textdomain(TEXT_DOMAIN);
 401 
 402         while ((c = getopt(argc, argv, "adimnrspMgvuxf:P:I:DRT:")) != -1) {
 403                 switch ((char)c) {
 404                 case 'a':               /* all connections */
 405                         Aflag = B_TRUE;
 406                         break;
 407 
 408                 case 'd':               /* DCE info */
 409                         Dflag = B_TRUE;
 410                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 411                         break;
 412 
 413                 case 'i':               /* interface (ill/ipif report) */
 414                         Iflag = B_TRUE;
 415                         IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
 416                         break;
 417 
 418                 case 'm':               /* streams msg report */
 419                         Mflag = B_TRUE;
 420                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 421                         break;
 422 


 442                 case 'p':               /* arp/ndp table */
 443                         Pflag = B_TRUE;
 444                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 445                         break;
 446 
 447                 case 'M':               /* multicast routing tables */
 448                         MMflag = B_TRUE;
 449                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 450                         break;
 451 
 452                 case 'g':               /* multicast group membership */
 453                         Gflag = B_TRUE;
 454                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 455                         break;
 456 
 457                 case 'v':               /* verbose output format */
 458                         Vflag = B_TRUE;
 459                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 460                         break;
 461 
 462                 case 'u':               /* show pid and uid information */
 463                         Uflag = B_TRUE;
 464                         break;
 465 
 466                 case 'x':               /* turn on debugging */
 467                         Xflag = B_TRUE;
 468                         break;
 469 
 470                 case 'f':
 471                         process_filter(optarg);
 472                         break;
 473 
 474                 case 'P':
 475                         if (strcmp(optarg, "ip") == 0) {
 476                                 proto = IPPROTO_IP;
 477                         } else if (strcmp(optarg, "ipv6") == 0 ||
 478                             strcmp(optarg, "ip6") == 0) {
 479                                 v4compat = 0;   /* Overridden */
 480                                 proto = IPPROTO_IPV6;
 481                         } else if (strcmp(optarg, "icmp") == 0) {
 482                                 proto = IPPROTO_ICMP;
 483                         } else if (strcmp(optarg, "icmpv6") == 0 ||
 484                             strcmp(optarg, "icmp6") == 0) {
 485                                 v4compat = 0;   /* Overridden */


 655                                 if (MMflag)
 656                                         mrt_report(item);
 657                         }
 658                         if (Gflag)
 659                                 group_report(item);
 660                         if (Pflag) {
 661                                 if (family_selected(AF_INET))
 662                                         arp_report(item);
 663                                 if (family_selected(AF_INET6))
 664                                         ndp_report(item);
 665                         }
 666                         if (Dflag)
 667                                 dce_report(item);
 668                         mib_item_destroy(&curritem);
 669                 }
 670 
 671                 /* netstat: AF_UNIX behaviour */
 672                 if (family_selected(AF_UNIX) &&
 673                     (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
 674                     MMflag || Pflag || Gflag)))
 675                         uds_report(kc);
 676                 (void) kstat_close(kc);
 677 
 678                 /* iteration handling code */
 679                 if (count > 0 && --count == 0)
 680                         break;
 681                 (void) sleep(interval);
 682 
 683                 /* re-populating of data structures */
 684                 if (family_selected(AF_INET) || family_selected(AF_INET6)) {
 685                         if (Sflag) {
 686                                 /* previtem is a cut-down list */
 687                                 previtem = mib_item_dup(item);
 688                                 if (previtem == NULL)
 689                                         fatal(1, "can't process mib data, "
 690                                             "out of memory\n");
 691                         }
 692                         mibfree(item);
 693                         (void) close(sd);
 694                         if ((sd = mibopen()) == -1)
 695                                 fatal(1, "can't open mib stream anymore\n");


 973                             item->length);
 974                         tempp = &(localp[c]);
 975                         if (c > 0)
 976                                 (localp[c - 1]).next_item = tempp;
 977                         c++;
 978                 }
 979         }
 980         return (localp);
 981 }
 982 
 983 /*
 984  * mib_item_diff: takes two (mib_item_t *) linked lists
 985  * item1 and item2 and computes the difference between
 986  * differentiable values in item2 against item1 for every
 987  * given member of item2; returns an mib_item_t * linked
 988  * list of diff's, or a copy of item2 if item1 is NULL;
 989  * will return NULL if system out of memory; works only
 990  * for item->mib_id == 0
 991  */
 992 static mib_item_t *
 993 mib_item_diff(mib_item_t *item1, mib_item_t *item2)
 994 {
 995         int     nitems  = 0; /* no. of items in item2 */
 996         mib_item_t *tempp2;  /* walking copy of item2 */
 997         mib_item_t *tempp1;  /* walking copy of item1 */
 998         mib_item_t *diffp;
 999         mib_item_t *diffptr; /* walking copy of diffp */
1000         mib_item_t *prevp = NULL;
1001 
1002         if (item1 == NULL) {
1003                 diffp = mib_item_dup(item2);
1004                 return (diffp);
1005         }
1006 
1007         for (tempp2 = item2;
1008             tempp2;
1009             tempp2 = tempp2->next_item) {
1010                 if (tempp2->mib_id == 0)
1011                         switch (tempp2->group) {
1012                         /*
1013                          * upon adding a case here, the same
1014                          * must also be added in the next


1500                         }
1501                 } /* 'for' loop 2 ends */
1502                 tempp1 = NULL;
1503         } /* 'for' loop 1 ends */
1504         tempp2 = NULL;
1505         diffptr--;
1506         diffptr->next_item = NULL;
1507         return (diffp);
1508 
1509 mibdiff_out_of_memory:;
1510         mib_item_destroy(&diffp);
1511         return (NULL);
1512 }
1513 
1514 /*
1515  * mib_item_destroy: cleans up a mib_item_t *
1516  * that was created by calling mib_item_dup or
1517  * mib_item_diff
1518  */
1519 static void
1520 mib_item_destroy(mib_item_t **itemp)
1521 {
1522         int     nitems = 0;
1523         int     c = 0;
1524         mib_item_t *tempp;
1525 
1526         if (itemp == NULL || *itemp == NULL)
1527                 return;
1528 
1529         for (tempp = *itemp; tempp != NULL; tempp = tempp->next_item)
1530                 if (tempp->mib_id == 0)
1531                         nitems++;
1532                 else
1533                         return; /* cannot destroy! */
1534 
1535         if (nitems == 0)
1536                 return;         /* cannot destroy! */
1537 
1538         for (c = nitems - 1; c >= 0; c--) {
1539                 if ((itemp[0][c]).valp != NULL)
1540                         free((itemp[0][c]).valp);
1541         }


3266                                 old6 = new6;
3267                                 cleanlist = oldlist6;
3268                                 oldlist6 = newlist6;
3269                                 while (cleanlist != NULL) {
3270                                         tlp = cleanlist->next_if;
3271                                         free(cleanlist);
3272                                         cleanlist = tlp;
3273                                 }
3274                         }
3275                         break;
3276                 }
3277                 }
3278                 (void) fflush(stdout);
3279         } /* 'for' loop 1 ends */
3280         if ((Iflag_only == 0) && (!once_only))
3281                 (void) putchar('\n');
3282         reentry = B_TRUE;
3283 }
3284 
3285 static void
3286 if_report_ip4(mib2_ipAddrEntry_t *ap, char ifname[], char logintname[],
3287     struct ifstat *statptr, boolean_t ksp_not_null)
3288 {
3289 
3290         char abuf[MAXHOSTNAMELEN + 1];
3291         char dstbuf[MAXHOSTNAMELEN + 1];
3292 
3293         if (ksp_not_null) {
3294                 (void) printf("%-5s %-4u ",
3295                     ifname, ap->ipAdEntInfo.ae_mtu);
3296                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3297                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3298                             abuf, sizeof (abuf));
3299                 else
3300                         (void) pr_netaddr(ap->ipAdEntAddr,
3301                             ap->ipAdEntNetMask, abuf, sizeof (abuf));
3302                 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3303                     "%-6llu %-6llu\n",
3304                     abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3305                     statptr->ipackets, statptr->ierrors,
3306                     statptr->opackets, statptr->oerrors,
3307                     statptr->collisions, 0LL);
3308         }


3314                 statptr->ipackets = ap->ipAdEntInfo.ae_ibcnt;
3315                 statptr->opackets = ap->ipAdEntInfo.ae_obcnt;
3316 
3317                 (void) printf("%-5s %-4u ", logintname, ap->ipAdEntInfo.ae_mtu);
3318                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3319                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr, abuf,
3320                             sizeof (abuf));
3321                 else
3322                         (void) pr_netaddr(ap->ipAdEntAddr, ap->ipAdEntNetMask,
3323                             abuf, sizeof (abuf));
3324 
3325                 (void) printf("%-13s %-14s %-6llu %-5s %-6s "
3326                     "%-5s %-6s %-6llu\n", abuf,
3327                     pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3328                     statptr->ipackets, "N/A", "N/A", "N/A", "N/A",
3329                     0LL);
3330         }
3331 }
3332 
3333 static void
3334 if_report_ip6(mib2_ipv6AddrEntry_t *ap6, char ifname[], char logintname[],
3335     struct ifstat *statptr, boolean_t ksp_not_null)
3336 {
3337 
3338         char abuf[MAXHOSTNAMELEN + 1];
3339         char dstbuf[MAXHOSTNAMELEN + 1];
3340 
3341         if (ksp_not_null) {
3342                 (void) printf("%-5s %-4u ", ifname, ap6->ipv6AddrInfo.ae_mtu);
3343                 if (ap6->ipv6AddrInfo.ae_flags &
3344                     IFF_POINTOPOINT) {
3345                         (void) pr_addr6(&ap6->ipv6AddrInfo.ae_pp_dst_addr,
3346                             abuf, sizeof (abuf));
3347                 } else {
3348                         (void) pr_prefix6(&ap6->ipv6AddrAddress,
3349                             ap6->ipv6AddrPfxLength, abuf,
3350                             sizeof (abuf));
3351                 }
3352                 (void) printf("%-27s %-27s %-6llu %-5llu "
3353                     "%-6llu %-5llu %-6llu\n",
3354                     abuf, pr_addr6(&ap6->ipv6AddrAddress, dstbuf,
3355                     sizeof (dstbuf)),
3356                     statptr->ipackets, statptr->ierrors, statptr->opackets,


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

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

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


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


5725                 (void) puts(">");
5726                 printfirst = B_TRUE;
5727         }
5728         while ((sle = sctp_getnext_local(&local, sle, id)) != NULL) {
5729                 if (!IN6_ARE_ADDR_EQUAL(&sle->sctpAssocLocalAddr,
5730                     &sp->sctpAssocLocPrimAddr)) {
5731                         if (printfirst == B_TRUE) {
5732                                 (void) fputs("\t<Local: ", stdout);
5733                                 printfirst = B_FALSE;
5734                         } else {
5735                                 (void) fputs(", ", stdout);
5736                         }
5737                         sctp_pr_addr(sle->sctpAssocLocalAddrType, lname,
5738                             sizeof (lname), &sle->sctpAssocLocalAddr, -1);
5739                         (void) fputs(lname, stdout);
5740                 }
5741         }
5742         if (printfirst == B_FALSE) {
5743                 (void) puts(">");
5744         }
5745 
5746         return (print_sctp_hdr);
5747 }
5748 
5749 static void
5750 sctp_report(const mib_item_t *item)
5751 {
5752         const mib_item_t                *head;
5753         const mib2_sctpConnEntry_t      *sp;
5754         boolean_t                       print_sctp_hdr_once = B_TRUE;
5755         mib2_transportMLPEntry_t        **attrs, **aptr;
5756         mib2_transportMLPEntry_t        *attr;
5757         conn_pid_info_t                 *cpi;
5758 
5759         /*
5760          * Preparation pass: the kernel returns separate entries for SCTP
5761          * connection table entries and Multilevel Port attributes.  We loop
5762          * through the attributes first and set up an array for each address
5763          * family.
5764          */
5765         attrs = RSECflag ?
5766             gather_attrs(item, MIB2_SCTP, MIB2_SCTP_CONN, sctpEntrySize) :
5767             NULL;
5768 
5769         aptr = attrs;
5770         head = item;
5771         for (; item != NULL; item = item->next_item) {
5772 
5773                 if (!((item->group == MIB2_SCTP &&
5774                     item->mib_id == MIB2_SCTP_CONN) ||
5775                     (item->group == MIB2_SCTP &&
5776                     item->mib_id == EXPER_XPORT_PROC_INFO)))
5777                         continue;
5778 
5779                 if ((!Uflag) && item->group == MIB2_SCTP &&
5780                     item->mib_id == MIB2_SCTP_CONN) {
5781                         for (sp = item->valp;
5782                             (char *)sp < (char *)item->valp + item->length;
5783                             /* LINTED: (note 1) */
5784                             sp = (mib2_sctpConnEntry_t *)((char *)sp +
5785                             sctpEntrySize)) {
5786                                 if (!(Aflag ||
5787                                     sp->sctpAssocState >=
5788                                     MIB2_SCTP_established))
5789                                         continue;
5790                                 attr = aptr == NULL ? NULL : *aptr++;
5791                                 print_sctp_hdr_once = sctp_conn_report_item(
5792                                     head, NULL, print_sctp_hdr_once, sp, attr);




5793                         }
5794                 } else if ((Uflag) && item->group == MIB2_SCTP &&
5795                     item->mib_id == EXPER_XPORT_PROC_INFO) {
5796                         for (sp = (mib2_sctpConnEntry_t *)item->valp;
5797                             (char *)sp < (char *)item->valp + item->length;
5798                             /* LINTED: (note 1) */
5799                             sp = (mib2_sctpConnEntry_t *)((char *)cpi +
5800                             cpi->cpi_tot_size)) {
5801                                 /* LINTED: (note 1) */
5802                                 cpi = (conn_pid_info_t *)((char *)sp +
5803                                     sctpEntrySize);
5804                                 if (!(Aflag ||
5805                                     sp->sctpAssocState >=
5806                                     MIB2_SCTP_established))
5807                                         continue;
5808                                 attr = aptr == NULL ? NULL : *aptr++;
5809                                 print_sctp_hdr_once = sctp_conn_report_item(
5810                                     head, cpi, print_sctp_hdr_once, sp, attr);
5811                         }
5812                 }
5813         }
5814         if (attrs != NULL)
5815                 free(attrs);
5816 }
5817 
5818 static char *
5819 plural(int n)
5820 {
5821         return (n != 1 ? "s" : "");
5822 }
5823 
5824 static char *
5825 pluraly(int n)
5826 {
5827         return (n != 1 ? "ies" : "y");
5828 }
5829 
5830 static char *
5831 plurales(int n)
5832 {
5833         return (n != 1 ? "es" : "");
5834 }
5835 
5836 static char *
5837 pktscale(int n)

5838 {
5839         static char buf[6];
5840         char t;
5841 
5842         if (n < 1024) {
5843                 t = ' ';
5844         } else if (n < 1024 * 1024) {
5845                 t = 'k';
5846                 n /= 1024;
5847         } else if (n < 1024 * 1024 * 1024) {
5848                 t = 'm';
5849                 n /= 1024 * 1024;
5850         } else {
5851                 t = 'g';
5852                 n /= 1024 * 1024 * 1024;
5853         }
5854 
5855         (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5856         return (buf);
5857 }


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