Print this page
XXXX adding PID information to netstat output

@@ -53,18 +53,23 @@
 #include <errno.h>
 #include <ctype.h>
 #include <kstat.h>
 #include <assert.h>
 #include <locale.h>
+#include <pwd.h>
+#include <limits.h>
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/stream.h>
 #include <stropts.h>
 #include <sys/strstat.h>
 #include <sys/tihdr.h>
+#include <procfs.h>
 
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/sockio.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <net/route.h>
 

@@ -89,11 +94,10 @@
 #include <libtsnet.h>
 #include <tsol/label.h>
 
 #include "statcommon.h"
 
-extern void     unixpr(kstat_ctl_t *kc);
 
 #define STR_EXPAND      4
 
 #define V4MASK_TO_V6(v4, v6)    ((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
                                 (v6)._S6_un._S6_u32[1] = 0xfffffffful, \

@@ -133,10 +137,16 @@
         struct iflist   *next_if;
         char            ifname[LIFNAMSIZ];
         struct ifstat   tot;
 };
 
+typedef struct proc_info {
+        char *pr_user;
+        char *pr_fname;
+        char *pr_psargs;
+} proc_info_t;
+
 static  mib_item_t      *mibget(int sd);
 static  void            mibfree(mib_item_t *firstitem);
 static  int             mibopen(void);
 static void             mib_get_constants(mib_item_t *item);
 static mib_item_t       *mib_item_dup(mib_item_t *item);

@@ -189,10 +199,11 @@
                             char ifname[], char logintname[],
                             struct ifstat *statptr, boolean_t ksp_not_null);
 static void             ire_report(const mib_item_t *item);
 static void             tcp_report(const mib_item_t *item);
 static void             udp_report(const mib_item_t *item);
+static void             uds_report(kstat_ctl_t *);
 static void             group_report(mib_item_t *item);
 static void             dce_report(mib_item_t *item);
 static void             print_ip_stats(mib2_ip_t *ip);
 static void             print_icmp_stats(mib2_icmp_t *icmp);
 static void             print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);

@@ -220,10 +231,12 @@
 static void             process_filter(char *arg);
 static char             *ifindex2str(uint_t, char *);
 static boolean_t        family_selected(int family);
 
 static void             usage(char *);
+static char             *get_username(uid_t);
+proc_info_t             *get_proc_info(pid_t);
 static void             fatal(int errcode, char *str1, ...);
 
 #define PLURAL(n) plural((int)n)
 #define PLURALY(n) pluraly((int)n)
 #define PLURALES(n) plurales((int)n)

@@ -239,10 +252,11 @@
 static  boolean_t       Nflag = B_FALSE;        /* Numeric Network Addresses */
 static  boolean_t       Rflag = B_FALSE;        /* Routing Tables */
 static  boolean_t       RSECflag = B_FALSE;     /* Security attributes */
 static  boolean_t       Sflag = B_FALSE;        /* Per-protocol Statistics */
 static  boolean_t       Vflag = B_FALSE;        /* Verbose */
+static  boolean_t       Uflag = B_FALSE;        /* Show PID and UID info. */
 static  boolean_t       Pflag = B_FALSE;        /* Net to Media Tables */
 static  boolean_t       Gflag = B_FALSE;        /* Multicast group membership */
 static  boolean_t       MMflag = B_FALSE;       /* Multicast routing table */
 static  boolean_t       DHCPflag = B_FALSE;     /* DHCP statistics */
 static  boolean_t       Xflag = B_FALSE;        /* Debug Info */

@@ -383,11 +397,11 @@
         free(default_ip_str);
 
         (void) setlocale(LC_ALL, "");
         (void) textdomain(TEXT_DOMAIN);
 
-        while ((c = getopt(argc, argv, "adimnrspMgvxf:P:I:DRT:")) != -1) {
+        while ((c = getopt(argc, argv, "adimnrspMgvuxf:P:I:DRT:")) != -1) {
                 switch ((char)c) {
                 case 'a':               /* all connections */
                         Aflag = B_TRUE;
                         break;
 

@@ -443,10 +457,14 @@
                 case 'v':               /* verbose output format */
                         Vflag = B_TRUE;
                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
                         break;
 
+                case 'u':               /* show pid and uid information */
+                        Uflag = B_TRUE;
+                        break;
+
                 case 'x':               /* turn on debugging */
                         Xflag = B_TRUE;
                         break;
 
                 case 'f':

@@ -652,11 +670,11 @@
 
                 /* netstat: AF_UNIX behaviour */
                 if (family_selected(AF_UNIX) &&
                     (!(Dflag || Iflag || Rflag || Sflag || Mflag ||
                     MMflag || Pflag || Gflag)))
-                        unixpr(kc);
+                        uds_report(kc);
                 (void) kstat_close(kc);
 
                 /* iteration handling code */
                 if (count > 0 && --count == 0)
                         break;

@@ -970,11 +988,12 @@
  * list of diff's, or a copy of item2 if item1 is NULL;
  * will return NULL if system out of memory; works only
  * for item->mib_id == 0
  */
 static mib_item_t *
-mib_item_diff(mib_item_t *item1, mib_item_t *item2) {
+mib_item_diff(mib_item_t *item1, mib_item_t *item2)
+{
         int     nitems  = 0; /* no. of items in item2 */
         mib_item_t *tempp2;  /* walking copy of item2 */
         mib_item_t *tempp1;  /* walking copy of item1 */
         mib_item_t *diffp;
         mib_item_t *diffptr; /* walking copy of diffp */

@@ -1496,11 +1515,12 @@
  * mib_item_destroy: cleans up a mib_item_t *
  * that was created by calling mib_item_dup or
  * mib_item_diff
  */
 static void
-mib_item_destroy(mib_item_t **itemp) {
+mib_item_destroy(mib_item_t **itemp)
+{
         int     nitems = 0;
         int     c = 0;
         mib_item_t *tempp;
 
         if (itemp == NULL || *itemp == NULL)

@@ -3261,13 +3281,13 @@
                 (void) putchar('\n');
         reentry = B_TRUE;
 }
 
 static void
-if_report_ip4(mib2_ipAddrEntry_t *ap,
-        char ifname[], char logintname[], struct ifstat *statptr,
-        boolean_t ksp_not_null) {
+if_report_ip4(mib2_ipAddrEntry_t *ap, char ifname[], char logintname[],
+    struct ifstat *statptr, boolean_t ksp_not_null)
+{
 
         char abuf[MAXHOSTNAMELEN + 1];
         char dstbuf[MAXHOSTNAMELEN + 1];
 
         if (ksp_not_null) {

@@ -3309,13 +3329,13 @@
                     0LL);
         }
 }
 
 static void
-if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
-        char ifname[], char logintname[], struct ifstat *statptr,
-        boolean_t ksp_not_null) {
+if_report_ip6(mib2_ipv6AddrEntry_t *ap6, char ifname[], char logintname[],
+    struct ifstat *statptr, boolean_t ksp_not_null)
+{
 
         char abuf[MAXHOSTNAMELEN + 1];
         char dstbuf[MAXHOSTNAMELEN + 1];
 
         if (ksp_not_null) {

@@ -4740,10 +4760,20 @@
 static const char tcp_hdr_v4_normal[] =
 "   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q "
 "   State\n"
 "-------------------- -------------------- ----- ------ ----- ------ "
 "-----------\n";
+static const char tcp_hdr_v4_pid[] =
+"   Local Address        Remote Address      User     Pid     Command     Swind"
+"   Send-Q  Rwind  Recv-Q    State\n"
+"-------------------- -------------------- -------- ------ ------------- ------"
+"- ------ ------- ------ -----------\n";
+static const char tcp_hdr_v4_pid_verbose[] =
+"Local/Remote Address  Swind   Snext     Suna    Rwind   Rnext     Rack    Rto "
+"  Mss     State      User    Pid      Command\n"
+"-------------------- ------- -------- -------- ------- -------- -------- -----"
+" ----- ----------- -------- ------ --------------\n";
 
 static const char tcp_hdr_v6[] =
 "\nTCP: IPv6\n";
 static const char tcp_hdr_v6_verbose[] =
 "Local/Remote Address              Swind  Snext     Suna   Rwind  Rnext   "

@@ -4753,15 +4783,28 @@
 static const char tcp_hdr_v6_normal[] =
 "   Local Address                     Remote Address                 "
 "Swind Send-Q Rwind Recv-Q   State      If\n"
 "--------------------------------- --------------------------------- "
 "----- ------ ----- ------ ----------- -----\n";
+static const char tcp_hdr_v6_pid[] =
+"   Local Address                     Remote Address                   User"
+"    Pid      Command      Swind  Send-Q  Rwind  Recv-Q   State      If\n"
+"--------------------------------- --------------------------------- --------"
+" ------ -------------- ------- ------ ------- ------ ----------- -----\n";
+static const char tcp_hdr_v6_pid_verbose[] =
+"Local/Remote Address               Swind   Snext     Suna    Rwind   Rnext"
+"     Rack    Rto   Mss    State      If     User    Pid     Command\n"
+"--------------------------------- ------- -------- -------- ------- --------"
+" -------- ----- ----- ----------- ----- -------- ------ --------------\n";
 
 static boolean_t tcp_report_item_v4(const mib2_tcpConnEntry_t *,
-    boolean_t first, const mib2_transportMLPEntry_t *);
+    conn_pid_info_t *, boolean_t first,
+    const mib2_transportMLPEntry_t *);
 static boolean_t tcp_report_item_v6(const mib2_tcp6ConnEntry_t *,
-    boolean_t first, const mib2_transportMLPEntry_t *);
+    conn_pid_info_t *, boolean_t first,
+    const mib2_transportMLPEntry_t *);
+
 
 static void
 tcp_report(const mib_item_t *item)
 {
         int                     jtemp = 0;

@@ -4770,10 +4813,11 @@
         mib2_tcpConnEntry_t     *tp;
         mib2_tcp6ConnEntry_t    *tp6;
         mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
         mib2_transportMLPEntry_t **v4a, **v6a;
         mib2_transportMLPEntry_t *aptr;
+        conn_pid_info_t                 *cpi;
 
         if (!protocol_selected(IPPROTO_TCP))
                 return;
 
         /*

@@ -4802,69 +4846,110 @@
                 }
 
                 if (!((item->group == MIB2_TCP &&
                     item->mib_id == MIB2_TCP_CONN) ||
                     (item->group == MIB2_TCP6 &&
-                    item->mib_id == MIB2_TCP6_CONN)))
+                    item->mib_id == MIB2_TCP6_CONN) ||
+                    (item->group == MIB2_TCP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) ||
+                    (item->group == MIB2_TCP6 &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO)))
                         continue; /* 'for' loop 1 */
 
                 if (item->group == MIB2_TCP && !family_selected(AF_INET))
                         continue; /* 'for' loop 1 */
                 else if (item->group == MIB2_TCP6 && !family_selected(AF_INET6))
                         continue; /* 'for' loop 1 */
 
-                if (item->group == MIB2_TCP) {
+                if ((!Uflag) && item->group == MIB2_TCP &&
+                    item->mib_id == MIB2_TCP_CONN) {
                         for (tp = (mib2_tcpConnEntry_t *)item->valp;
                             (char *)tp < (char *)item->valp + item->length;
                             /* LINTED: (note 1) */
                             tp = (mib2_tcpConnEntry_t *)((char *)tp +
                             tcpConnEntrySize)) {
                                 aptr = v4a == NULL ? NULL : *v4a++;
                                 print_hdr_once_v4 = tcp_report_item_v4(tp,
-                                    print_hdr_once_v4, aptr);
+                                    NULL, print_hdr_once_v4, aptr);
                         }
-                } else {
+                } else if ((!Uflag) && item->group == MIB2_TCP6 &&
+                    item->mib_id == MIB2_TCP6_CONN) {
                         for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
                             (char *)tp6 < (char *)item->valp + item->length;
                             /* LINTED: (note 1) */
                             tp6 = (mib2_tcp6ConnEntry_t *)((char *)tp6 +
                             tcp6ConnEntrySize)) {
                                 aptr = v6a == NULL ? NULL : *v6a++;
                                 print_hdr_once_v6 = tcp_report_item_v6(tp6,
-                                    print_hdr_once_v6, aptr);
+                                    NULL, print_hdr_once_v6, aptr);
+                        }
+                } else if ((Uflag) && item->group == MIB2_TCP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) {
+                        for (tp = (mib2_tcpConnEntry_t *)item->valp;
+                            (char *)tp < (char *)item->valp + item->length;
+                            /* LINTED: (note 1) */
+                            tp = (mib2_tcpConnEntry_t *)((char *)cpi +
+                            cpi->cpi_tot_size)) {
+                                aptr = v4a == NULL ? NULL : *v4a++;
+                                /* LINTED: (note 1) */
+                                cpi = (conn_pid_info_t *)((char *)tp +
+                                    tcpConnEntrySize);
+                                print_hdr_once_v4 = tcp_report_item_v4(tp,
+                                    cpi, print_hdr_once_v4, aptr);
+                        }
+                } else if ((Uflag) && item->group == MIB2_TCP6 &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) {
+                        for (tp6 = (mib2_tcp6ConnEntry_t *)item->valp;
+                            (char *)tp6 < (char *)item->valp + item->length;
+                            /* LINTED: (note 1) */
+                            tp6 = (mib2_tcp6ConnEntry_t *)((char *)cpi +
+                            cpi->cpi_tot_size)) {
+                                aptr = v6a == NULL ? NULL : *v6a++;
+                                /* LINTED: (note 1) */
+                                cpi = (conn_pid_info_t *)((char *)tp6 +
+                                    tcp6ConnEntrySize);
+                                print_hdr_once_v6 = tcp_report_item_v6(tp6,
+                                    cpi, print_hdr_once_v6, aptr);
                         }
                 }
+
         } /* 'for' loop 1 ends */
         (void) fflush(stdout);
 
         if (v4_attrs != NULL)
                 free(v4_attrs);
         if (v6_attrs != NULL)
                 free(v6_attrs);
 }
 
 static boolean_t
-tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first,
-    const mib2_transportMLPEntry_t *attr)
+tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, conn_pid_info_t *cpi,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
         /*
          * lname and fname below are for the hostname as well as the portname
          * There is no limit on portname length so we assume MAXHOSTNAMELEN
          * as the limit
          */
         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
         char    fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 
+
         if (!(Aflag || tp->tcpConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
                 return (first); /* Nothing to print */
 
         if (first) {
                 (void) printf(v4compat ? tcp_hdr_v4_compat : tcp_hdr_v4);
-                (void) printf(Vflag ? tcp_hdr_v4_verbose : tcp_hdr_v4_normal);
+                if (Uflag)
+                        (void) printf(Vflag ? tcp_hdr_v4_pid_verbose :
+                            tcp_hdr_v4_pid);
+                else
+                        (void) printf(Vflag ? tcp_hdr_v4_verbose :
+                            tcp_hdr_v4_normal);
         }
 
-        if (Vflag) {
+        if ((!Uflag) && Vflag) {
                 (void) printf("%-20s\n%-20s %5u %08x %08x %5u %08x %08x "
                     "%5u %5u %s\n",
                     pr_ap(tp->tcpConnLocalAddress,
                     tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
                     pr_ap(tp->tcpConnRemAddress,

@@ -4876,11 +4961,11 @@
                     tp->tcpConnEntryInfo.ce_rnxt,
                     tp->tcpConnEntryInfo.ce_rack,
                     tp->tcpConnEntryInfo.ce_rto,
                     tp->tcpConnEntryInfo.ce_mss,
                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
-        } else {
+        } else if ((!Uflag) && (!Vflag)) {
                 int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
                     (int)tp->tcpConnEntryInfo.ce_suna - 1;
                 int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
                     (int)tp->tcpConnEntryInfo.ce_rack;
 

@@ -4892,20 +4977,68 @@
                     tp->tcpConnEntryInfo.ce_swnd,
                     (sq >= 0) ? sq : 0,
                     tp->tcpConnEntryInfo.ce_rwnd,
                     (rq >= 0) ? rq : 0,
                     mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
+        } else if (Uflag && Vflag) {
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-20s\n%-20s %7u %08x %08x %7u %08x "
+                            "%08x %5u %5u %-11s %-8.8s %6u %s\n",
+                            pr_ap(tp->tcpConnLocalAddress,
+                            tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
+                            pr_ap(tp->tcpConnRemAddress,
+                            tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
+                            tp->tcpConnEntryInfo.ce_swnd,
+                            tp->tcpConnEntryInfo.ce_snxt,
+                            tp->tcpConnEntryInfo.ce_suna,
+                            tp->tcpConnEntryInfo.ce_rwnd,
+                            tp->tcpConnEntryInfo.ce_rnxt,
+                            tp->tcpConnEntryInfo.ce_rack,
+                            tp->tcpConnEntryInfo.ce_rto,
+                            tp->tcpConnEntryInfo.ce_mss,
+                            mitcp_state(tp->tcpConnEntryInfo.ce_state, attr),
+                            pinfo->pr_user, (int)*pids, pinfo->pr_psargs);
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
+        } else if (Uflag && (!Vflag)) {
+                int sq = (int)tp->tcpConnEntryInfo.ce_snxt -
+                    (int)tp->tcpConnEntryInfo.ce_suna - 1;
+                int rq = (int)tp->tcpConnEntryInfo.ce_rnxt -
+                    (int)tp->tcpConnEntryInfo.ce_rack;
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-20s %-20s %-8.8s %6u %-13.13s %7u "
+                            "%6d %7u %6d %s\n",
+                            pr_ap(tp->tcpConnLocalAddress,
+                            tp->tcpConnLocalPort, "tcp", lname, sizeof (lname)),
+                            pr_ap(tp->tcpConnRemAddress,
+                            tp->tcpConnRemPort, "tcp", fname, sizeof (fname)),
+                            pinfo->pr_user, (int)*pids, pinfo->pr_fname,
+                            tp->tcpConnEntryInfo.ce_swnd,
+                            (sq >= 0) ? sq : 0,
+                            tp->tcpConnEntryInfo.ce_rwnd,
+                            (rq >= 0) ? rq : 0,
+                            mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
         }
 
         print_transport_label(attr);
 
         return (B_FALSE);
 }
 
 static boolean_t
-tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first,
-    const mib2_transportMLPEntry_t *attr)
+tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, conn_pid_info_t *cpi,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
         /*
          * lname and fname below are for the hostname as well as the portname
          * There is no limit on portname length so we assume MAXHOSTNAMELEN
          * as the limit

@@ -4918,19 +5051,24 @@
         if (!(Aflag || tp6->tcp6ConnEntryInfo.ce_state >= TCPS_ESTABLISHED))
                 return (first); /* Nothing to print */
 
         if (first) {
                 (void) printf(tcp_hdr_v6);
-                (void) printf(Vflag ? tcp_hdr_v6_verbose : tcp_hdr_v6_normal);
+                if (Uflag)
+                        (void) printf(Vflag ? tcp_hdr_v6_pid_verbose :
+                            tcp_hdr_v6_pid);
+                else
+                        (void) printf(Vflag ? tcp_hdr_v6_verbose :
+                            tcp_hdr_v6_normal);
         }
 
         ifnamep = (tp6->tcp6ConnIfIndex != 0) ?
             if_indextoname(tp6->tcp6ConnIfIndex, ifname) : NULL;
         if (ifnamep == NULL)
                 ifnamep = "";
 
-        if (Vflag) {
+        if ((!Uflag) && Vflag) {
                 (void) printf("%-33s\n%-33s %5u %08x %08x %5u %08x %08x "
                     "%5u %5u %-11s %s\n",
                     pr_ap6(&tp6->tcp6ConnLocalAddress,
                     tp6->tcp6ConnLocalPort, "tcp", lname, sizeof (lname)),
                     pr_ap6(&tp6->tcp6ConnRemAddress,

@@ -4943,11 +5081,11 @@
                     tp6->tcp6ConnEntryInfo.ce_rack,
                     tp6->tcp6ConnEntryInfo.ce_rto,
                     tp6->tcp6ConnEntryInfo.ce_mss,
                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
                     ifnamep);
-        } else {
+        } else if ((!Uflag) && (!Vflag)) {
                 int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
                     (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
                 int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
                     (int)tp6->tcp6ConnEntryInfo.ce_rack;
 

@@ -4960,33 +5098,109 @@
                     (sq >= 0) ? sq : 0,
                     tp6->tcp6ConnEntryInfo.ce_rwnd,
                     (rq >= 0) ? rq : 0,
                     mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
                     ifnamep);
+        } else if (Uflag && Vflag) {
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-33s\n%-33s %7u %08x %08x %7u %08x "
+                            "%08x %5u %5u %-11s %-5.5s %-8.8s %6u %s\n",
+                            pr_ap6(&tp6->tcp6ConnLocalAddress,
+                            tp6->tcp6ConnLocalPort, "tcp", lname,
+                            sizeof (lname)),
+                            pr_ap6(&tp6->tcp6ConnRemAddress,
+                            tp6->tcp6ConnRemPort, "tcp", fname,
+                            sizeof (fname)),
+                            tp6->tcp6ConnEntryInfo.ce_swnd,
+                            tp6->tcp6ConnEntryInfo.ce_snxt,
+                            tp6->tcp6ConnEntryInfo.ce_suna,
+                            tp6->tcp6ConnEntryInfo.ce_rwnd,
+                            tp6->tcp6ConnEntryInfo.ce_rnxt,
+                            tp6->tcp6ConnEntryInfo.ce_rack,
+                            tp6->tcp6ConnEntryInfo.ce_rto,
+                            tp6->tcp6ConnEntryInfo.ce_mss,
+                            mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
+                            ifnamep, pinfo->pr_user, (int)*pids,
+                            pinfo->pr_psargs);
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
+        } else if (Uflag && (!Vflag)) {
+                int sq = (int)tp6->tcp6ConnEntryInfo.ce_snxt -
+                    (int)tp6->tcp6ConnEntryInfo.ce_suna - 1;
+                int rq = (int)tp6->tcp6ConnEntryInfo.ce_rnxt -
+                    (int)tp6->tcp6ConnEntryInfo.ce_rack;
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-33s %-33s %-8.8s %6u %-14.14s %7d "
+                            "%6u %7d %6d %-11s %s\n",
+                            pr_ap6(&tp6->tcp6ConnLocalAddress,
+                            tp6->tcp6ConnLocalPort, "tcp", lname,
+                            sizeof (lname)),
+                            pr_ap6(&tp6->tcp6ConnRemAddress,
+                            tp6->tcp6ConnRemPort, "tcp", fname, sizeof (fname)),
+                            pinfo->pr_user, (int)*pids, pinfo->pr_fname,
+                            tp6->tcp6ConnEntryInfo.ce_swnd,
+                            (sq >= 0) ? sq : 0,
+                            tp6->tcp6ConnEntryInfo.ce_rwnd,
+                            (rq >= 0) ? rq : 0,
+                            mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
+                            ifnamep);
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
         }
 
         print_transport_label(attr);
 
         return (B_FALSE);
 }
 
 /* ------------------------------- UDP_REPORT------------------------------- */
 
 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
-    boolean_t first, const mib2_transportMLPEntry_t *attr);
+    conn_pid_info_t *cpi, boolean_t first,
+    const mib2_transportMLPEntry_t *attr);
 static boolean_t udp_report_item_v6(const mib2_udp6Entry_t *ude6,
-    boolean_t first, const mib2_transportMLPEntry_t *attr);
+    conn_pid_info_t *cpi, boolean_t first,
+    const mib2_transportMLPEntry_t *attr);
 
 static const char udp_hdr_v4[] =
 "   Local Address        Remote Address      State\n"
 "-------------------- -------------------- ----------\n";
+static const char udp_hdr_v4_pid[] =
+"   Local Address        Remote Address      User    Pid   "
+"   Command       State\n"
+"-------------------- -------------------- -------- ------ "
+"-------------- ----------\n";
+static const char udp_hdr_v4_pid_verbose[] =
+"   Local Address        Remote Address      User    Pid     State    "
+"   Command\n"
+"-------------------- -------------------- -------- ------ ---------- "
+"----------------\n";
 
 static const char udp_hdr_v6[] =
 "   Local Address                     Remote Address                 "
 "  State      If\n"
 "--------------------------------- --------------------------------- "
 "---------- -----\n";
+static const char udp_hdr_v6_pid[] =
+"   Local Address                     Remote Address                 "
+"  User    Pid      Command       State      If\n"
+"--------------------------------- --------------------------------- "
+"-------- ------ -------------- ---------- -----\n";
+static const char udp_hdr_v6_pid_verbose[] =
+"   Local Address                     Remote Address                 "
+"  User    Pid     State      If     Command\n"
+"--------------------------------- --------------------------------- "
+"-------- ------ ---------- ----- ----------------\n";
+
 
 static void
 udp_report(const mib_item_t *item)
 {
         int                     jtemp = 0;

@@ -4995,10 +5209,11 @@
         mib2_udpEntry_t         *ude;
         mib2_udp6Entry_t        *ude6;
         mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
         mib2_transportMLPEntry_t **v4a, **v6a;
         mib2_transportMLPEntry_t *aptr;
+        conn_pid_info_t                 *cpi;
 
         if (!protocol_selected(IPPROTO_UDP))
                 return;
 
         /*

@@ -5025,38 +5240,72 @@
                             item->length, item->valp);
                 }
                 if (!((item->group == MIB2_UDP &&
                     item->mib_id == MIB2_UDP_ENTRY) ||
                     (item->group == MIB2_UDP6 &&
-                    item->mib_id == MIB2_UDP6_ENTRY)))
+                    item->mib_id == MIB2_UDP6_ENTRY) ||
+                    (item->group == MIB2_UDP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) ||
+                    (item->group == MIB2_UDP6 &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO)))
                         continue; /* 'for' loop 1 */
 
                 if (item->group == MIB2_UDP && !family_selected(AF_INET))
                         continue; /* 'for' loop 1 */
                 else if (item->group == MIB2_UDP6 && !family_selected(AF_INET6))
                         continue; /* 'for' loop 1 */
 
                 /*      xxx.xxx.xxx.xxx,pppp  sss... */
-                if (item->group == MIB2_UDP) {
+                if ((!Uflag) && item->group == MIB2_UDP &&
+                    item->mib_id == MIB2_UDP_ENTRY) {
                         for (ude = (mib2_udpEntry_t *)item->valp;
                             (char *)ude < (char *)item->valp + item->length;
                             /* LINTED: (note 1) */
                             ude = (mib2_udpEntry_t *)((char *)ude +
                             udpEntrySize)) {
                                 aptr = v4a == NULL ? NULL : *v4a++;
                                 print_hdr_once_v4 = udp_report_item_v4(ude,
-                                    print_hdr_once_v4, aptr);
+                                    NULL, print_hdr_once_v4, aptr);
                         }
-                } else {
+                } else if ((!Uflag) && item->group == MIB2_UDP6 &&
+                    item->mib_id == MIB2_UDP6_ENTRY) {
                         for (ude6 = (mib2_udp6Entry_t *)item->valp;
                             (char *)ude6 < (char *)item->valp + item->length;
                             /* LINTED: (note 1) */
                             ude6 = (mib2_udp6Entry_t *)((char *)ude6 +
                             udp6EntrySize)) {
                                 aptr = v6a == NULL ? NULL : *v6a++;
                                 print_hdr_once_v6 = udp_report_item_v6(ude6,
-                                    print_hdr_once_v6, aptr);
+                                    NULL, print_hdr_once_v6, aptr);
+                        }
+                } else if ((Uflag) && item->group == MIB2_UDP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) {
+                        for (ude = (mib2_udpEntry_t *)item->valp;
+                            (char *)ude < (char *)item->valp + item->length;
+                            /* LINTED: (note 1) */
+                            ude = (mib2_udpEntry_t *)((char *)cpi +
+                            cpi->cpi_tot_size)) {
+                                aptr = v4a == NULL ? NULL : *v4a++;
+                                /* LINTED: (note 1) */
+                                cpi = (conn_pid_info_t *)((char *)ude +
+                                    udpEntrySize);
+                                print_hdr_once_v4 = udp_report_item_v4(ude,
+                                    cpi, print_hdr_once_v4, aptr);
+                        }
+                } else if ((Uflag) && item->group == MIB2_UDP6 &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) {
+                        for (ude6 = (mib2_udp6Entry_t *)item->valp;
+                            (char *)ude6 < (char *)item->valp + item->length;
+                            /* LINTED: (note 1) */
+                            ude6 = (mib2_udp6Entry_t *)((char *)cpi +
+                            cpi->cpi_tot_size)) {
+                                aptr = v6a == NULL ? NULL : *v6a++;
+                                /* LINTED: (note 1) */
+                                cpi = (conn_pid_info_t *)((char *)ude6 +
+                                    udp6EntrySize);
+                                print_hdr_once_v6 = udp_report_item_v6(ude6,
+                                    cpi, print_hdr_once_v6, aptr);
                         }
                 }
         } /* 'for' loop 1 ends */
         (void) fflush(stdout);
 

@@ -5065,43 +5314,71 @@
         if (v6_attrs != NULL)
                 free(v6_attrs);
 }
 
 static boolean_t
-udp_report_item_v4(const mib2_udpEntry_t *ude, boolean_t first,
-    const mib2_transportMLPEntry_t *attr)
+udp_report_item_v4(const mib2_udpEntry_t *ude, conn_pid_info_t *cpi,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
                         /* hostname + portname */
 
         if (!(Aflag || ude->udpEntryInfo.ue_state >= MIB2_UDP_connected))
                 return (first); /* Nothing to print */
 
         if (first) {
                 (void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
+
+                if (Uflag)
+                        (void) printf(Vflag ? udp_hdr_v4_pid_verbose :
+                            udp_hdr_v4_pid);
+                else
                 (void) printf(udp_hdr_v4);
+
                 first = B_FALSE;
         }
 
-        (void) printf("%-20s ",
+        (void) printf("%-20s %-20s ",
             pr_ap(ude->udpLocalAddress, ude->udpLocalPort, "udp",
-            lname, sizeof (lname)));
-        (void) printf("%-20s %s\n",
+            lname, sizeof (lname)),
             ude->udpEntryInfo.ue_state == MIB2_UDP_connected ?
             pr_ap(ude->udpEntryInfo.ue_RemoteAddress,
             ude->udpEntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
-            "",
+            "");
+        if (!Uflag) {
+                (void) printf("%s\n",
             miudp_state(ude->udpEntryInfo.ue_state, attr));
+        } else {
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-8.8s %6u ", pinfo->pr_user,
+                            (int)*pids);
+                        if (Vflag) {
+                                (void) printf("%-10.10s %s\n",
+                                    miudp_state(ude->udpEntryInfo.ue_state,
+                                    attr),
+                                    pinfo->pr_psargs);
+                        } else {
+                                (void) printf("%-14.14s %s\n", pinfo->pr_fname,
+                                    miudp_state(ude->udpEntryInfo.ue_state,
+                                    attr));
+                        }
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
+        }
 
         print_transport_label(attr);
 
         return (first);
 }
 
 static boolean_t
-udp_report_item_v6(const mib2_udp6Entry_t *ude6, boolean_t first,
-    const mib2_transportMLPEntry_t *attr)
+udp_report_item_v6(const mib2_udp6Entry_t *ude6, conn_pid_info_t *cpi,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
         char    lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
                         /* hostname + portname */
         char    ifname[LIFNAMSIZ + 1];
         const char *ifnamep;

@@ -5109,27 +5386,58 @@
         if (!(Aflag || ude6->udp6EntryInfo.ue_state >= MIB2_UDP_connected))
                 return (first); /* Nothing to print */
 
         if (first) {
                 (void) printf("\nUDP: IPv6\n");
+
+                if (Uflag)
+                        (void) printf(Vflag ? udp_hdr_v6_pid_verbose :
+                            udp_hdr_v6_pid);
+                else
                 (void) printf(udp_hdr_v6);
+
                 first = B_FALSE;
         }
 
         ifnamep = (ude6->udp6IfIndex != 0) ?
             if_indextoname(ude6->udp6IfIndex, ifname) : NULL;
 
-        (void) printf("%-33s ",
+        (void) printf("%-33s %-33s ",
             pr_ap6(&ude6->udp6LocalAddress,
-            ude6->udp6LocalPort, "udp", lname, sizeof (lname)));
-        (void) printf("%-33s %-10s %s\n",
+            ude6->udp6LocalPort, "udp", lname, sizeof (lname)),
             ude6->udp6EntryInfo.ue_state == MIB2_UDP_connected ?
             pr_ap6(&ude6->udp6EntryInfo.ue_RemoteAddress,
             ude6->udp6EntryInfo.ue_RemotePort, "udp", lname, sizeof (lname)) :
-            "",
+            "");
+        if (!Uflag) {
+                (void) printf("%-10s %s\n",
             miudp_state(ude6->udp6EntryInfo.ue_state, attr),
             ifnamep == NULL ? "" : ifnamep);
+        } else {
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-8.8s %6u ", pinfo->pr_user,
+                            (int)*pids);
+                        if (Vflag) {
+                                (void) printf("%-10.10s %-5.5s %s\n",
+                                    miudp_state(ude6->udp6EntryInfo.ue_state,
+                                    attr),
+                                    ifnamep == NULL ? "" : ifnamep,
+                                    pinfo->pr_psargs);
+                        } else {
+                                (void) printf("%-14.14s %-10.10s %s\n",
+                                    pinfo->pr_fname,
+                                    miudp_state(ude6->udp6EntryInfo.ue_state,
+                                    attr),
+                                    ifnamep == NULL ? "" : ifnamep);
+                        }
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
+        }
 
         print_transport_label(attr);
 
         return (first);
 }

@@ -5141,10 +5449,20 @@
 static const char sctp_hdr_normal[] =
 "        Local Address                   Remote Address          "
 "Swind  Send-Q Rwind  Recv-Q StrsI/O  State\n"
 "------------------------------- ------------------------------- "
 "------ ------ ------ ------ ------- -----------";
+static const char sctp_hdr_pid[] =
+"        Local Address                   Remote Address          "
+"Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid      Command      State\n"
+"------------------------------- ------------------------------- ------ "
+"------ ------ ------ ------- -------- ------ -------------- -----------";
+static const char sctp_hdr_pid_verbose[] =
+"        Local Address                   Remote Address          "
+"Swind  Send-Q Rwind  Recv-Q StrsI/O   User    Pid    State         Command\n"
+"------------------------------- ------------------------------- ------ "
+"------ ------ ------ ------- -------- ------ ----------- --------------";
 
 static const char *
 nssctp_state(int state, const mib2_transportMLPEntry_t *attr)
 {
         static char sctpsbuf[50];

@@ -5307,12 +5625,13 @@
                 (void) snprintf(name, namelen, "<unknown addr type>");
                 break;
         }
 }
 
-static void
-sctp_conn_report_item(const mib_item_t *head, const mib2_sctpConnEntry_t *sp,
+static boolean_t
+sctp_conn_report_item(const mib_item_t *head, conn_pid_info_t *cpi,
+    boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp,
     const mib2_transportMLPEntry_t *attr)
 {
         char            lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
         char            fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
         const mib2_sctpConnRemoteEntry_t        *sre = NULL;

@@ -5320,28 +5639,69 @@
         const mib_item_t *local = head;
         const mib_item_t *remote = head;
         uint32_t        id = sp->sctpAssocId;
         boolean_t       printfirst = B_TRUE;
 
+        if (print_sctp_hdr == B_TRUE) {
+                (void) puts(sctp_hdr);
+                if (Uflag)
+                        (void) puts(Vflag? sctp_hdr_pid_verbose: sctp_hdr_pid);
+                else
+                        (void) puts(sctp_hdr_normal);
+
+                print_sctp_hdr = B_FALSE;
+        }
+
         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, fname, sizeof (fname),
             &sp->sctpAssocRemPrimAddr, sp->sctpAssocRemPort);
         sctp_pr_addr(sp->sctpAssocRemPrimAddrType, lname, sizeof (lname),
             &sp->sctpAssocLocPrimAddr, sp->sctpAssocLocalPort);
 
+        if (Uflag) {
+                int i = 0;
+                pid_t *pids = cpi->cpi_pids;
+                proc_info_t *pinfo;
+                do {
+                        pinfo = get_proc_info(*pids);
+                        (void) printf("%-31s %-31s %6u %6d %6u %6d "
+                            "%3d/%-3d %-8.8s %6u ",
+                            lname, fname,
+                            sp->sctpConnEntryInfo.ce_swnd,
+                            sp->sctpConnEntryInfo.ce_sendq,
+                            sp->sctpConnEntryInfo.ce_rwnd,
+                            sp->sctpConnEntryInfo.ce_recvq,
+                            sp->sctpAssocInStreams,
+                            sp->sctpAssocOutStreams,
+                            pinfo->pr_user, (int)*pids);
+                        if (Vflag) {
+                                (void) printf("%-11.11s %s\n",
+                                    nssctp_state(sp->sctpAssocState, attr),
+                                    pinfo->pr_psargs);
+                        } else {
+                                (void) printf("%-14.14s %s\n",
+                                    pinfo->pr_fname,
+                                    nssctp_state(sp->sctpAssocState, attr));
+                        }
+                        i++; pids++;
+                } while (i < cpi->cpi_pids_cnt);
+
+        } else {
+
         (void) printf("%-31s %-31s %6u %6d %6u %6d %3d/%-3d %s\n",
             lname, fname,
             sp->sctpConnEntryInfo.ce_swnd,
             sp->sctpConnEntryInfo.ce_sendq,
             sp->sctpConnEntryInfo.ce_rwnd,
             sp->sctpConnEntryInfo.ce_recvq,
             sp->sctpAssocInStreams, sp->sctpAssocOutStreams,
             nssctp_state(sp->sctpAssocState, attr));
+        }
 
         print_transport_label(attr);
 
         if (!Vflag) {
-                return;
+                return (print_sctp_hdr);
         }
 
         /* Print remote addresses/local addresses on following lines */
         while ((sre = sctp_getnext_rem(&remote, sre, id)) != NULL) {
                 if (!IN6_ARE_ADDR_EQUAL(&sre->sctpAssocRemAddr,

@@ -5380,20 +5740,23 @@
                 }
         }
         if (printfirst == B_FALSE) {
                 (void) puts(">");
         }
+
+        return (print_sctp_hdr);
 }
 
 static void
 sctp_report(const mib_item_t *item)
 {
         const mib_item_t                *head;
         const mib2_sctpConnEntry_t      *sp;
-        boolean_t               first = B_TRUE;
+        boolean_t                       print_sctp_hdr_once = B_TRUE;
         mib2_transportMLPEntry_t **attrs, **aptr;
         mib2_transportMLPEntry_t *attr;
+        conn_pid_info_t                 *cpi;
 
         /*
          * Preparation pass: the kernel returns separate entries for SCTP
          * connection table entries and Multilevel Port attributes.  We loop
          * through the attributes first and set up an array for each address

@@ -5405,27 +5768,48 @@
 
         aptr = attrs;
         head = item;
         for (; item != NULL; item = item->next_item) {
 
-                if (!(item->group == MIB2_SCTP &&
-                    item->mib_id == MIB2_SCTP_CONN))
+                if (!((item->group == MIB2_SCTP &&
+                    item->mib_id == MIB2_SCTP_CONN) ||
+                    (item->group == MIB2_SCTP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO)))
                         continue;
 
+                if ((!Uflag) && item->group == MIB2_SCTP &&
+                    item->mib_id == MIB2_SCTP_CONN) {
                 for (sp = item->valp;
                     (char *)sp < (char *)item->valp + item->length;
                     /* LINTED: (note 1) */
-                    sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
+                            sp = (mib2_sctpConnEntry_t *)((char *)sp +
+                            sctpEntrySize)) {
+                                if (!(Aflag ||
+                                    sp->sctpAssocState >=
+                                    MIB2_SCTP_established))
+                                        continue;
                         attr = aptr == NULL ? NULL : *aptr++;
-                        if (Aflag ||
-                            sp->sctpAssocState >= MIB2_SCTP_established) {
-                                if (first == B_TRUE) {
-                                        (void) puts(sctp_hdr);
-                                        (void) puts(sctp_hdr_normal);
-                                        first = B_FALSE;
+                                print_sctp_hdr_once = sctp_conn_report_item(
+                                    head, NULL, print_sctp_hdr_once, sp, attr);
                                 }
-                                sctp_conn_report_item(head, sp, attr);
+                } else if ((Uflag) && item->group == MIB2_SCTP &&
+                    item->mib_id == EXPER_XPORT_PROC_INFO) {
+                        for (sp = (mib2_sctpConnEntry_t *)item->valp;
+                            (char *)sp < (char *)item->valp + item->length;
+                            /* LINTED: (note 1) */
+                            sp = (mib2_sctpConnEntry_t *)((char *)cpi +
+                            cpi->cpi_tot_size)) {
+                                /* LINTED: (note 1) */
+                                cpi = (conn_pid_info_t *)((char *)sp +
+                                    sctpEntrySize);
+                                if (!(Aflag ||
+                                    sp->sctpAssocState >=
+                                    MIB2_SCTP_established))
+                                        continue;
+                                attr = aptr == NULL ? NULL : *aptr++;
+                                print_sctp_hdr_once = sctp_conn_report_item(
+                                    head, cpi, print_sctp_hdr_once, sp, attr);
                         }
                 }
         }
         if (attrs != NULL)
                 free(attrs);

@@ -5448,12 +5832,11 @@
 {
         return (n != 1 ? "es" : "");
 }
 
 static char *
-pktscale(n)
-        int n;
+pktscale(int n)
 {
         static char buf[6];
         char t;
 
         if (n < 1024) {

@@ -6409,16 +6792,79 @@
 
         return (ifname);
 }
 
 /*
+ * Gets proc info in (proc_info_t) given pid. It doesn't return NULL.
+ */
+proc_info_t *
+get_proc_info(pid_t pid)
+{
+        static pid_t saved_pid = 0;
+        static proc_info_t saved_proc_info;
+        static proc_info_t unknown_proc_info = {"<unknown>", "", ""};
+        static psinfo_t pinfo;
+        char path[128];
+        int fd;
+
+        /* hardcode pid = 0 */
+        if (pid == 0) {
+                saved_proc_info.pr_user = "root";
+                saved_proc_info.pr_fname = "sched";
+                saved_proc_info.pr_psargs = "sched";
+                saved_pid = 0;
+                return (&saved_proc_info);
+        }
+
+        if (pid == saved_pid)
+                return (&saved_proc_info);
+        if ((snprintf(path, 128, "/proc/%u/psinfo", (int)pid) > 0) &&
+            ((fd = open(path, O_RDONLY)) != -1)) {
+                if (read(fd, &pinfo, sizeof (pinfo)) == sizeof (pinfo)) {
+                        saved_proc_info.pr_user = get_username(pinfo.pr_uid);
+                        saved_proc_info.pr_fname = pinfo.pr_fname;
+                        saved_proc_info.pr_psargs = pinfo.pr_psargs;
+                        saved_pid = pid;
+                        (void) close(fd);
+                        return (&saved_proc_info);
+                } else {
+                        (void) close(fd);
+                }
+        }
+
+        return (&unknown_proc_info);
+}
+
+/*
+ * Gets username given uid. It doesn't return NULL.
+ */
+static char *
+get_username(uid_t u)
+{
+        static uid_t saved_uid = UINT_MAX;
+        static char  saved_username[128];
+        struct passwd *pw = NULL;
+        if (u == UINT_MAX)
+                return ("<unknown>");
+        if (u == saved_uid && saved_username[0] != '\0')
+                return (saved_username);
+        setpwent();
+        if ((pw = getpwuid(u)) != NULL)
+                (void) strlcpy(saved_username, pw->pw_name, 128);
+        else
+                (void) snprintf(saved_username, 128, "%u", u);
+        saved_uid = u;
+        return (saved_username);
+}
+
+/*
  * print the usage line
  */
 static void
 usage(char *cmdname)
 {
-        (void) fprintf(stderr, "usage: %s [-anv] [-f address_family] "
+        (void) fprintf(stderr, "usage: %s [-anuv] [-f address_family] "
             "[-T d|u]\n", cmdname);
         (void) fprintf(stderr, "       %s [-n] [-f address_family] "
             "[-P protocol] [-T d|u] [-g | -p | -s [interval [count]]]\n",
             cmdname);
         (void) fprintf(stderr, "       %s -m [-v] [-T d|u] "

@@ -6451,5 +6897,181 @@
         (void) vfprintf(stderr, format, argp);
         va_end(argp);
 
         exit(errcode);
 }
+
+
+/* -------------------UNIX Domain Sockets Report---------------------------- */
+
+
+#define NO_ADDR         "                                       "
+#define SO_PAIR         " (socketpair)                          "
+
+static char             *typetoname(t_scalar_t);
+static boolean_t        uds_report_item(struct sockinfo *, boolean_t);
+
+
+static char uds_hdr[] = "\nActive UNIX domain sockets\n";
+
+static char uds_hdr_normal[] =
+" Type       Local Adress                           "
+" Remote Address\n"
+"---------- --------------------------------------- "
+"---------------------------------------\n";
+
+static char uds_hdr_pid[] =
+" Type       User     Pid     Command       "
+" Local Address                         "
+" Remote Address\n"
+"---------- -------- ------ -------------- "
+"--------------------------------------- "
+"---------------------------------------\n";
+static char uds_hdr_pid_verbose[] =
+" Type       User     Pid    Local Address                          "
+" Remote Address                          Command\n"
+"---------- -------- ------ --------------------------------------- "
+"--------------------------------------- --------------\n";
+
+/*
+ * Print a summary of connections related to unix protocols.
+ */
+static void
+uds_report(kstat_ctl_t  *kc)
+{
+        int             i;
+        kstat_t         *ksp;
+        struct sockinfo *psi;
+        boolean_t       print_uds_hdr_once = B_TRUE;
+
+        if (kc == NULL) {
+                fail(0, "uds_report: No kstat");
+                exit(3);
+        }
+
+        if ((ksp = kstat_lookup(kc, "sockfs", 0, "sock_unix_list")) ==
+            (kstat_t *)NULL) {
+                fail(0, "kstat_data_lookup failed\n");
+        }
+
+        if (kstat_read(kc, ksp, NULL) == -1) {
+                fail(0, "kstat_read failed for sock_unix_list\n");
+        }
+
+        if (ksp->ks_ndata == 0) {
+                return;                 /* no AF_UNIX sockets found     */
+        }
+
+        /*
+         * Having ks_data set with ks_data == NULL shouldn't happen;
+         * If it does, the sockfs kstat is seriously broken.
+         */
+        if ((psi = ksp->ks_data) == NULL) {
+                fail(0, "uds_report: no kstat data\n");
+        }
+
+        for (i = 0; i < ksp->ks_ndata; i++) {
+
+                print_uds_hdr_once = uds_report_item(psi, print_uds_hdr_once);
+
+                /* if si_size didn't get filled in, then we're done     */
+                if (psi->si_size == 0 ||
+                    !IS_P2ALIGNED(psi->si_size, sizeof (psi))) {
+                        break;
+                }
+
+                /* point to the next sockinfo in the array */
+                /* LINTED: (note 1) */
+                psi = (struct sockinfo *)(((char *)psi) + psi->si_size);
+        }
+}
+
+static boolean_t
+uds_report_item(struct sockinfo *psi, boolean_t first)
+{
+        int             i = 0;
+        pid_t           *pids;
+        proc_info_t     *pinfo;
+        char            *laddr, *raddr;
+
+        if (first) {
+                (void) printf("%s", uds_hdr);
+                if (Uflag)
+                        (void) printf("%s", Vflag?uds_hdr_pid_verbose:
+                            uds_hdr_pid);
+                else
+                        (void) printf("%s", uds_hdr_normal);
+
+                first = B_FALSE;
+        }
+
+        pids = psi->si_pids;
+
+        do {
+                pinfo = get_proc_info(*pids);
+                raddr = laddr = NO_ADDR;
+
+                /* Try to fill laddr */
+                if ((psi->si_state & SS_ISBOUND) &&
+                    strlen(psi->si_laddr_sun_path) != 0 &&
+                    psi->si_laddr_soa_len != 0) {
+                        if (psi->si_faddr_noxlate) {
+                                laddr = SO_PAIR;
+                        } else {
+                                if (psi->si_laddr_soa_len >
+                                    sizeof (psi->si_laddr_family))
+                                        laddr = psi->si_laddr_sun_path;
+                        }
+                }
+
+                /* Try to fill raddr */
+                if ((psi->si_state & SS_ISCONNECTED) &&
+                    strlen(psi->si_faddr_sun_path) != 0 &&
+                    psi->si_faddr_soa_len != 0) {
+
+                        if (psi->si_faddr_noxlate) {
+                                raddr = SO_PAIR;
+                        } else {
+                                if (psi->si_faddr_soa_len >
+                                    sizeof (psi->si_faddr_family))
+                                        raddr = psi->si_faddr_sun_path;
+                        }
+                }
+
+                if (Uflag && Vflag) {
+                        (void) printf("%-10.10s %-8.8s %6u "
+                            "%-39.39s %-39.39s %s\n",
+                            typetoname(psi->si_serv_type), pinfo->pr_user,
+                            (int)*pids, laddr, raddr, pinfo->pr_psargs);
+                } else if (Uflag && (!Vflag)) {
+                        (void) printf("%-10.10s %-8.8s %6u %-14.14s"
+                            "%-39.39s %-39.39s\n",
+                            typetoname(psi->si_serv_type), pinfo->pr_user,
+                            (int)*pids, pinfo->pr_fname, laddr, raddr);
+                } else {
+                        (void) printf("%-10.10s %s %s\n",
+                            typetoname(psi->si_serv_type), laddr, raddr);
+                }
+
+                i++; pids++;
+        } while (i < psi->si_pn_cnt);
+
+        return (first);
+}
+
+static char *
+typetoname(t_scalar_t type)
+{
+        switch (type) {
+        case T_CLTS:
+                return ("dgram");
+
+        case T_COTS:
+                return ("stream");
+
+        case T_COTS_ORD:
+                return ("stream-ord");
+
+        default:
+                return ("");
+        }
+}