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