--- old/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile	2015-08-09 12:47:29.960618838 +0300
+++ new/usr/src/cmd/cmd-inet/usr.bin/netstat/Makefile	2015-08-09 12:47:29.996217119 +0300
@@ -28,7 +28,7 @@
 
 PROG=		netstat
 
-LOCALOBJS=	netstat.o unix.o
+LOCALOBJS=	netstat.o
 COMMONOBJS=	compat.o
 
 include ../../../Makefile.cmd
--- old/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c	2015-08-09 12:47:31.404549390 +0300
+++ new/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c	2015-08-09 12:47:31.639534827 +0300
@@ -55,14 +55,19 @@
 #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>
@@ -91,7 +96,6 @@
 
 #include "statcommon.h"
 
-extern void	unixpr(kstat_ctl_t *kc);
 
 #define	STR_EXPAND	4
 
@@ -135,6 +139,12 @@
 	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);
@@ -191,6 +201,7 @@
 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);
@@ -222,6 +233,8 @@
 static boolean_t	family_selected(int family);
 
 static void		usage(char *);
+static char		*get_username(uid_t);
+proc_info_t		*get_proc_info(uint32_t);
 static void 		fatal(int errcode, char *str1, ...);
 
 #define	PLURAL(n) plural((int)n)
@@ -241,6 +254,7 @@
 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 */
@@ -385,7 +399,7 @@
 	(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;
@@ -445,6 +459,10 @@
 			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;
@@ -654,7 +672,7 @@
 		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 */
@@ -4742,6 +4760,16 @@
 "   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";
@@ -4755,23 +4783,37 @@
 "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_node_list_hdr_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_node_list_hdr_t *, boolean_t first,
+    const mib2_transportMLPEntry_t *);
+
 
 static void
 tcp_report(const mib_item_t *item)
 {
-	int			jtemp = 0;
-	boolean_t		print_hdr_once_v4 = B_TRUE;
-	boolean_t		print_hdr_once_v6 = B_TRUE;
-	mib2_tcpConnEntry_t	*tp;
-	mib2_tcp6ConnEntry_t	*tp6;
-	mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
-	mib2_transportMLPEntry_t **v4a, **v6a;
-	mib2_transportMLPEntry_t *aptr;
+	int				jtemp = 0;
+	boolean_t			print_hdr_once_v4 = B_TRUE;
+	boolean_t			print_hdr_once_v6 = B_TRUE;
+	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_node_list_hdr_t	*cph;
 
 	if (!protocol_selected(IPPROTO_TCP))
 		return;
@@ -4804,7 +4846,11 @@
 		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))
@@ -4812,7 +4858,8 @@
 		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) */
@@ -4820,9 +4867,10 @@
 			    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) */
@@ -4830,9 +4878,38 @@
 			    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 *)cph +
+			    cph->cph_tot_size)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
+				/* LINTED: (note 1) */
+				cph = (conn_pid_node_list_hdr_t *)
+					((char *)tp + tcpConnEntrySize);
+				print_hdr_once_v4 = tcp_report_item_v4(tp,
+				    cph, 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 *)cph +
+			    cph->cph_tot_size)) {
+				aptr = v6a == NULL ? NULL : *v6a++;
+				/* LINTED: (note 1) */
+				cph = (conn_pid_node_list_hdr_t *)
+					((char *)tp6 + tcp6ConnEntrySize);
+				print_hdr_once_v6 = tcp_report_item_v6(tp6,
+				    cph, print_hdr_once_v6, aptr);
 			}
 		}
+
 	} /* 'for' loop 1 ends */
 	(void) fflush(stdout);
 
@@ -4843,7 +4920,8 @@
 }
 
 static boolean_t
-tcp_report_item_v4(const mib2_tcpConnEntry_t *tp, boolean_t first,
+tcp_report_item_v4(const mib2_tcpConnEntry_t *tp,
+    conn_pid_node_list_hdr_t * cph, boolean_t first,
     const mib2_transportMLPEntry_t *attr)
 {
 	/*
@@ -4854,15 +4932,21 @@
 	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,
@@ -4878,7 +4962,7 @@
 		    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 -
@@ -4894,6 +4978,60 @@
 		    tp->tcpConnEntryInfo.ce_rwnd,
 		    (rq >= 0) ? rq : 0,
 		    mitcp_state(tp->tcpConnEntryInfo.ce_state, attr));
+	} else if (Uflag && Vflag) {
+		int i = 0;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+
+			(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, pid, pinfo->pr_psargs);
+			i++; cpn++;
+		} while (i < cph->cph_pn_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;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+
+			(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, pid, 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++; cpn++;
+		} while (i < cph->cph_pn_cnt);
 	}
 
 	print_transport_label(attr);
@@ -4902,7 +5040,8 @@
 }
 
 static boolean_t
-tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6, boolean_t first,
+tcp_report_item_v6(const mib2_tcp6ConnEntry_t *tp6,
+    conn_pid_node_list_hdr_t *cph, boolean_t first,
     const mib2_transportMLPEntry_t *attr)
 {
 	/*
@@ -4920,7 +5059,12 @@
 
 	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) ?
@@ -4928,7 +5072,7 @@
 	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,
@@ -4945,7 +5089,7 @@
 		    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 -
@@ -4962,6 +5106,61 @@
 		    (rq >= 0) ? rq : 0,
 		    mitcp_state(tp6->tcp6ConnEntryInfo.ce_state, attr),
 		    ifnamep);
+	} else if (Uflag && Vflag) {
+		int i = 0;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+
+			(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, pid, pinfo->pr_psargs);
+			i++; cpn++;
+		} while (i < cph->cph_pn_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;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+
+			(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, pid, 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++; cpn++;
+		} while (i < cph->cph_pn_cnt);
 	}
 
 	print_transport_label(attr);
@@ -4972,31 +5171,55 @@
 /* ------------------------------- UDP_REPORT------------------------------- */
 
 static boolean_t udp_report_item_v4(const mib2_udpEntry_t *ude,
-    boolean_t first, const mib2_transportMLPEntry_t *attr);
+    conn_pid_node_list_hdr_t *cph, 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_node_list_hdr_t *cph, 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;
-	boolean_t		print_hdr_once_v4 = B_TRUE;
-	boolean_t		print_hdr_once_v6 = B_TRUE;
-	mib2_udpEntry_t		*ude;
-	mib2_udp6Entry_t	*ude6;
-	mib2_transportMLPEntry_t **v4_attrs, **v6_attrs;
-	mib2_transportMLPEntry_t **v4a, **v6a;
-	mib2_transportMLPEntry_t *aptr;
+	int				jtemp = 0;
+	boolean_t			print_hdr_once_v4 = B_TRUE;
+	boolean_t			print_hdr_once_v6 = B_TRUE;
+	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_node_list_hdr_t	*cph;
 
 	if (!protocol_selected(IPPROTO_UDP))
 		return;
@@ -5027,7 +5250,11 @@
 		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))
@@ -5036,7 +5263,8 @@
 			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) */
@@ -5044,9 +5272,10 @@
 			    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) */
@@ -5054,7 +5283,35 @@
 			    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 *)cph +
+			    cph->cph_tot_size)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
+				/* LINTED: (note 1) */
+				cph = (conn_pid_node_list_hdr_t *)
+					((char *)ude + udpEntrySize);
+				print_hdr_once_v4 = udp_report_item_v4(ude,
+				    cph, 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 *)cph +
+			    cph->cph_tot_size)) {
+				aptr = v6a == NULL ? NULL : *v6a++;
+				/* LINTED: (note 1) */
+				cph = (conn_pid_node_list_hdr_t *)
+					((char *)ude6 + udp6EntrySize);
+				print_hdr_once_v6 = udp_report_item_v6(ude6,
+				    cph, print_hdr_once_v6, aptr);
 			}
 		}
 	} /* 'for' loop 1 ends */
@@ -5067,8 +5324,8 @@
 }
 
 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_node_list_hdr_t *cph,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
 	char	lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 			/* hostname + portname */
@@ -5078,19 +5335,49 @@
 
 	if (first) {
 		(void) printf(v4compat ? "\nUDP\n" : "\nUDP: IPv4\n");
-		(void) printf(udp_hdr_v4);
+
+		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)) :
-	    "",
-	    miudp_state(ude->udpEntryInfo.ue_state, attr));
+	    "");
+	if (!Uflag) {
+		(void) printf("%s\n",
+		    miudp_state(ude->udpEntryInfo.ue_state, attr));
+	} else {
+		int i = 0;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+			(void) printf("%-8.8s %6u ", pinfo->pr_user, pid);
+
+			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++; cpn++;
+		} while (i < cph->cph_pn_cnt);
+	}
 
 	print_transport_label(attr);
 
@@ -5098,8 +5385,8 @@
 }
 
 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_node_list_hdr_t *cph,
+    boolean_t first, const mib2_transportMLPEntry_t *attr)
 {
 	char	lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
 			/* hostname + portname */
@@ -5111,23 +5398,56 @@
 
 	if (first) {
 		(void) printf("\nUDP: IPv6\n");
-		(void) printf(udp_hdr_v6);
+
+		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)) :
-	    "",
-	    miudp_state(ude6->udp6EntryInfo.ue_state, attr),
-	    ifnamep == NULL ? "" : ifnamep);
+	    "");
+	if (!Uflag) {
+		(void) printf("%-10s %s\n",
+		    miudp_state(ude6->udp6EntryInfo.ue_state, attr),
+		    ifnamep == NULL ? "" : ifnamep);
+	} else {
+		int i = 0;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+			(void) printf("%-8.8s %6u ", pinfo->pr_user, pid);
+
+			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++; cpn++;
+		} while (i < cph->cph_pn_cnt);
+	}
 
 	print_transport_label(attr);
 
@@ -5143,6 +5463,16 @@
 "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)
@@ -5309,8 +5639,9 @@
 	}
 }
 
-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_node_list_hdr_t * cph,
+    boolean_t print_sctp_hdr, const mib2_sctpConnEntry_t *sp,
     const mib2_transportMLPEntry_t *attr)
 {
 	char		lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
@@ -5322,24 +5653,68 @@
 	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);
 
