bin/116643: [patch] [request] fstat(1): add INET/INET6 socket details as in NetBSD and OpenBSD

Jeremie Le Hen jeremie at le-hen.org
Wed May 5 16:50:03 UTC 2010


The following reply was made to PR bin/116643; it has been noted by GNATS.

From: Jeremie Le Hen <jeremie at le-hen.org>
To: bug-followup at FreeBSD.org
Cc: bz at FreeBSD.org, freebsd-net at FreeBSD.org, jeremie at le-hen.org
Subject: Re: bin/116643: [patch] [request] fstat(1): add INET/INET6 socket
 details as in NetBSD and OpenBSD
Date: Wed, 5 May 2010 18:40:34 +0200

 --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--


More information about the freebsd-net mailing list