Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 May 2010 18:40:34 +0200
From:      Jeremie Le Hen <jeremie@le-hen.org>
To:        bug-followup@FreeBSD.org
Cc:        freebsd-net@FreeBSD.org, bz@FreeBSD.org, jeremie@le-hen.org
Subject:   Re: bin/116643: [patch] [request] fstat(1): add INET/INET6 socket details as in NetBSD and OpenBSD
Message-ID:  <20100505164033.GF56740@felucia.tataz.chchile.org>

next in thread | raw e-mail | index | archive | help

--XOIedfhf+7KOe/yw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

I've updated the patch so it compiles with -CURRENT.  Also the proposed
behaviour is opt-in through the -i option.

This PR has been waiting for two years and a half.  I propose that we
try to find a consensus whether it is useful or not and then close it,
no matter if it has been accepted or not.

Regards,
-- 
Jeremie Le Hen

Humans are born free and equal.  But some are more equal than others.
					    Coluche

--XOIedfhf+7KOe/yw
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="fstat-i.diff"

Index: fstat.1
===================================================================
RCS file: /mnt/repos/freebsd-cvsroot/src/usr.bin/fstat/fstat.1,v
retrieving revision 1.28
diff -u -p -u -p -r1.28 fstat.1
--- fstat.1	9 Jul 2009 16:40:00 -0000	1.28
+++ fstat.1	5 May 2010 16:39:49 -0000
@@ -40,7 +40,7 @@
 .Nd identify active files
 .Sh SYNOPSIS
 .Nm
-.Op Fl fmnv
+.Op Fl fimnv
 .Op Fl M Ar core
 .Op Fl N Ar system
 .Op Fl p Ar pid
@@ -68,6 +68,8 @@ directory
 .Pa /usr/src
 resides, type
 .Dq Li fstat -f /usr/src .
+.It Fl i
+Print extended socket informations for internet sockets.
 .It Fl M
 Extract values associated with the name list from the specified core
 instead of the default
@@ -213,6 +215,16 @@ connected unix domain stream socket.
 A unidirectional unix domain socket indicates the direction of flow with
 an arrow (``<-'' or ``->''), and a full duplex socket shows a double arrow
 (``<->'').
+.Pp
+For internet sockets,
+the
+.Fl i
+flag will make
+.Nm
+mimic other BSDs behaviour that is attempt to print the internet address and
+port for the local connection.
+If a socket is connected it also prints the remote internet address and port.
+An asterisk (``*'') is used to indicate an INADDR_ANY binding.
 .Sh SEE ALSO
 .Xr netstat 1 ,
 .Xr nfsstat 1 ,
Index: fstat.c
===================================================================
RCS file: /mnt/repos/freebsd-cvsroot/src/usr.bin/fstat/fstat.c,v
retrieving revision 1.72
diff -u -p -u -p -r1.72 fstat.c
--- fstat.c	20 Aug 2009 10:57:14 -0000	1.72
+++ fstat.c	5 May 2010 16:26:45 -0000
@@ -87,6 +87,8 @@ __FBSDID("$FreeBSD: src/usr.bin/fstat/fs
 #include <netinet/ip.h>
 #include <netinet/in_pcb.h>
 
+#include <arpa/inet.h>
+
 #include <ctype.h>
 #include <err.h>
 #include <fcntl.h>
@@ -126,6 +128,7 @@ int 	checkfile; /* true if restricting t
 int	nflg;	/* (numerical) display f.s. and rdev as dev_t */
 int	vflg;	/* display errors in locating kernel data objects etc... */
 int	mflg;	/* include memory-mapped files */
+int	iflg;	/* display inet socket details */
 
 
 struct file **ofiles;	/* buffer of pointers to file structures */
@@ -153,6 +156,7 @@ int  nfs_filestat(struct vnode *vp, stru
 int  devfs_filestat(struct vnode *vp, struct filestat *fsp);
 char *getmnton(struct mount *m);
 void pipetrans(struct pipe *pi, int i, int flag);
+const char *inet6_addrstr(struct in6_addr *);
 void socktrans(struct socket *sock, int i);
 void ptstrans(struct tty *tp, int i, int flag);
 void getinetproto(int number);
@@ -169,11 +173,14 @@ main(int argc, char **argv)
 	arg = 0;
 	what = KERN_PROC_PROC;
 	nlistf = memf = NULL;
-	while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1)
+	while ((ch = getopt(argc, argv, "fimnp:u:vN:M:")) != -1)
 		switch((char)ch) {
 		case 'f':
 			fsflg = 1;
 			break;
+		case 'i':
+			iflg = 1;
+			break;
 		case 'M':
 			memf = optarg;
 			break;
@@ -772,6 +779,31 @@ bad:
 	printf("* error\n");
 }
 
+const char *
+inet6_addrstr(struct in6_addr *p)
+{
+	struct sockaddr_in6 sin6;
+	static char hbuf[NI_MAXHOST];
+	const int niflags = NI_NUMERICHOST;
+
+	memset(&sin6, 0, sizeof(sin6));
+	sin6.sin6_family = AF_INET6;
+	sin6.sin6_len = sizeof(struct sockaddr_in6);
+	sin6.sin6_addr = *p;
+	if (IN6_IS_ADDR_LINKLOCAL(p) &&
+	    *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
+		sin6.sin6_scope_id =
+		    ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+		sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
+	    }
+
+	    if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+		hbuf, sizeof(hbuf), NULL, 0, niflags))
+		    return "invalid";
+
+	    return hbuf;
+}
+
 void
 socktrans(struct socket *sock, int i)
 {
@@ -791,6 +823,7 @@ socktrans(struct socket *sock, int i)
 	struct unpcb	unpcb;
 	int len;
 	char dname[32];
+	char xaddrbuf[NI_MAXHOST + 2];
 
 	PREFIX(i);
 
@@ -841,19 +874,72 @@ socktrans(struct socket *sock, int i)
 	 */
 	switch(dom.dom_family) {
 	case AF_INET:
+		getinetproto(proto.pr_protocol);
+		if (proto.pr_protocol == IPPROTO_TCP ||
+		    proto.pr_protocol == IPPROTO_UDP) {
+			if (so.so_pcb == NULL)
+				break;
+			if (kvm_read(kd, (u_long)so.so_pcb,
+			    (char *)&inpcb, sizeof(struct inpcb))
+			    != sizeof(struct inpcb)) {
+				dprintf(stderr,
+				    "can't read inpcb at %p\n",
+				    (void *)so.so_pcb);
+				goto bad;
+			}
+			if (proto.pr_protocol == IPPROTO_TCP)
+				printf(" %lx", (u_long)inpcb.inp_ppcb);
+			else
+				printf(" %lx", (u_long)so.so_pcb);
+			if (!iflg)
+				break;
+			printf(" %s:%hu",
+			    inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" :
+			    inet_ntoa(inpcb.inp_laddr),
+			    ntohs(inpcb.inp_lport));
+			if (inpcb.inp_fport) {
+				printf(" <-> %s:%hu",
+				    inpcb.inp_faddr.s_addr == INADDR_ANY ?
+				    "*" : inet_ntoa(inpcb.inp_faddr),
+				    ntohs(inpcb.inp_fport));
+			}
+		}
+		else if (so.so_pcb)
+			printf(" %lx", (u_long)so.so_pcb);
+		break;
 	case AF_INET6:
 		getinetproto(proto.pr_protocol);
-		if (proto.pr_protocol == IPPROTO_TCP ) {
-			if (so.so_pcb) {
-				if (kvm_read(kd, (u_long)so.so_pcb,
-				    (char *)&inpcb, sizeof(struct inpcb))
-				    != sizeof(struct inpcb)) {
-					dprintf(stderr,
-					    "can't read inpcb at %p\n",
-					    (void *)so.so_pcb);
-					goto bad;
-				}
+		if (proto.pr_protocol == IPPROTO_TCP ||
+		    proto.pr_protocol == IPPROTO_UDP) {
+			if (so.so_pcb == NULL)
+				break;
+			if (kvm_read(kd, (u_long)so.so_pcb,
+			    (char *)&inpcb, sizeof(struct inpcb))
+			    != sizeof(struct inpcb)) {
+				dprintf(stderr,
+				    "can't read inpcb at %p\n",
+				    (void *)so.so_pcb);
+				goto bad;
+			}
+			if (proto.pr_protocol == IPPROTO_TCP)
 				printf(" %lx", (u_long)inpcb.inp_ppcb);
+			else
+				printf(" %lx", (u_long)so.so_pcb);
+			if (!iflg)
+				break;
+			snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
+			    inet6_addrstr(&inpcb.in6p_laddr));
+			printf(" %s:%hu",
+			    IN6_IS_ADDR_UNSPECIFIED(&inpcb.in6p_laddr) ?
+			    "*" : xaddrbuf,
+			    ntohs(inpcb.inp_lport));
+			if (inpcb.inp_fport) {
+				snprintf(xaddrbuf, sizeof(xaddrbuf),
+				    "[%s]", inet6_addrstr(&inpcb.in6p_faddr));
+				printf(" <-> %s:%hu",
+				    IN6_IS_ADDR_UNSPECIFIED(&inpcb.in6p_faddr)?
+				    "*" : xaddrbuf,
+				    ntohs(inpcb.inp_fport));
 			}
 		}
 		else if (so.so_pcb)

--XOIedfhf+7KOe/yw--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100505164033.GF56740>