Subject: kern/22579: ipfilter should use linklocal address in ipfr_fastroute6()
To: None <gnats-bugs@gnats.netbsd.org>
From: KOZUKA Masahiro <ma-kun@kozuka.jp>
List: netbsd-bugs
Date: 08/23/2003 13:20:07
>Number:         22579
>Category:       kern
>Synopsis:       ipfilter should use linklocal address in ipfr_fastroute6()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Aug 23 06:43:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     KOZUKA Masahiro
>Release:        NetBSD 1.6.1
>Organization:
Kyoto University
>Environment:
System: NetBSD no30 1.6.1 NetBSD 1.6.1 (GENERIC) #45: Sat Aug 23 09:31:06 JST 2003 kozuka@no30:/usr/home/kozuka/netbsd/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
	By PR#22157 return-rst works with IPv6 in --current. But
	in repliying RST packet to linklocal address, rtalloc() in
	ipfr_fastroute6 fails because in the case of linklocal address,
	interface index must be set in second dst6->sin6_addr's short
	(dst6->sin6_addr.s6_addr16[1]).
>How-To-Repeat:
	ipf6.conf
	 block return-rst in log on pcn0 proto tcp from fe80::2 to fe80::1
	Try to connect from fe80::2 to fe80::1(host working ipfilter),
	the packet will be dropped, but RST not sent to fe80::2.
>Fix:
	See the diff below.
	First part already fixed by PR#22157.

diff -u -r netinet.orig/ip_fil.c netinet/ip_fil.c
--- netinet.orig/ip_fil.c	Thu Oct 24 18:33:45 2002
+++ netinet/ip_fil.c	Sat Aug 23 10:01:59 2003
@@ -1942,10 +1950,12 @@
 	dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
 	dst6->sin6_family = AF_INET6;
 	dst6->sin6_len = sizeof(struct sockaddr_in6);
-	dst6->sin6_addr = fin->fin_fi.fi_src.in6;
+	dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
 
 	if (fdp != NULL)
 		ifp = fdp->fd_ifp;
+	else
+		ifp = fin->fin_ifp;
 
 	if ((fr != NULL) && (fin->fin_rev != 0)) {
 		if ((ifp != NULL) && (fdp == &fr->fr_tif))
@@ -1957,6 +1967,11 @@
 	if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE)))
 		return -2;
 
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+	/* KAME */
+	if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
+		dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
+#endif
 	rtalloc((struct route *)ro);
 
 	if ((ifp == NULL) && (ro->ro_rt != NULL))
>Release-Note:
>Audit-Trail:
>Unformatted: