misc/116643: [patch] fstat: add INET/INET6 socket details as in
NetBSD and OpenBSD
Jeremie Le Hen
jeremie at le-hen.org
Tue Sep 25 16:20:02 PDT 2007
>Number: 116643
>Category: misc
>Synopsis: [patch] fstat: add INET/INET6 socket details as in NetBSD and OpenBSD
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Sep 25 23:20:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Jeremie Le Hen <jeremie at le-hen.org>
>Release: FreeBSD 7.0-CURRENT i386
>Organization:
>Environment:
FreeBSD 7.0-CURRENT
>Description:
This patch adds socket details to AF_INET/AF_INET6 output of fstat.
Currently, we have an output like this:
root sshd 721 3* internet stream tcp c3f08e10
tataz ssh 1271 3* internet stream tcp c4611870
With this patch, we have:
root sshd 721 3* internet stream tcp c3f08e10 *:22
tataz ssh 1271 3* internet stream tcp c4611870 192.168.1.3:50995 <-> 192.168.1.2:22
>How-To-Repeat:
>Fix:
The patch below implements this behaviour. It has been ported from
NetBSD and OpenBSD. Note that due to lack of inet6 connectivity, I
couldn't test the AF_INET6 case.
--- fstat_inetsock_detail.diff begins here ---
Index: fstat.c
===================================================================
RCS file: /mnt/octobre/space/freebsd-cvs/src/usr.bin/fstat/fstat.c,v
retrieving revision 1.64
diff -u -p -r1.64 fstat.c
--- fstat.c 9 Mar 2007 16:21:40 -0000 1.64
+++ fstat.c 25 Sep 2007 23:04:31 -0000
@@ -86,6 +86,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>
@@ -151,6 +153,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 getinetproto(int number);
int getfname(const char *filename);
@@ -757,6 +760,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)
{
@@ -776,6 +804,7 @@ socktrans(struct socket *sock, int i)
struct unpcb unpcb;
int len;
char dname[32];
+ char xaddrbuf[NI_MAXHOST + 2];
PREFIX(i);
@@ -826,19 +855,68 @@ 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);
+ 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);
+ snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
+ inet6_addrstr(&inpcb.in6p_laddr));
+ printf(" %s:%hu",
+ IN6_IS_ADDR_UNSPECIFIED(&inpcb.in6p_laddr) ?
+ "*" : xaddrbuf,
+ ntohs(inpcb.in6p_lport));
+ if (inpcb.in6p_fport) {
+ snprintf(xaddrbuf, sizeof(xaddrbuf),
+ "[%s]", inet6_addrstr(&inpcb.in6p_faddr));
+ printf(" <-> %s:%hu",
+ IN6_IS_ADDR_UNSPECIFIED(&inpcb.in6p_faddr)?
+ "*" : xaddrbuf,
+ ntohs(inpcb.in6p_fport));
}
}
else if (so.so_pcb)
--- fstat_inetsock_detail.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list