Subject: bin/9199: fstat(1) lacks IPv6 support
To: None <gnats-bugs@gnats.netbsd.org>
From: None <ura@hiru.aoba.yokohama.jp>
List: netbsd-bugs
Date: 01/15/2000 13:12:53
>Number:         9199
>Category:       bin
>Synopsis:       fstat(1) lacks IPv6 support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jan 15 13:09:04 2000
>Last-Modified:
>Originator:     URA Hiroshi
>Organization:
URA Hiroshi		E-mail: ura@hiru.aoba.yokohama.jp
>Release:        NetBSD-current 1.4P (1999/12/17)
>Environment:
System: NetBSD uzuki.hiru.aoba.yokohama.jp 1.4P NetBSD 1.4P (UZUKI) #26: Fri Dec 17 18:55:34 JST 1999 root@:/usr/local/src/NetBSD/current/src/sys/arch/sparc/compile/UZUKI sparc


>Description:
  When the file discriptor points the internet socket, fstat(1) indicates
the IPv4 address and port for the local end and/or the remote.  But, when
the file discriptor points the internet6 socket, fstat(1) doesn't indicate.

If the IPv6 address specfies, the IPv6 address is wrapped in square bracket
(e.g. [2345:678:9ab:1000::1]). If the IPv6 address doesn't specfiy, a ``*''
is used for indication. 


>How-To-Repeat:
  Try the following commands.
    # fstat | egrep internet6

>Fix:
  Apply this patch.

Index: fstat.c
===================================================================
RCS file: /cvsroot/netbsd/basesrc/usr.bin/fstat/fstat.c,v
retrieving revision 1.37
diff -u -u -r1.37 fstat.c
--- fstat.c	1999/08/02 17:39:13	1.37
+++ fstat.c	2000/01/15 10:42:49
@@ -81,6 +81,10 @@
 #include <netinet/ip.h>
 #include <netinet/in_pcb.h>
 
+#include <netinet/ip6.h>
+#include <netinet6/in6_systm.h>
+#include <netinet6/in6_pcb.h>
+
 #include <arpa/inet.h>
 
 #include <ctype.h>
@@ -618,9 +622,12 @@
 	struct protosw	proto;
 	struct domain	dom;
 	struct inpcb	inpcb;
+	struct in6pcb	in6pcb;
 	struct unpcb	unpcb;
 	int len;
 	char dname[32];
+	char addrbuf[INET6_ADDRSTRLEN];
+	char xaddrbuf[INET6_ADDRSTRLEN + 2];
 
 	PREFIX(i);
 
@@ -682,8 +689,7 @@
 			    inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" :
 			    inet_ntoa(inpcb.inp_laddr), ntohs(inpcb.inp_lport));
 			if (inpcb.inp_fport) {
-				printf(" <-> ");
-				printf("%s:%d",
+				printf(" <-> %s:%d",
 				    inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" :
 				    inet_ntoa(inpcb.inp_faddr),
 				    ntohs(inpcb.inp_fport));
@@ -705,6 +711,61 @@
 				    inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" :
 				    inet_ntoa(inpcb.inp_faddr),
 				    ntohs(inpcb.inp_fport));
+		} else if (so.so_pcb)
+			printf(" %lx", (long)so.so_pcb);
+		break;
+	case AF_INET6:
+		getinetproto(proto.pr_protocol);
+		if (proto.pr_protocol == IPPROTO_TCP) {
+			if (so.so_pcb == NULL)
+				break;
+			if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb,
+			    sizeof(struct in6pcb)) != sizeof(struct in6pcb)) {
+				dprintf("can't read in6pcb at %p", so.so_pcb);
+				goto bad;
+			}
+			printf(" %lx", (long)in6pcb.in6p_ppcb);
+			sprintf(xaddrbuf, "[%s]", 
+ 			    inet_ntop(AF_INET6, &in6pcb.in6p_laddr,
+				addrbuf, sizeof(addrbuf)));
+			printf(" %s:%d",
+			    IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_laddr) ? "*" :
+			    xaddrbuf,
+			    ntohs(in6pcb.in6p_lport));
+			if (in6pcb.in6p_fport) {
+				sprintf(xaddrbuf, "[%s]", 
+				    inet_ntop(AF_INET6, &in6pcb.in6p_faddr,
+					addrbuf, sizeof(addrbuf)));
+				printf(" <-> %s:%d",
+			            IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_faddr) ? "*" :
+				    xaddrbuf,
+				    ntohs(in6pcb.in6p_fport));
+			}
+		} else if (proto.pr_protocol == IPPROTO_UDP) {
+			if (so.so_pcb == NULL)
+				break;
+			if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb,
+			    sizeof(struct in6pcb)) != sizeof(struct in6pcb)) {
+				dprintf("can't read inpcb at %p", so.so_pcb);
+				goto bad;
+			}
+			printf(" %lx", (long)so.so_pcb);
+			sprintf(xaddrbuf, "[%s]", 
+			    inet_ntop(AF_INET6, &in6pcb.in6p_laddr,
+				addrbuf, sizeof(addrbuf)));
+			printf(" %s:%d",
+		            IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_laddr) ? "*" :
+			    xaddrbuf,
+			    ntohs(in6pcb.in6p_lport));
+			if (in6pcb.in6p_fport) {
+				sprintf(xaddrbuf, "[%s]", 
+				    inet_ntop(AF_INET6, &in6pcb.in6p_faddr,
+					addrbuf, sizeof(addrbuf)));
+				printf(" <-> %s:%d",
+			            IN6_IS_ADDR_UNSPECIFIED(&in6pcb.in6p_faddr) ? "*" :
+				    xaddrbuf,
+				    ntohs(in6pcb.in6p_fport));
+			}
 		} else if (so.so_pcb)
 			printf(" %lx", (long)so.so_pcb);
 		break;
>Audit-Trail:
>Unformatted: