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 ("");
+ }
+}