-	(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));
+	if (Uflag) {
+		int i = 0;
+		conn_pid_node_t *cpn = cph->cph_cpns;
+		proc_info_t *pinfo;
+
+		do {
+			int pid = (cph->cph_pn_cnt)?cpn->cpn_pid:0;
+			pinfo = get_proc_info(cpn->cpn_pid);
+			(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, pid);
+
+			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++; cpn++;
+		} while (i < cph->cph_pn_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 */
@@ -5382,6 +5757,8 @@
 	if (printfirst == B_FALSE) {
 		(void) puts(">");
 	}
+
+	return (print_sctp_hdr);
 }
 
 static void
@@ -5389,9 +5766,10 @@
 {
 	const mib_item_t		*head;
 	const mib2_sctpConnEntry_t	*sp;
-	boolean_t		first = B_TRUE;
-	mib2_transportMLPEntry_t **attrs, **aptr;
-	mib2_transportMLPEntry_t *attr;
+	boolean_t 			print_sctp_hdr_once = B_TRUE;
+	mib2_transportMLPEntry_t 	**attrs, **aptr;
+	mib2_transportMLPEntry_t	*attr;
+	conn_pid_node_list_hdr_t	*cph;
 
 	/*
 	 * Preparation pass: the kernel returns separate entries for SCTP
@@ -5407,23 +5785,43 @@
 	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;
 
-		for (sp = item->valp;
-		    (char *)sp < (char *)item->valp + item->length;
-		    /* LINTED: (note 1) */
-		    sp = (mib2_sctpConnEntry_t *)((char *)sp + sctpEntrySize)) {
-			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;
-				}
-				sctp_conn_report_item(head, sp, attr);
+		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)) {
+				if (!(Aflag ||
+				  sp->sctpAssocState >= MIB2_SCTP_established))
+					continue;
+				attr = aptr == NULL ? NULL : *aptr++;
+				print_sctp_hdr_once = sctp_conn_report_item(head, NULL,
+							print_sctp_hdr_once, 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 *)cph +
+			    cph->cph_tot_size)) {
+				/* LINTED: (note 1) */
+				cph = (conn_pid_node_list_hdr_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, cph,
+					print_sctp_hdr_once, sp, attr);
 			}
 		}
 	}
@@ -6411,12 +6809,77 @@
 }
 
 /*
+ * get proc info (psinfo_t) given pid. It doesn't return NULL.
+ */
+
+proc_info_t *
+get_proc_info(uint32_t pid)
+{
+	static uint32_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",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);
+}
+
+/*
+ * get 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",
@@ -6453,3 +6916,183 @@
 
 	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 a unix protocol.
+ */
+static void
+uds_report(kstat_ctl_t 	*kc)
+{
+	int		i;
+	kstat_t		*ksp;
+	struct sockinfo	*psi;		/* ptr to current sockinfo	*/
+	boolean_t	print_uds_hdr_once = B_TRUE;
+
+	if (kc == NULL) {	/* sanity check.			*/
+		fail(0, "uds_report: No kstat");
+		exit(3);
+	}
+
+	/* find the sockfs kstat:					*/
+	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 each sockinfo structure, display what we need:		*/
+	for (i = 0; i < ksp->ks_ndata; i++) {
+
+		/* process this entry */
+		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;
+	conn_pid_node_t	*cpn;
+	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;
+	}
+
+	cpn = psi->si_pns;
+
+	do {
+		int pid = (psi->si_pn_cnt)?cpn->cpn_pid:0;
+		pinfo = get_proc_info(cpn->cpn_pid);
+		raddr = laddr = NO_ADDR;
+
+		/* laddr.soa_sa: 					*/
+		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;
+			}
+		}
+
+		/* faddr.soa_sa:					*/
+		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,
+				pid, 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,
+				pid, pinfo->pr_fname, laddr, raddr);
+		} else {
+			(void) printf("%-10.10s %s %s\n",
+				typetoname(psi->si_serv_type), laddr, raddr);
+		}
+
+		i++; cpn++;
+	} 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 ("");
+	}
+}
--- old/usr/src/cmd/cmd-inet/usr.bin/netstat/unix.c	2015-08-09 12:47:33.808647866 +0300
+++ /dev/null	2015-08-09 12:47:33.000000000 +0300
@@ -1,243 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
-
-/*
- * University Copyright- Copyright (c) 1982, 1986, 1988
- * The Regents of the University of California
- * All Rights Reserved
- *
- * University Acknowledgment- Portions of this document are derived from
- * software developed by the University of California, Berkeley, and its
- * contributors.
- */
-
-/*
- * code for netstat's -k option
- *
- * NOTES:
- * 1. A comment "LINTED: (note 1)" appears before certain lines where
- *    lint would have complained, "pointer cast may result in improper
- *    alignment". These are lines where lint had suspected potential
- *    improper alignment of a data structure; in each such situation
- *    we have relied on the kernel guaranteeing proper alignment.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <strings.h>
-#include <string.h>
-#include <kstat.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stream.h>
-#include <sys/tiuser.h>
-#include <sys/socketvar.h>
-#include <sys/sysmacros.h>
-
-static char		*typetoname(t_scalar_t);
-static void		print_kn(kstat_t *);
-static char		*nextstr(char *);
-extern void		fail(int, char *, ...);
-
-#define	NALEN	8			/* nulladdress string length	*/
-
-/*
- * Print a summary of connections related to a unix protocol.
- */
-void
-unixpr(kstat_ctl_t 	*kc)
-{
-	kstat_t		*ksp;
-
-	if (kc == NULL) {	/* sanity check.			*/
-		fail(0, "unixpr: No kstat");
-		exit(3);
-	}
-
-	/* find the sockfs kstat:					*/
-	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");
-	}
-
-	print_kn(ksp);
-}
-
-static void
-print_kn(kstat_t *ksp)
-{
-	int		i;
-	struct sockinfo	*psi;		/* ptr to current sockinfo	*/
-	char		*pas;		/* ptr to string-format addrs	*/
-	char		*nullstr;	/* ptr to null string		*/
-	char		*conn_vp;
-	char		*local_vp;
-
-	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, "print_kn: no kstat data\n");
-	}
-
-	/* set pas to the address strings which are after the sockinfo	*/
-	pas = &((char *)psi)[sizeof (struct sockinfo)];
-
-	/* Create a string of NALEN "0"'s for NULL addresses.		*/
-	if ((nullstr = calloc(1, NALEN)) == NULL) {
-		fail(0, "print_kn: out of memory\n");
-	}
-	(void) memset((void *)nullstr, '0', NALEN);
-
-	(void) printf("\nActive UNIX domain sockets\n");
-	(void) printf("%-8.8s %-10.10s %8.8s %8.8s  "
-	    "Local Addr      Remote Addr\n",
-	    "Address", "Type", "Vnode", "Conn");
-
-	/* for each sockinfo structure, display what we need:		*/
-	for (i = 0; i < ksp->ks_ndata; i++) {
-		/* display sonode's address. 1st string after sockinfo:	*/
-		pas = &(((char *)psi)[sizeof (struct sockinfo)]);
-		(void) printf("%s ", pas);
-
-		(void) printf("%-10.10s ", typetoname(psi->si_serv_type));
-
-		/* laddr.sou_vp: 2nd string after sockinfo:		*/
-		pas = nextstr(pas);
-
-		local_vp = conn_vp = nullstr;
-
-		if ((psi->si_state & SS_ISBOUND) &&
-		    (psi->si_ux_laddr_sou_magic == SOU_MAGIC_EXPLICIT)) {
-			local_vp = pas;
-		}
-
-		/* faddr.sou_vp: 3rd string after sockinfo:		*/
-		pas = nextstr(pas);
-		if ((psi->si_state & SS_ISCONNECTED) &&
-		    (psi->si_ux_faddr_sou_magic == SOU_MAGIC_EXPLICIT)) {
-			conn_vp = pas;
-		}
-
-		(void) printf("%s %s ", local_vp, conn_vp);
-
-		/* laddr.soa_sa: 					*/
-		if ((psi->si_state & SS_ISBOUND) &&
-		    strlen(psi->si_laddr_sun_path) != 0 &&
-		    psi->si_laddr_soa_len != 0) {
-			if (psi->si_faddr_noxlate) {
-				(void) printf(" (socketpair)  ");
-			} else {
-				if (psi->si_laddr_soa_len >
-				    sizeof (psi->si_laddr_family))
-					(void) printf("%s ",
-					    psi->si_laddr_sun_path);
-				else
-					(void) printf("               ");
-			}
-		} else
-			(void) printf("               ");
-
-		/* faddr.soa_sa:					*/
-		if ((psi->si_state & SS_ISCONNECTED) &&
-		    strlen(psi->si_faddr_sun_path) != 0 &&
-		    psi->si_faddr_soa_len != 0) {
-
-			if (psi->si_faddr_noxlate) {
-				(void) printf(" (socketpair)  ");
-			} else {
-				if (psi->si_faddr_soa_len >
-				    sizeof (psi->si_faddr_family))
-					(void) printf("%s ",
-					    psi->si_faddr_sun_path);
-				else
-					(void) printf("               ");
-			}
-		} else
-			(void) printf("               ");
-
-		(void) printf("\n");
-
-		/* 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;
-		}
-
-		/* LINTED: (note 1) */
-		psi = (struct sockinfo *)&(((char *)psi)[psi->si_size]);
-	}
-}
-
-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 ("");
-	}
-}
-
-/*
- * nextstr():	find the beginning of a next string.
- *	The sockfs kstat left-justifies each address string, leaving
- *	null's between the strings. Since we don't necessarily know
- *	the sizes of pointers in the kernel, we need to skip over these
- *	nulls in order to get to the start of the next string.
- */
-static char *
-nextstr(char *pas)
-{
-	char *next;
-
-	for (next = &pas[strlen(pas) + 1]; *next == NULL; ) {
-		next++;
-	}
-
-	return (next);
-}
--- old/usr/src/common/list/list.c	2015-08-09 12:47:34.381951358 +0300
+++ new/usr/src/common/list/list.c	2015-08-09 12:47:34.452422246 +0300
@@ -249,3 +249,17 @@
 {
 	return (list_empty(list));
 }
