Subject: pkg/29517: net/oidentd lookups of IPv6 connections fail on NetBSD 2.0
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <woodstoc@quina.moeckel.org>
List: pkgsrc-bugs
Date: 02/23/2005 22:51:00
>Number:         29517
>Category:       pkg
>Synopsis:       net/oidentd lookups of IPv6 connections fail on NetBSD 2.0
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Feb 23 22:51:00 +0000 2005
>Originator:     Hans Rosenfeld
>Release:        NetBSD 2.0
>Organization:
>Environment:
System: NetBSD quina.moeckel.org 2.0.1 NetBSD 2.0.1 (QUINA) #2: Tue Feb 22 21:17:45 CET 2005 woodstoc@quina.moeckel.org:/usr/obj/sys/arch/i386/compile/QUINA i386
Architecture: i386
Machine: i386

>Description:
	Lookups of IPv6 connections fail on 2.0 returning NO-USER to all queries.
	This is because oidentd still wants to use the tcb6 structure for those lookups,
	but tcb6 was removed from netinet/tcp_subr.c (version 1.151, 2003/09/04 09:17:01),
	tcbtable has to be used instead (as is already done for IPv4 connections).

>How-To-Repeat:
	Install net/oidentd on a IPv6-capable machine running NetBSD 2.0 and try to query
	it for IPv6 connections.

>Fix:
	This patch to src/kernel/netbsd.c changes the IPv6 lookup routines to use tcbtable
	instead of tcb6.

--- netbsd.c.orig	2003-02-12 03:15:59.000000000 +0100
+++ netbsd.c	2005-02-23 23:24:02.000000000 +0100
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <netinet/in.h>
@@ -99,7 +100,7 @@
 	kinfo->nl[N_TCB].n_name = "_tcbtable";
 
 #ifdef WANT_IPV6
-	kinfo->nl[N_TCB6].n_name = "_tcb6";
+	kinfo->nl[N_TCB6].n_name = "_tcbtable";
 #else
 	kinfo->nl[N_TCB6].n_name = "_oidentd_nonexistent";
 #endif
@@ -162,7 +163,7 @@
 	if (tcbtablep == NULL)
 		return (NULL);
 
-	kpcbp = tcbtablep->inpt_queue.cqh_first;
+	kpcbp = (struct inpcb *) tcbtablep->inpt_queue.cqh_first;
 	while (kpcbp != (struct inpcb *) ktcbtablep) {
 		if (getbuf((u_long) kpcbp, &pcb, sizeof(struct inpcb)) == -1)
 			break;
@@ -185,7 +186,7 @@
 			return (pcb.inp_socket);
 		}
 
-		kpcbp = pcb.inp_queue.cqe_next;
+		kpcbp = (struct inpcb *) pcb.inp_queue.cqe_next;
 	}
 
 	return (NULL);
@@ -327,35 +328,32 @@
 ** Returns NULL if no match.
 */
 
-static struct socket *getlist6(	struct in6pcb *tcb6,
+static struct socket *getlist6(	struct inpcbtable *tcbtablep,
+								struct inpcbtable *ktcbtablep,
 								in_port_t lport,
 								in_port_t fport,
 								const struct in6_addr *laddr,
 								const struct in6_addr *faddr)
 {
-	struct in6pcb *tcb6_cur, tcb6_temp;
+	struct in6pcb *kpcbp, pcb;
 
-	if (tcb6 == NULL)
+	if (tcbtablep == NULL)
 		return (NULL);
 
-	tcb6_cur = tcb6;
-
-	memcpy(&tcb6_temp, tcb6, sizeof(tcb6_temp));
-
-	do {
-		if (tcb6_temp.in6p_fport == fport &&
-			tcb6_temp.in6p_lport == lport &&
-			IN6_ARE_ADDR_EQUAL(&tcb6_temp.in6p_laddr, laddr) &&
-			IN6_ARE_ADDR_EQUAL(&tcb6_temp.in6p_faddr, faddr))
+	kpcbp = (struct in6pcb *) tcbtablep->inpt_queue.cqh_first;
+	while (kpcbp != (struct in6pcb *) ktcbtablep) {
+		if (getbuf((u_long) kpcbp, &pcb, sizeof(struct in6pcb)) == -1)
+			break;
+		if (pcb.in6p_fport == fport &&
+			pcb.in6p_lport == lport &&
+			IN6_ARE_ADDR_EQUAL(&pcb.in6p_laddr, laddr) &&
+			IN6_ARE_ADDR_EQUAL(&pcb.in6p_faddr, faddr))
 		{
-			return (tcb6_temp.in6p_socket);
+			return (pcb.in6p_socket);
 		}
 
-		tcb6_cur = tcb6_temp.in6p_next;
-		if (getbuf((u_long) tcb6_cur, &tcb6_temp, sizeof(tcb6_temp)) == -1)
-			break;
-	} while ((u_long) tcb6_cur != kinfo->nl[N_TCB6].n_value);
-
+		kpcbp = (struct in6pcb *) pcb.in6p_queue.cqe_next;
+	}
 	return (NULL);
 }
 
@@ -369,15 +367,16 @@
 				struct sockaddr_storage *faddr)
 {
 	struct socket *sockp, sock;
-	struct in6pcb tcb6;
+	struct inpcbtable tcbtable;
 	int ret;
 
-	ret = getbuf(kinfo->nl[N_TCB6].n_value, &tcb6, sizeof(tcb6));
+	ret = getbuf(kinfo->nl[N_TCB6].n_value, &tcbtable, sizeof(tcbtable));
 	if (ret == -1)
 		return (-1);
 
-	sockp = getlist6(&tcb6, lport, fport,
-				&SIN6(laddr)->sin6_addr, &SIN6(faddr)->sin6_addr);
+	sockp = getlist6(&tcbtable,
+				(struct inpcbtable *) kinfo->nl[N_TCB6].n_value,
+				lport, fport, &SIN6(laddr)->sin6_addr, &SIN6(faddr)->sin6_addr);
 
 	if (sockp == NULL)
 		return (-1);