+
+uint64_t
+list_size(list_t *list)
+{
+	size_t sz = 0;
+	list_node_t *node;
+
+	node = &list->list_head;
+	while (node->list_next != &list->list_head) {
+		sz++;
+		node = node->list_next;
+	}
+	return (sz);
+}
--- old/usr/src/pkg/manifests/system-header.mf	2015-08-09 12:47:35.987422535 +0300
+++ new/usr/src/pkg/manifests/system-header.mf	2015-08-09 12:47:35.999235556 +0300
@@ -1288,6 +1288,7 @@
 file path=usr/include/sys/pghw.h
 file path=usr/include/sys/physmem.h
 $(i386_ONLY)file path=usr/include/sys/pic.h
+file path=usr/include/sys/pidnode.h
 $(i386_ONLY)file path=usr/include/sys/pit.h
 file path=usr/include/sys/pkp_hash.h
 file path=usr/include/sys/pm.h
--- old/usr/src/uts/common/fs/doorfs/door_sys.c	2015-08-09 12:47:37.897758733 +0300
+++ new/usr/src/uts/common/fs/doorfs/door_sys.c	2015-08-09 12:47:37.937995349 +0300
@@ -1784,6 +1784,11 @@
 	setf(fd, fp);
 	dp->d_data.d_desc.d_descriptor = fd;
 
+	/* add curproc to the pid list associated with that file */
+	if (fp->f_vnode != NULL)
+		(void) VOP_IOCTL(fp->f_vnode, F_FORKED, (intptr_t)curproc, FKIOCTL,
+			kcred, NULL, NULL);
+
 	/* Fill in the attributes */
 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
 		vp = fp->f_vnode;
--- old/usr/src/uts/common/fs/sockfs/sockcommon.c	2015-08-09 12:47:39.687351092 +0300
+++ new/usr/src/uts/common/fs/sockfs/sockcommon.c	2015-08-09 12:47:39.762726900 +0300
@@ -475,6 +475,8 @@
 	    offsetof(struct sonode, so_acceptq_node));
 	list_create(&so->so_acceptq_defer, sizeof (struct sonode),
 	    offsetof(struct sonode, so_acceptq_node));
+	list_create(&so->so_pid_list, sizeof (pid_node_t),
+		offsetof(pid_node_t, pn_ref_link));
 	list_link_init(&so->so_acceptq_node);
 	so->so_acceptq_len	= 0;
 	so->so_backlog		= 0;
@@ -490,6 +492,7 @@
 
 	mutex_init(&so->so_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&so->so_acceptq_lock, NULL, MUTEX_DEFAULT, NULL);
+	mutex_init(&so->so_pid_list_lock, NULL, MUTEX_DEFAULT, NULL);
 	rw_init(&so->so_fallback_rwlock, NULL, RW_DEFAULT, NULL);
 	cv_init(&so->so_state_cv, NULL, CV_DEFAULT, NULL);
 	cv_init(&so->so_single_cv, NULL, CV_DEFAULT, NULL);
@@ -520,6 +523,7 @@
 
 	list_destroy(&so->so_acceptq_list);
 	list_destroy(&so->so_acceptq_defer);
+	list_destroy(&so->so_pid_list);
 	ASSERT(!list_link_active(&so->so_acceptq_node));
 	ASSERT(so->so_listener == NULL);
 
@@ -535,6 +539,7 @@
 
 	mutex_destroy(&so->so_lock);
 	mutex_destroy(&so->so_acceptq_lock);
+	mutex_destroy(&so->so_pid_list_lock);
 	rw_destroy(&so->so_fallback_rwlock);
 
 	cv_destroy(&so->so_state_cv);
@@ -626,6 +631,7 @@
 sonode_fini(struct sonode *so)
 {
 	vnode_t *vp;
+	pid_node_t *pn;
 
 	ASSERT(so->so_count == 0);
 
@@ -654,6 +660,13 @@
 	if (so->so_filter_top != NULL)
 		sof_sonode_cleanup(so);
 
+	mutex_enter(&so->so_pid_list_lock);
+	while ((pn = list_head(&so->so_pid_list)) != NULL) {
+		list_remove(&so->so_pid_list, pn);
+		kmem_free(pn, sizeof (*pn));
+	}
+	mutex_exit(&so->so_pid_list_lock);
+
 	ASSERT(list_is_empty(&so->so_acceptq_list));
 	ASSERT(list_is_empty(&so->so_acceptq_defer));
 	ASSERT(!list_link_active(&so->so_acceptq_node));
@@ -664,3 +677,58 @@
 	ASSERT(so->so_rcv_head == NULL);
 	ASSERT(so->so_rcv_last_head == NULL);
 }
+
+void
+sonode_insert_pid(struct sonode *so, proc_t *p)
+{
+	pid_node_t	*pn;
+
+	/*
+	 * don't add pid = 0 to the list. this  is usually the case
+	 * with sockets created as the result of accepting a new connection.
+	 * These sockets are created by the kernel, we will catch them once
+	 * the process accepts them.
+	 */
+
+	if (p->p_pidp->pid_id == 0)
+		return;
+
+	mutex_enter(&so->so_pid_list_lock);
+	pn = list_head(&so->so_pid_list);
+	while (pn != NULL && pn->pn_pid != p->p_pidp->pid_id) {
+		pn = list_next(&so->so_pid_list, pn);
+	}
+
+	if (pn != NULL) {
+		pn->pn_count++;
+	} else {
+		pn = kmem_zalloc(sizeof (*pn), KM_SLEEP);
+		list_link_init(&pn->pn_ref_link);
+		pn->pn_pid = p->p_pidp->pid_id;
+		pn->pn_count = 1;
+		list_insert_tail(&so->so_pid_list, pn);
+	}
+	mutex_exit(&so->so_pid_list_lock);
+}
+
+void
+sonode_remove_pid(struct sonode *so, proc_t *p)
+{
+	pid_node_t *pn;
+
+	mutex_enter(&so->so_pid_list_lock);
+	pn = list_head(&so->so_pid_list);
+	while (pn != NULL && pn->pn_pid != p->p_pidp->pid_id) {
+		pn = list_next(&so->so_pid_list, pn);
+	}
+
+	if (pn != NULL) {
+		if (pn->pn_count > 1)
+				pn->pn_count--;
+		else {
+			list_remove(&so->so_pid_list, pn);
+			kmem_free(pn, sizeof (*pn));
+		}
+	}
+	mutex_exit(&so->so_pid_list_lock);
+}
--- old/usr/src/uts/common/fs/sockfs/sockcommon.h	2015-08-09 12:47:40.828743734 +0300
+++ new/usr/src/uts/common/fs/sockfs/sockcommon.h	2015-08-09 12:47:40.839294712 +0300
@@ -163,6 +163,7 @@
 extern int	so_disconnected(sock_upper_handle_t, sock_connid_t, int);
 extern void	so_txq_full(sock_upper_handle_t, boolean_t);
 extern void 	so_opctl(sock_upper_handle_t, sock_opctl_action_t, uintptr_t);
+conn_pid_node_list_hdr_t *so_get_sock_pid_list(sock_upper_handle_t sock_handle);
 /* Common misc. functions */
 
 	/* accept queue */
@@ -233,6 +234,8 @@
 extern void 	sonode_init(struct sonode *, struct sockparams *,
     int, int, int, sonodeops_t *);
 extern void	sonode_fini(struct sonode *);
+extern void	sonode_insert_pid(struct sonode *, proc_t *);
+extern void	sonode_remove_pid(struct sonode *, proc_t *);
 
 /*
  * Event flags to socket_sendsig().
--- old/usr/src/uts/common/fs/sockfs/sockcommon_sops.c	2015-08-09 12:47:42.604824739 +0300
+++ new/usr/src/uts/common/fs/sockfs/sockcommon_sops.c	2015-08-09 12:47:42.663803039 +0300
@@ -37,6 +37,7 @@
 #include <sys/stropts.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/fcntl.h>
 
 #define	_SUN_TPI_VERSION	2
 #include <sys/tihdr.h>
@@ -357,6 +358,7 @@
 			socket_destroy(nso);
 		} else {
 			*nsop = nso;
+			sonode_insert_pid(nso, curproc);
 		}
 	}
 
@@ -1540,6 +1542,45 @@
 	VN_RELE(SOTOV(so));
 }
 
+conn_pid_node_list_hdr_t *
+so_get_sock_pid_list(sock_upper_handle_t sock_handle)
+{
+	int sz, n = 0;
+	pid_node_t			*pn;
+	conn_pid_node_t			*cpn;
+	conn_pid_node_list_hdr_t	*cph;
+	struct sonode 			*so = (struct sonode *)sock_handle;
+
+	mutex_enter(&so->so_pid_list_lock);
+
+	n = list_size(&so->so_pid_list);
+	sz = sizeof (conn_pid_node_list_hdr_t);
+	sz += (n > 1)?((n - 1) * sizeof (conn_pid_node_t)):0;
+	cph = kmem_zalloc(sz, KM_SLEEP);
+
+	cph->cph_magic = CONN_PID_NODE_LIST_HDR_MAGIC;
+	cph->cph_contents = CONN_PID_NODE_LIST_HDR_SOC;
+	cph->cph_pn_cnt = n;
+	cph->cph_tot_size = sz;
+	cph->cph_flags = 0;
+	cph->cph_optional1 = 0;
+	cph->cph_optional2 = 0;
+
+	if (cph->cph_pn_cnt > 0) {
+		cpn = cph->cph_cpns;
+		pn = list_head(&so->so_pid_list);
+		while (pn != NULL) {
+			PIDNODE2CONNPIDNODE(pn, cpn);
+			pn = list_next(&so->so_pid_list, pn);
+			cpn++;
+		}
+	}
+
+	mutex_exit(&so->so_pid_list_lock);
+
+	return (cph);
+}
+
 void
 so_zcopy_notify(sock_upper_handle_t sock_handle)
 {
@@ -1940,5 +1981,6 @@
 	so_signal_oob,
 	so_zcopy_notify,
 	so_set_error,
-	so_closed
+	so_closed,
+	so_get_sock_pid_list
 };
--- old/usr/src/uts/common/fs/sockfs/sockcommon_vnops.c	2015-08-09 12:47:45.392690611 +0300
+++ new/usr/src/uts/common/fs/sockfs/sockcommon_vnops.c	2015-08-09 12:47:45.402729201 +0300
@@ -123,6 +123,8 @@
 	so->so_count++;
 	mutex_exit(&so->so_lock);
 
+	sonode_insert_pid(so, curproc);
+
 	ASSERT(so->so_count != 0);	/* wraparound */
 	ASSERT(vp->v_type == VSOCK);
 
@@ -209,6 +211,22 @@
 
 	ASSERT(vp->v_type == VSOCK);
 
+	switch (cmd) {
+		case F_FORKED: {
+			if (cr != kcred)
+				return (-1);
+			sonode_insert_pid(so, (proc_t *)arg);
+			return (0);
+		}
+
+		case F_CLOSED: {
+			if (cr != kcred)
+				return (-1);
+			sonode_remove_pid(so, (proc_t *)arg);
+			return (0);
+		}
+	}
+
 	return (socket_ioctl(so, cmd, arg, mode, cr, rvalp));
 }
 
--- old/usr/src/uts/common/fs/sockfs/socksubr.c	2015-08-09 12:47:48.436399324 +0300
+++ new/usr/src/uts/common/fs/sockfs/socksubr.c	2015-08-09 12:47:48.446745633 +0300
@@ -113,17 +113,6 @@
 
 extern int modrootloaded;
 
-#define	ADRSTRLEN (2 * sizeof (void *) + 1)
-/*
- * kernel structure for passing the sockinfo data back up to the user.
- * the strings array allows us to convert AF_UNIX addresses into strings
- * with a common method regardless of which n-bit kernel we're running.
- */
-struct k_sockinfo {
-	struct sockinfo	ks_si;
-	char		ks_straddr[3][ADRSTRLEN];
-};
-
 /*
  * Translate from a device pathname (e.g. "/dev/tcp") to a vnode.
  * Returns with the vnode held.
@@ -766,6 +755,11 @@
 		mutex_exit(&fp->f_tlock);
 		setf(fd, fp);
 		*rp++ = fd;
+		/* add curproc to the pid list associated with that file */
+		if (fp->f_vnode != NULL)
+			(void) VOP_IOCTL(fp->f_vnode, F_FORKED,
+			    (intptr_t)curproc, FKIOCTL, kcred, NULL, NULL);
+
 		if (AU_AUDITING())
 			audit_fdrecv(fd, fp);
 		dprint(1, ("fdbuf_extract: [%d] = %d, %p refcnt %d\n",
@@ -1743,13 +1737,17 @@
  * other process (zone) can currently get inbetween resulting in a wrong size
  * buffer allocation.
  */
+
 static int
 sockfs_update(kstat_t *ksp, int rw)
 {
-	uint_t	nactive = 0;		/* # of active AF_UNIX sockets	*/
+	uint_t	n, nactive = 0;		/* # of active AF_UNIX sockets	*/
+	uint_t	tsze, sze;
 	struct sonode	*so;		/* current sonode on socklist	*/
 	zoneid_t	myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
 
+	tsze = sze = 0;
+
 	ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
 
 	if (rw == KSTAT_WRITE) {	/* bounce all writes		*/
@@ -1758,11 +1756,21 @@
 
 	for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
 		if (so->so_count != 0 && so->so_zoneid == myzoneid) {
+
 			nactive++;
+
+			mutex_enter(&so->so_pid_list_lock);
+			n = list_size(&so->so_pid_list);
+			mutex_exit(&so->so_pid_list_lock);
+
+			sze = sizeof (struct sockinfo);
+			sze += (n > 1)?((n - 1) * sizeof (conn_pid_node_t)):0;
+			tsze += sze;
+
 		}
 	}
 	ksp->ks_ndata = nactive;
-	ksp->ks_data_size = nactive * sizeof (struct k_sockinfo);
+	ksp->ks_data_size = tsze;
 
 	return (0);
 }
@@ -1772,11 +1780,14 @@
 {
 	int			ns;	/* # of sonodes we've copied	*/
 	struct sonode		*so;	/* current sonode on socklist	*/
-	struct k_sockinfo	*pksi;	/* where we put sockinfo data	*/
+	struct sockinfo		*psi;	/* where we put sockinfo data	*/
 	t_uscalar_t		sn_len;	/* soa_len			*/
 	zoneid_t		myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
 	sotpi_info_t 		*sti;
 
+	uint_t				sze;
+	conn_pid_node_list_hdr_t	*cph;
+
 	ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
 
 	ksp->ks_snaptime = gethrtime();
@@ -1789,7 +1800,7 @@
 	 * for each sonode on the socklist, we massage the important
 	 * info into buf, in k_sockinfo format.
 	 */
-	pksi = (struct k_sockinfo *)buf;
+	psi = (struct sockinfo *)buf;
 	ns = 0;
 	for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
 		/* only stuff active sonodes and the same zone:		*/
@@ -1797,30 +1808,41 @@
 			continue;
 		}
 
+		/* get the pidnode list associated with this sonode */
+		cph = so_get_sock_pid_list((sock_upper_handle_t)so);
+
+		/* calculate the size of this sockinfo structure */
+		sze = sizeof (struct sockinfo);
+		sze += (cph->cph_pn_cnt > 1)?
+			((cph->cph_pn_cnt - 1) * sizeof (conn_pid_node_t)):0;
+
 		/*
 		 * If the sonode was activated between the update and the
-		 * snapshot, we're done - as this is only a snapshot.
+		 * snapshot, we're done - as this is only a snapshot. We need
+		 * to make sure that we have space for this sockinfo.
 		 */
-		if ((caddr_t)(pksi) >= (caddr_t)buf + ksp->ks_data_size) {
+		if (((caddr_t)(psi) + sze) >
+			((caddr_t)buf + ksp->ks_data_size)) {
 			break;
 		}
 
 		sti = SOTOTPI(so);
 		/* copy important info into buf:			*/
-		pksi->ks_si.si_size = sizeof (struct k_sockinfo);
-		pksi->ks_si.si_family = so->so_family;
-		pksi->ks_si.si_type = so->so_type;
-		pksi->ks_si.si_flag = so->so_flag;
-		pksi->ks_si.si_state = so->so_state;
-		pksi->ks_si.si_serv_type = sti->sti_serv_type;
-		pksi->ks_si.si_ux_laddr_sou_magic =
+		psi->si_size = sze;
+		psi->si_family = so->so_family;
+		psi->si_type = so->so_type;
+		psi->si_flag = so->so_flag;
+		psi->si_state = so->so_state;
+		psi->si_serv_type = sti->sti_serv_type;
+		psi->si_ux_laddr_sou_magic =
 		    sti->sti_ux_laddr.soua_magic;
-		pksi->ks_si.si_ux_faddr_sou_magic =
+		psi->si_ux_faddr_sou_magic =
 		    sti->sti_ux_faddr.soua_magic;
-		pksi->ks_si.si_laddr_soa_len = sti->sti_laddr.soa_len;
-		pksi->ks_si.si_faddr_soa_len = sti->sti_faddr.soa_len;
-		pksi->ks_si.si_szoneid = so->so_zoneid;
-		pksi->ks_si.si_faddr_noxlate = sti->sti_faddr_noxlate;
+		psi->si_laddr_soa_len = sti->sti_laddr.soa_len;
+		psi->si_faddr_soa_len = sti->sti_faddr.soa_len;
+		psi->si_szoneid = so->so_zoneid;
+		psi->si_faddr_noxlate = sti->sti_faddr_noxlate;
+
 
 		mutex_enter(&so->so_lock);
 
@@ -1828,47 +1850,53 @@
 			ASSERT(sti->sti_laddr_sa->sa_data != NULL);
 			sn_len = sti->sti_laddr_len;
 			ASSERT(sn_len <= sizeof (short) +
-			    sizeof (pksi->ks_si.si_laddr_sun_path));
+			    sizeof (psi->si_laddr_sun_path));
 
-			pksi->ks_si.si_laddr_family =
+			psi->si_laddr_family =
 			    sti->sti_laddr_sa->sa_family;
 			if (sn_len != 0) {
 				/* AF_UNIX socket names are NULL terminated */
-				(void) strncpy(pksi->ks_si.si_laddr_sun_path,
+				(void) strncpy(psi->si_laddr_sun_path,
 				    sti->sti_laddr_sa->sa_data,
-				    sizeof (pksi->ks_si.si_laddr_sun_path));
-				sn_len = strlen(pksi->ks_si.si_laddr_sun_path);
+				    sizeof (psi->si_laddr_sun_path));
+				sn_len = strlen(psi->si_laddr_sun_path);
 			}
-			pksi->ks_si.si_laddr_sun_path[sn_len] = 0;
+			psi->si_laddr_sun_path[sn_len] = 0;
 		}
 
 		if (sti->sti_faddr_sa != NULL) {
 			ASSERT(sti->sti_faddr_sa->sa_data != NULL);
 			sn_len = sti->sti_faddr_len;
 			ASSERT(sn_len <= sizeof (short) +
-			    sizeof (pksi->ks_si.si_faddr_sun_path));
+			    sizeof (psi->si_faddr_sun_path));
 
-			pksi->ks_si.si_faddr_family =
+			psi->si_faddr_family =
 			    sti->sti_faddr_sa->sa_family;
 			if (sn_len != 0) {
-				(void) strncpy(pksi->ks_si.si_faddr_sun_path,
+				(void) strncpy(psi->si_faddr_sun_path,
 				    sti->sti_faddr_sa->sa_data,
-				    sizeof (pksi->ks_si.si_faddr_sun_path));
-				sn_len = strlen(pksi->ks_si.si_faddr_sun_path);
+				    sizeof (psi->si_faddr_sun_path));
+				sn_len = strlen(psi->si_faddr_sun_path);
 			}
-			pksi->ks_si.si_faddr_sun_path[sn_len] = 0;
+			psi->si_faddr_sun_path[sn_len] = 0;
 		}
 
 		mutex_exit(&so->so_lock);
 
-		(void) sprintf(pksi->ks_straddr[0], "%p", (void *)so);
-		(void) sprintf(pksi->ks_straddr[1], "%p",
+		(void) sprintf(psi->si_son_straddr, "%p", (void *)so);
+		(void) sprintf(psi->si_lvn_straddr, "%p",
 		    (void *)sti->sti_ux_laddr.soua_vp);
-		(void) sprintf(pksi->ks_straddr[2], "%p",
+		(void) sprintf(psi->si_fvn_straddr, "%p",
 		    (void *)sti->sti_ux_faddr.soua_vp);
 
+		if ((psi->si_pn_cnt = cph->cph_pn_cnt) > 0)
+			(void) memcpy(psi->si_pns, cph->cph_cpns,
+				psi->si_pn_cnt * sizeof (conn_pid_node_t));
+
+		kmem_free(cph, cph->cph_tot_size);
+
+		psi = (struct sockinfo *)((char *)psi + psi->si_size);
 		ns++;
-		pksi++;
 	}
 
 	ksp->ks_ndata = ns;
--- old/usr/src/uts/common/inet/ip/ipclassifier.c	2015-08-09 12:47:50.320403790 +0300
+++ new/usr/src/uts/common/inet/ip/ipclassifier.c	2015-08-09 12:47:50.336451308 +0300
@@ -2722,3 +2722,29 @@
 	return (1);
 }
 #endif
+
+conn_pid_node_list_hdr_t *
+conn_get_pid_list(conn_t *connp)
+{
+	conn_pid_node_list_hdr_t	*cph;
+
+	if (connp->conn_upper_handle != NULL) {
+		return (*connp->conn_upcalls->su_get_sock_pid_list)
+			(connp->conn_upper_handle);
+	} else if (!IPCL_IS_NONSTR(connp) && connp->conn_rq != NULL &&
+			connp->conn_rq->q_stream != NULL) {
+		return (sh_get_pid_list(connp->conn_rq->q_stream));
+	}
+
+	/* return an empty header */
+	cph = kmem_zalloc(sizeof (conn_pid_node_list_hdr_t), KM_SLEEP);
+	cph->cph_magic = CONN_PID_NODE_LIST_HDR_MAGIC;
+	cph->cph_contents = CONN_PID_NODE_LIST_HDR_NON;
+	cph->cph_pn_cnt = 0;
+	cph->cph_tot_size = sizeof (conn_pid_node_list_hdr_t);
+	cph->cph_flags = 0;
+	cph->cph_optional1 = 0;
+	cph->cph_optional2 = 0;
+
+	return (cph);
+}
--- old/usr/src/uts/common/inet/ipclassifier.h	2015-08-09 12:47:53.320681603 +0300
+++ new/usr/src/uts/common/inet/ipclassifier.h	2015-08-09 12:47:53.336199244 +0300
@@ -729,7 +729,7 @@
 extern void ip_free_helper_stream(conn_t *);
 extern int	ip_helper_stream_setup(queue_t *, dev_t *, int, int,
     cred_t *, boolean_t);
-
+conn_pid_node_list_hdr_t *conn_get_pid_list(conn_t *);
 #ifdef	__cplusplus
 }
 #endif
--- old/usr/src/uts/common/inet/mib2.h	2015-08-09 12:47:56.426916534 +0300
+++ new/usr/src/uts/common/inet/mib2.h	2015-08-09 12:47:56.442409704 +0300
@@ -28,6 +28,7 @@
 #include <netinet/in.h>	/* For in6_addr_t */
 #include <sys/tsol/label.h> /* For brange_t */
 #include <sys/tsol/label_macro.h> /* For brange_t */
+#include <sys/pidnode.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -185,6 +186,7 @@
  * There can be one of each of these tables per transport (MIB2_* above).
  */
 #define	EXPER_XPORT_MLP		105	/* transportMLPEntry */
+#define	EXPER_XPORT_PROC_INFO	106	/* conn_pid_node entry */
 
 /* Old names retained for compatibility */
 #define	MIB2_IP_20	MIB2_IP_ADDR
--- old/usr/src/uts/common/inet/sctp/sctp_snmp.c	2015-08-09 12:47:57.474443149 +0300
+++ new/usr/src/uts/common/inet/sctp/sctp_snmp.c	2015-08-09 12:47:57.488457330 +0300
@@ -528,6 +528,9 @@
 	mblk_t			*mp_conn_ctl = NULL;
 	mblk_t			*mp_conn_data;
 	mblk_t			*mp_conn_tail = NULL;
+	mblk_t			*mp_pidnode_ctl = NULL;
+	mblk_t			*mp_pidnode_data;
+	mblk_t			*mp_pidnode_tail = NULL;
 	mblk_t			*mp_local_ctl = NULL;
 	mblk_t			*mp_local_data;
 	mblk_t			*mp_local_tail = NULL;
@@ -553,6 +556,9 @@
 	int			idx;
 	mib2_sctp_t		sctp_mib;
 
+
+	conn_pid_node_list_hdr_t	*cph;
+
 	/*
 	 * Make copies of the original message.
 	 * mpctl will hold SCTP counters,
@@ -560,23 +566,27 @@
 	 */
 	mp_ret = copymsg(mpctl);
 	mp_conn_ctl = copymsg(mpctl);
+	mp_pidnode_ctl = copymsg(mpctl);
 	mp_local_ctl = copymsg(mpctl);
 	mp_rem_ctl = copymsg(mpctl);
 	mp_attr_ctl = copymsg(mpctl);
 
 	mpdata = mpctl->b_cont;
 
-	if (mp_conn_ctl == NULL || mp_local_ctl == NULL ||
-	    mp_rem_ctl == NULL || mp_attr_ctl == NULL || mpdata == NULL) {
+	if (mp_conn_ctl == NULL || mp_pidnode_ctl == NULL ||
+	    mp_local_ctl == NULL || mp_rem_ctl == NULL || mp_attr_ctl == NULL ||
+	    mpdata == NULL) {
 		freemsg(mp_attr_ctl);
 		freemsg(mp_rem_ctl);
 		freemsg(mp_local_ctl);
+		freemsg(mp_pidnode_ctl);
 		freemsg(mp_conn_ctl);
 		freemsg(mp_ret);
 		freemsg(mpctl);
 		return (NULL);
 	}
 	mp_conn_data = mp_conn_ctl->b_cont;
+	mp_pidnode_data = mp_pidnode_ctl->b_cont;
 	mp_local_data = mp_local_ctl->b_cont;
 	mp_rem_data = mp_rem_ctl->b_cont;
 	mp_attr_data = mp_attr_ctl->b_cont;
@@ -803,6 +813,17 @@
 		sce.sctpConnEntryInfo.ce_mss = sctp->sctp_mss;
 		(void) snmp_append_data2(mp_conn_data, &mp_conn_tail,
 		    (char *)&sce, sizeof (sce));
+		/* my data */
+		(void) snmp_append_data2(mp_pidnode_data, &mp_pidnode_tail,
+		    (char *)&sce, sizeof (sce));
+
+		cph = conn_get_pid_list(connp);
+
+		(void) snmp_append_data2(mp_pidnode_data, &mp_pidnode_tail,
+		    (char *)cph, cph->cph_tot_size);
+
+		kmem_free(cph, cph->cph_tot_size);
+		/* end of my data */
 		mlp.tme_connidx = idx++;
 		if (needattr)
 			(void) snmp_append_data2(mp_attr_ctl->b_cont,
@@ -833,6 +854,14 @@
 	optp->len = msgdsize(mp_conn_data);
 	qreply(q, mp_conn_ctl);
 
+	/* table of EXPER_XPORT_PROC_INFO */
+	optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_SCTP;
+	optp->name = EXPER_XPORT_PROC_INFO;
+	optp->len = msgdsize(mp_pidnode_data);
+	qreply(q, mp_pidnode_ctl);
+
 	/* assoc local address table */
 	optp = (struct opthdr *)&mp_local_ctl->b_rptr[
 	    sizeof (struct T_optmgmt_ack)];
--- old/usr/src/uts/common/inet/sockmods/socksctp.c	2015-08-09 12:47:58.395707031 +0300
+++ new/usr/src/uts/common/inet/sockmods/socksctp.c	2015-08-09 12:47:58.419157931 +0300
@@ -30,6 +30,7 @@
 #include <sys/buf.h>
 #include <sys/vfs.h>
 #include <sys/vnode.h>
+#include <sys/fcntl.h>
 #include <sys/debug.h>
 #include <sys/errno.h>
 #include <sys/stropts.h>
@@ -106,6 +107,8 @@
 static void sctp_assoc_xmitted(sock_upper_handle_t, boolean_t);
 static void sctp_assoc_properties(sock_upper_handle_t,
     struct sock_proto_props *);
+static conn_pid_node_list_hdr_t *
+    sctp_get_sock_pid_list(sock_upper_handle_t);
 
 sonodeops_t sosctp_sonodeops = {
 	sosctp_init,			/* sop_init	*/
@@ -168,6 +171,9 @@
 	sctp_assoc_xmitted,
 	NULL,			/* su_recv_space */
 	NULL,			/* su_signal_oob */
+	NULL,			/* su_set_error */
+	NULL,			/* su_closed */
+	sctp_get_sock_pid_list
 };
 
 /* ARGSUSED */
@@ -1773,6 +1779,11 @@
 		mutex_exit(&nfp->f_tlock);
 		setf(nfd, nfp);
 
+		/* add curproc to the pid list associated with that file */
+		if (nfp->f_vnode != NULL)
+			(void) VOP_IOCTL(nfp->f_vnode, F_FORKED,
+			    (intptr_t)curproc, FKIOCTL, kcred, NULL, NULL);
+
 		mutex_enter(&so->so_lock);
 
 		sosctp_assoc_move(ss, SOTOSSO(nso), ssa);
@@ -2230,3 +2241,17 @@
 	}
 	mutex_exit(&so->so_lock);
 }
+
+static conn_pid_node_list_hdr_t *
+sctp_get_sock_pid_list(sock_upper_handle_t handle)
+{
+	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
+	struct sonode *so;
+
+	if (ssa->ssa_type == SOSCTP_ASSOC)
+		so = &ssa->ssa_sonode->ss_so;
+	else
+		so = &((struct sctp_sonode *)handle)->ss_so;
+
+	return (so_get_sock_pid_list((sock_upper_handle_t)so));
+}
--- old/usr/src/uts/common/inet/tcp/tcp_stats.c	2015-08-09 12:47:59.503073919 +0300
+++ new/usr/src/uts/common/inet/tcp/tcp_stats.c	2015-08-09 12:47:59.517863475 +0300
@@ -30,6 +30,13 @@
 #include <sys/tsol/tnet.h>
 #include <sys/kstat.h>
 
+#include <sys/strsun.h>
+#include <sys/stropts.h>
+#include <sys/strsubr.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/uio.h>
+
 #include <inet/common.h>
 #include <inet/ip.h>
 #include <inet/tcp.h>
@@ -97,10 +104,14 @@
 	mblk_t			*mp_conn_tail;
 	mblk_t			*mp_attr_ctl = NULL;
 	mblk_t			*mp_attr_tail;
+	mblk_t			*mp_pidnode_ctl = NULL;
+	mblk_t			*mp_pidnode_tail;
 	mblk_t			*mp6_conn_ctl = NULL;
 	mblk_t			*mp6_conn_tail;
 	mblk_t			*mp6_attr_ctl = NULL;
 	mblk_t			*mp6_attr_tail;
+	mblk_t			*mp6_pidnode_ctl = NULL;
+	mblk_t			*mp6_pidnode_tail;
 	struct opthdr		*optp;
 	mib2_tcpConnEntry_t	tce;
 	mib2_tcp6ConnEntry_t	tce6;
@@ -118,6 +129,8 @@
 	mib2_tcp_t		tcp_mib;
 	size_t			tcp_mib_size, tce_size, tce6_size;
 
+	conn_pid_node_list_hdr_t	*cph;
+
 	/*
 	 * make a copy of the original message
 	 */
@@ -127,12 +140,16 @@
 	    (mpdata = mpctl->b_cont) == NULL ||
 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
 	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
+	    (mp_pidnode_ctl = copymsg(mpctl)) == NULL ||
 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
-	    (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
+	    (mp6_attr_ctl = copymsg(mpctl)) == NULL ||
+	    (mp6_pidnode_ctl = copymsg(mpctl)) == NULL) {
 		freemsg(mp_conn_ctl);
 		freemsg(mp_attr_ctl);
+		freemsg(mp_pidnode_ctl);
 		freemsg(mp6_conn_ctl);
 		freemsg(mp6_attr_ctl);
+		freemsg(mp6_pidnode_ctl);
 		freemsg(mpctl);
 		freemsg(mp2ctl);
 		return (NULL);
@@ -166,6 +183,7 @@
 
 	v4_conn_idx = v6_conn_idx = 0;
 	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
+	mp_pidnode_tail = mp6_pidnode_tail = NULL;
 
 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 		ipst = tcps->tcps_netstack->netstack_ip;
@@ -281,6 +299,21 @@
 			(void) snmp_append_data2(mp6_conn_ctl->b_cont,
 			    &mp6_conn_tail, (char *)&tce6, tce6_size);
 
+			/* my data */
+			/* push connt_t */
+			(void) snmp_append_data2(mp6_pidnode_ctl->b_cont,
+				&mp6_pidnode_tail, (char *)&tce6, tce6_size);
+
+			cph = conn_get_pid_list(connp);
+
+			/* push the header + conn pid nodes */
+			(void) snmp_append_data2(mp6_pidnode_ctl->b_cont,
+			    &mp6_pidnode_tail,
+			    (char *)cph, cph->cph_tot_size);
+
+			kmem_free(cph, cph->cph_tot_size);
+			/* end of my  data */
+
 			mlp.tme_connidx = v6_conn_idx++;
 			if (needattr)
 				(void) snmp_append_data2(mp6_attr_ctl->b_cont,
@@ -348,6 +381,21 @@
 				(void) snmp_append_data2(mp_conn_ctl->b_cont,
 				    &mp_conn_tail, (char *)&tce, tce_size);
 
+				/* my data */
+				/* push connt_t */
+				(void) snmp_append_data2(mp_pidnode_ctl->b_cont,
+				    &mp_pidnode_tail, (char *)&tce, tce_size);
+
+				cph = conn_get_pid_list(connp);
+
+				/* push the header + conn pid nodes */
+				(void) snmp_append_data2(mp_pidnode_ctl->b_cont,
+					&mp_pidnode_tail, (char *)cph,
+					cph->cph_tot_size);
+
+				kmem_free(cph, cph->cph_tot_size);
+				/* end of my code */
+
 				mlp.tme_connidx = v4_conn_idx++;
 				if (needattr)
 					(void) snmp_append_data2(
@@ -417,6 +465,30 @@
 		freemsg(mp6_attr_ctl);
 	else
 		qreply(q, mp6_attr_ctl);
+
+
+	/* table of EXPER_XPORT_PROC_INFO  ipv4 */
+	optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[
+		sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_TCP;
+	optp->name = EXPER_XPORT_PROC_INFO;
+	optp->len = msgdsize(mp_pidnode_ctl->b_cont);
+	if (optp->len == 0)
+		freemsg(mp_pidnode_ctl);
+	else
+		qreply(q, mp_pidnode_ctl);
+
+	/* table of EXPER_XPORT_PROC_INFO  ipv6 */
+	optp = (struct opthdr *)&mp6_pidnode_ctl->b_rptr[
+		sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_TCP6;
+	optp->name = EXPER_XPORT_PROC_INFO;
+	optp->len = msgdsize(mp6_pidnode_ctl->b_cont);
+	if (optp->len == 0)
+		freemsg(mp6_pidnode_ctl);
+	else
+		qreply(q, mp6_pidnode_ctl);
+
 	return (mp2ctl);
 }
 
--- old/usr/src/uts/common/inet/udp/udp_stats.c	2015-08-09 12:48:00.122147990 +0300
+++ new/usr/src/uts/common/inet/udp/udp_stats.c	2015-08-09 12:48:00.133230892 +0300
@@ -53,12 +53,16 @@
 	mblk_t			*mpdata;
 	mblk_t			*mp_conn_ctl;
 	mblk_t			*mp_attr_ctl;
+	mblk_t			*mp_pidnode_ctl;
 	mblk_t			*mp6_conn_ctl;
 	mblk_t			*mp6_attr_ctl;
+	mblk_t			*mp6_pidnode_ctl;
 	mblk_t			*mp_conn_tail;
 	mblk_t			*mp_attr_tail;
+	mblk_t			*mp_pidnode_tail;
 	mblk_t			*mp6_conn_tail;
 	mblk_t			*mp6_attr_tail;
+	mblk_t			*mp6_pidnode_tail;
 	struct opthdr		*optp;
 	mib2_udpEntry_t		ude;
 	mib2_udp6Entry_t	ude6;
@@ -78,6 +82,8 @@
 	mib2_udp_t		udp_mib;
 	size_t			udp_mib_size, ude_size, ude6_size;
 
+	conn_pid_node_list_hdr_t	*cph;
+
 
 	/*
 	 * make a copy of the original message
@@ -89,11 +95,16 @@
 	    (mpdata = mpctl->b_cont) == NULL ||
 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
 	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
+	    (mp_pidnode_ctl = copymsg(mpctl)) == NULL ||
 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
-	    (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
+	    (mp6_attr_ctl = copymsg(mpctl)) == NULL ||
+	    (mp6_pidnode_ctl = copymsg(mpctl)) == NULL) {
 		freemsg(mp_conn_ctl);
 		freemsg(mp_attr_ctl);
+		freemsg(mp_pidnode_ctl);
 		freemsg(mp6_conn_ctl);
+		freemsg(mp6_attr_ctl);
+		freemsg(mp6_pidnode_ctl);
 		freemsg(mpctl);
 		freemsg(mp2ctl);
 		return (0);
@@ -135,6 +146,7 @@
 	qreply(q, mpctl);
 
 	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
+	mp_pidnode_tail = mp6_pidnode_tail = NULL;
 	v4_conn_idx = v6_conn_idx = 0;
 
 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
@@ -249,6 +261,18 @@
 
 				(void) snmp_append_data2(mp_conn_ctl->b_cont,
 				    &mp_conn_tail, (char *)&ude, ude_size);
+				/* my data */
+				(void) snmp_append_data2(mp_pidnode_ctl->b_cont,
+				    &mp_pidnode_tail, (char *)&ude, ude_size);
+
+				cph = conn_get_pid_list(connp);
+				(void) snmp_append_data2(mp_pidnode_ctl->b_cont,
+				    &mp_pidnode_tail, (char *)cph,
+				    cph->cph_tot_size);
+
+				kmem_free(cph, cph->cph_tot_size);
+				/* end of my data */
+
 				mlp.tme_connidx = v4_conn_idx++;
 				if (needattr)
 					(void) snmp_append_data2(
@@ -292,6 +316,18 @@
 
 				(void) snmp_append_data2(mp6_conn_ctl->b_cont,
 				    &mp6_conn_tail, (char *)&ude6, ude6_size);
+				/* my dat */
+				(void) snmp_append_data2(
+				    mp6_pidnode_ctl->b_cont, &mp6_pidnode_tail,
+				    (char *)&ude6, ude6_size);
+
+				cph = conn_get_pid_list(connp);
+				(void) snmp_append_data2(
+				    mp6_pidnode_ctl->b_cont, &mp6_pidnode_tail,
+				    (char *)cph, cph->cph_tot_size);
+
+				kmem_free(cph, cph->cph_tot_size);
+				/* end of my data */
 				mlp.tme_connidx = v6_conn_idx++;
 				if (needattr)
 					(void) snmp_append_data2(
@@ -321,6 +357,17 @@
 	else
 		qreply(q, mp_attr_ctl);
 
+	/* table of EXPER_XPORT_PROC_INFO  ipv4 */
+	optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_UDP;
+	optp->name = EXPER_XPORT_PROC_INFO;
+	optp->len = msgdsize(mp_pidnode_ctl->b_cont);
+	if (optp->len == 0)
+		freemsg(mp_pidnode_ctl);
+	else
+		qreply(q, mp_pidnode_ctl);
+
 	/* IPv6 UDP endpoints */
 	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
 	    sizeof (struct T_optmgmt_ack)];
@@ -340,6 +387,17 @@
 	else
 		qreply(q, mp6_attr_ctl);
 
+	/* table of EXPER_XPORT_PROC_INFO  ipv6 */
+	optp = (struct opthdr *)&mp6_pidnode_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_UDP6;
+	optp->name = EXPER_XPORT_PROC_INFO;
+	optp->len = msgdsize(mp6_pidnode_ctl->b_cont);
+	if (optp->len == 0)
+		freemsg(mp6_pidnode_ctl);
+	else
+		qreply(q, mp6_pidnode_ctl);
+
 	return (mp2ctl);
 }
 
--- old/usr/src/uts/common/os/fio.c	2015-08-09 12:48:00.700382821 +0300
+++ new/usr/src/uts/common/os/fio.c	2015-08-09 12:48:00.713384166 +0300
@@ -837,11 +837,14 @@
  * Duplicate all file descriptors across a fork.
  */
 void
-flist_fork(uf_info_t *pfip, uf_info_t *cfip)
+flist_fork(proc_t *pp, proc_t *cp)
 {
 	int fd, nfiles;
 	uf_entry_t *pufp, *cufp;
 
+	uf_info_t *pfip = P_FINFO(pp);
+	uf_info_t *cfip = P_FINFO(cp);
+
 	mutex_init(&cfip->fi_lock, NULL, MUTEX_DEFAULT, NULL);
 	cfip->fi_rlist = NULL;
 
@@ -859,6 +862,14 @@
 		cufp->uf_alloc = pufp->uf_alloc;
 		cufp->uf_flag = pufp->uf_flag;
 		cufp->uf_busy = pufp->uf_busy;
+
+		if (cufp->uf_file != NULL && cufp->uf_file->f_vnode != NULL) {
+			VOP_IOCTL(cufp->uf_file->f_vnode, F_FORKED,
+				(intptr_t)cp,
+				FKIOCTL,
+				kcred, NULL, NULL);
+		}
+
 		if (pufp->uf_file == NULL) {
 			ASSERT(pufp->uf_flag == 0);
 			if (pufp->uf_busy) {
@@ -944,6 +955,9 @@
 	offset = fp->f_offset;
 
 	vp = fp->f_vnode;
+	if (vp != NULL)
+		VOP_IOCTL(vp, F_CLOSED, (intptr_t)ttoproc(curthread),
+			FKIOCTL, kcred, NULL, NULL);
 
 	error = VOP_CLOSE(vp, flag, count, offset, fp->f_cred, NULL);
 
--- old/usr/src/uts/common/os/fork.c	2015-08-09 12:48:01.845542853 +0300
+++ new/usr/src/uts/common/os/fork.c	2015-08-09 12:48:01.859597344 +0300
@@ -1189,7 +1189,7 @@
 	 */
 	uarea = PTOU(cp);
 	bcopy(PTOU(pp), uarea, sizeof (*uarea));
-	flist_fork(P_FINFO(pp), P_FINFO(cp));
+	flist_fork(pp, cp);
 
 	gethrestime(&uarea->u_start);
 	uarea->u_ticks = ddi_get_lbolt();
--- old/usr/src/uts/common/os/streamio.c	2015-08-09 12:48:02.495236925 +0300
+++ new/usr/src/uts/common/os/streamio.c	2015-08-09 12:48:02.521613831 +0300
@@ -77,6 +77,7 @@
 #include <sys/dld.h>
 #include <sys/zone.h>
 #include <c2/audit.h>
+#include <sys/fcntl.h>
 
 /*
  * This define helps improve the readability of streams code while
@@ -5682,6 +5683,18 @@
 	case FIONBIO:
 	case FIOASYNC:
 		return (0);	/* handled by the upper layer */
+	case F_FORKED: {
+		if (crp != kcred)
+			return (-1);
+		sh_insert_pid(stp, (proc_t *)arg);
+		return (0);
+	}
+	case F_CLOSED: {
+		if (crp != kcred)
+			return (-1);
+		sh_remove_pid(stp, (proc_t *)arg);
+		return (0);
+	}
 	}
 }
 
--- old/usr/src/uts/common/os/strsubr.c	2015-08-09 12:48:04.079859935 +0300
+++ new/usr/src/uts/common/os/strsubr.c	2015-08-09 12:48:04.117722869 +0300
@@ -651,11 +651,14 @@
 	mutex_init(&stp->sd_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&stp->sd_reflock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&stp->sd_qlock, NULL, MUTEX_DEFAULT, NULL);
+	mutex_init(&stp->sd_pid_list_lock, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&stp->sd_monitor, NULL, CV_DEFAULT, NULL);
 	cv_init(&stp->sd_iocmonitor, NULL, CV_DEFAULT, NULL);
 	cv_init(&stp->sd_refmonitor, NULL, CV_DEFAULT, NULL);
 	cv_init(&stp->sd_qcv, NULL, CV_DEFAULT, NULL);
 	cv_init(&stp->sd_zcopy_wait, NULL, CV_DEFAULT, NULL);
+	list_create(&stp->sd_pid_list, sizeof (pid_node_t),
+		offsetof(pid_node_t, pn_ref_link));
 	stp->sd_wrq = NULL;
 
 	return (0);
@@ -670,11 +673,13 @@
 	mutex_destroy(&stp->sd_lock);
 	mutex_destroy(&stp->sd_reflock);
 	mutex_destroy(&stp->sd_qlock);
+	mutex_destroy(&stp->sd_pid_list_lock);
 	cv_destroy(&stp->sd_monitor);
 	cv_destroy(&stp->sd_iocmonitor);
 	cv_destroy(&stp->sd_refmonitor);
 	cv_destroy(&stp->sd_qcv);
 	cv_destroy(&stp->sd_zcopy_wait);
+	list_destroy(&stp->sd_pid_list);
 }
 
 /*
@@ -3306,6 +3311,7 @@
 	stp->sd_nqueues = 0;
 	stp->sd_svcflags = 0;
 	stp->sd_copyflag = 0;
+	sh_insert_pid(stp, curproc);
 
 	return (stp);
 }
@@ -3316,6 +3322,8 @@
 void
 shfree(stdata_t *stp)
 {
+	pid_node_t *pn;
+
 	ASSERT(MUTEX_NOT_HELD(&stp->sd_lock));
 
 	stp->sd_wrq = NULL;
@@ -3339,9 +3347,98 @@
 	ASSERT(stp->sd_qhead == NULL);
 	ASSERT(stp->sd_qtail == NULL);
 	ASSERT(stp->sd_nqueues == 0);
+
+	mutex_enter(&stp->sd_pid_list_lock);
+	while ((pn = list_head(&stp->sd_pid_list)) != NULL) {
+		list_remove(&stp->sd_pid_list, pn);
+		kmem_free(pn, sizeof (*pn));
+	}
+	mutex_exit(&stp->sd_pid_list_lock);
+
 	kmem_cache_free(stream_head_cache, stp);
 }
 
+void
+sh_insert_pid(struct stdata *stp, proc_t *p)
+{
+	pid_node_t	*pn;
+
+	mutex_enter(&stp->sd_pid_list_lock);
+	pn = list_head(&stp->sd_pid_list);
+	while (pn != NULL && pn->pn_pid != p->p_pidp->pid_id) {
+		pn = list_next(&stp->sd_pid_list, pn);
+	}
+
+	if (pn != NULL) {
+		pn->pn_count++;
+	} else {
+		pn = kmem_zalloc(sizeof (*pn), KM_SLEEP);
+		list_link_init(&pn->pn_ref_link);
+		pn->pn_pid = p->p_pidp->pid_id;
+		pn->pn_count = 1;
+		list_insert_tail(&stp->sd_pid_list, pn);
+	}
+	mutex_exit(&stp->sd_pid_list_lock);
+}
+void
+sh_remove_pid(struct stdata *stp, proc_t *p)
+{
+	pid_node_t *pn;
+
+	mutex_enter(&stp->sd_pid_list_lock);
+	pn = list_head(&stp->sd_pid_list);
+	while (pn != NULL && pn->pn_pid != p->p_pidp->pid_id) {
+		pn = list_next(&stp->sd_pid_list, pn);
+	}
+
+	if (pn != NULL) {
+		if (pn->pn_count > 1)
+			pn->pn_count--;
+		else {
+			list_remove(&stp->sd_pid_list, pn);
+			kmem_free(pn, sizeof (*pn));
+		}
+	}
+	mutex_exit(&stp->sd_pid_list_lock);
+}
+
+conn_pid_node_list_hdr_t *
+sh_get_pid_list(struct stdata *stp)
+{
+	int sz, n = 0;
+	pid_node_t			*pn;
+	conn_pid_node_t			*cpn;
+	conn_pid_node_list_hdr_t	*cph;
+
+	mutex_enter(&stp->sd_pid_list_lock);
+
+	n = list_size(&stp->sd_pid_list);
+	sz = sizeof (conn_pid_node_list_hdr_t);
+	sz += (n > 1)?((n - 1) * sizeof (conn_pid_node_t)):0;
+
+	cph = kmem_zalloc(sz, KM_SLEEP);
+	cph->cph_magic = CONN_PID_NODE_LIST_HDR_MAGIC;
+	cph->cph_contents = CONN_PID_NODE_LIST_HDR_XTI;
+	cph->cph_pn_cnt = n;
+	cph->cph_tot_size = sz;
+	cph->cph_flags = 0;
+	cph->cph_optional1 = 0;
+	cph->cph_optional2 = 0;
+
+	if (cph->cph_pn_cnt > 0) {
+		cpn = cph->cph_cpns;
+		pn = list_head(&stp->sd_pid_list);
+		while (pn != NULL) {
+			PIDNODE2CONNPIDNODE(pn, cpn);
+			pn = list_next(&stp->sd_pid_list, pn);
+			cpn++;
+		}
+	}
+
+	mutex_exit(&stp->sd_pid_list_lock);
+	return (cph);
+}
+
 /*
  * Allocate a pair of queues and a syncq for the pair
  */
--- old/usr/src/uts/common/sys/Makefile	2015-08-09 12:48:05.289037784 +0300
+++ new/usr/src/uts/common/sys/Makefile	2015-08-09 12:48:05.333158800 +0300
@@ -133,6 +133,7 @@
 	crc32.h			\
 	cred.h			\
 	cred_impl.h		\
+	pidnode.h		\
 	crtctl.h		\
 	cryptmod.h		\
 	csiioctl.h		\
--- old/usr/src/uts/common/sys/fcntl.h	2015-08-09 12:48:06.129371918 +0300
+++ new/usr/src/uts/common/sys/fcntl.h	2015-08-09 12:48:06.141040578 +0300
@@ -165,6 +165,9 @@
 #define	F_SETLK_NBMAND	44	/* private */
 #endif /* _LP64 || _FILE_OFFSET_BITS == 32 */
 
+#define	F_FORKED	29
+#define	F_CLOSED	30
+
 #if 	defined(_LARGEFILE64_SOURCE)
 
 #if !defined(_LP64) || defined(_KERNEL)
--- old/usr/src/uts/common/sys/file.h	2015-08-09 12:48:07.270532337 +0300
+++ new/usr/src/uts/common/sys/file.h	2015-08-09 12:48:07.280764500 +0300
@@ -184,7 +184,7 @@
 #ifndef	_BOOT
 extern void closeall(uf_info_t *);
 #endif
-extern void flist_fork(uf_info_t *, uf_info_t *);
+extern void flist_fork(proc_t *, proc_t *);
 extern int closef(file_t *);
 extern int closeandsetf(int, file_t *);
 extern int ufalloc_file(int, file_t *);
--- old/usr/src/uts/common/sys/list.h	2015-08-09 12:48:08.251495842 +0300
+++ new/usr/src/uts/common/sys/list.h	2015-08-09 12:48:08.262607403 +0300
@@ -54,6 +54,7 @@
 void *list_next(list_t *, void *);
 void *list_prev(list_t *, void *);
 int list_is_empty(list_t *);
+uint64_t list_size(list_t *);
 
 void list_link_init(list_node_t *);
 void list_link_replace(list_node_t *, list_node_t *);
--- /dev/null	2015-08-09 12:48:09.000000000 +0300
+++ new/usr/src/uts/common/sys/pidnode.h	2015-08-09 12:48:09.020162716 +0300
@@ -0,0 +1,72 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2015 Mohamed A. Khalfella <khalfella@gmail.com>
+ */
+#ifndef _SYS_PIDNODE_H
+#define	_SYS_PIDNODE_H
+
+#include <sys/list.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	CONN_PID_NODE_LIST_HDR_MAGIC	0x5A7A0B1D
+
+#define	CONN_PID_NODE_LIST_HDR_NON	0
+#define	CONN_PID_NODE_LIST_HDR_SOC	1
+#define	CONN_PID_NODE_LIST_HDR_XTI	2
+#define	CONN_PID_NODE_LIST_HDR_UNX	3
+
+typedef struct conn_pid_node_s {
+	uint32_t	cpn_pid;
+} conn_pid_node_t;
+
+typedef struct conn_pid_node_list_hdr_s {
+	uint32_t	cph_magic;	/* CONN_PID_NODE_LIST_HDR_MAGIC */
+	uint32_t	cph_contents;	/* CONN_PID_NODE_LIST_HDR_* */
+	uint64_t	cph_pn_cnt;	/* # of conn_pid_node_t(s) */
+	uint64_t	cph_tot_size;	/* total size of hdr + nodes */
+	uint32_t	cph_flags;	/* not used yet */
+	uint32_t	cph_optional1;  /* an optional field, not used yet */
+	uint64_t	cph_optional2;  /* an optional field, not used yet */
+	conn_pid_node_t	cph_cpns[1];	/* arrary of conn_pid_node_t */
+} conn_pid_node_list_hdr_t;
+
+#if defined(_KERNEL)
+
+typedef struct pid_node_s {
+	list_node_t	pn_ref_link;
+	uint32_t	pn_count;
+	uint32_t	pn_pid;
+} pid_node_t;
+
+#endif /* defined(_KERNEL) */
+
+#define	PIDNODE2CONNPIDNODE(pn, cpn)	(cpn)->cpn_pid = (pn)->pn_pid
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_PIDNODE_H */
--- old/usr/src/uts/common/sys/socket_proto.h	2015-08-09 12:48:09.316410552 +0300
+++ new/usr/src/uts/common/sys/socket_proto.h	2015-08-09 12:48:09.331545849 +0300
@@ -30,6 +30,7 @@
 #endif
 
 #include <sys/socket.h>
+#include <sys/pidnode.h>
 
 /*
  * Generation count
@@ -200,6 +201,8 @@
 	void	(*su_zcopy_notify)(sock_upper_handle_t);
 	void	(*su_set_error)(sock_upper_handle_t, int);
 	void	(*su_closed)(sock_upper_handle_t);
+	conn_pid_node_list_hdr_t *	(*su_get_sock_pid_list)
+			(sock_upper_handle_t);
 };
 
 #define	SOCK_UC_VERSION		sizeof (sock_upcalls_t)
--- old/usr/src/uts/common/sys/socketvar.h	2015-08-09 12:48:10.036783174 +0300
+++ new/usr/src/uts/common/sys/socketvar.h	2015-08-09 12:48:10.046766054 +0300
@@ -46,6 +46,7 @@
 #include <sys/stream.h>
 #include <sys/t_lock.h>
 #include <sys/cred.h>
+#include <sys/pidnode.h>
 #include <sys/vnode.h>
 #include <sys/file.h>
 #include <sys/param.h>
@@ -244,6 +245,10 @@
 	struct sof_instance	*so_filter_top;		/* top of stack */
 	struct sof_instance	*so_filter_bottom;	/* bottom of stack */
 	clock_t			so_filter_defertime;	/* time when deferred */
+
+	/* pid list */
+	list_t			so_pid_list;
+	kmutex_t		so_pid_list_lock;
 };
 
 #define	SO_HAVE_DATA(so)						\
@@ -953,6 +958,9 @@
  * These types match those corresponding in the sonode structure.
  * This is not a published interface, and may change at any time.
  */
+
+#define	ADRSTRLEN (2 * sizeof (uint64_t) + 1)
+
 struct sockinfo {
 	uint_t		si_size;		/* real length of this struct */
 	short		si_family;
@@ -970,6 +978,11 @@
 	char		si_faddr_sun_path[MAXPATHLEN + 1];
 	boolean_t	si_faddr_noxlate;
 	zoneid_t	si_szoneid;
+	char		si_son_straddr[ADRSTRLEN];
+	char		si_lvn_straddr[ADRSTRLEN];
+	char		si_fvn_straddr[ADRSTRLEN];
+	uint_t		si_pn_cnt;
+	conn_pid_node_t	si_pns[1];
 };
 
 /*
--- old/usr/src/uts/common/sys/strsubr.h	2015-08-09 12:48:10.745324635 +0300
+++ new/usr/src/uts/common/sys/strsubr.h	2015-08-09 12:48:10.757122494 +0300
@@ -44,6 +44,7 @@
 #include <sys/proc.h>
 #include <sys/netstack.h>
 #include <sys/modhash.h>
+#include <sys/pidnode.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -241,6 +242,8 @@
 	uint_t		sd_copyflag;	/* copy-related flags */
 	zoneid_t	sd_anchorzone;	/* Allow removal from same zone only */
 	struct msgb	*sd_cmdblk;	/* reply from _I_CMD */
+	list_t		sd_pid_list;
+	kmutex_t	sd_pid_list_lock;
 } stdata_t;
 
 /*
@@ -1140,6 +1143,9 @@
 extern int strwaitbuf(size_t, int);
 extern int strwaitq(stdata_t *, int, ssize_t, int, clock_t, int *);
 extern struct stdata *shalloc(queue_t *);
+extern void sh_insert_pid(struct stdata *, proc_t *);
+extern void sh_remove_pid(struct stdata *, proc_t *);
+extern conn_pid_node_list_hdr_t *sh_get_pid_list(struct stdata *);
 extern void shfree(struct stdata *s);
 extern queue_t *allocq(void);
 extern void freeq(queue_t *);
--- old/usr/src/uts/common/syscall/fcntl.c	2015-08-09 12:48:11.273671856 +0300
+++ new/usr/src/uts/common/syscall/fcntl.c	2015-08-09 12:48:11.287872897 +0300
@@ -178,6 +178,13 @@
 				f_setfd(retval, FD_CLOEXEC);
 			}
 		}
+
+		if (error == 0 && fp->f_vnode != NULL) {
+			(void) VOP_IOCTL(fp->f_vnode, F_FORKED,
+				(intptr_t) p, FKIOCTL,
+				kcred, NULL, NULL);
+		}
+
 		goto done;
 
 	case F_DUP2FD_CLOEXEC:
@@ -214,6 +221,15 @@
 			fp->f_count++;
 			mutex_exit(&fp->f_tlock);
 			releasef(fdes);
+
+			/* assume we have forked successfully */
+
+			if (fp->f_vnode != NULL) {
+				(void) VOP_IOCTL(fp->f_vnode, F_FORKED,
+					(intptr_t) p, FKIOCTL,
+					kcred, NULL, NULL);
+			}
+
 			if ((error = closeandsetf(iarg, fp)) == 0) {
 				if (cmd == F_DUP2FD_CLOEXEC) {
 					f_setfd(iarg, FD_CLOEXEC);
@@ -224,6 +240,12 @@
 				if (fp->f_count > 1) {
 					fp->f_count--;
 					mutex_exit(&fp->f_tlock);
+					if (fp->f_vnode != NULL) {
+						VOP_IOCTL(fp->f_vnode, F_CLOSED,
+							(intptr_t) p, FKIOCTL,
+							kcred, NULL, NULL);
+					}
+
 				} else {
 					mutex_exit(&fp->f_tlock);
 					(void) closef(fp);
