Subject: Re: fxp0: can't handle af118
To: Christos Zoulas <christos@zoulas.com>
From: Andreas Wrede <andreas@planix.com>
List: current-users
Date: 05/18/2004 17:27:15
This is a multi-part message in MIME format.
--------------080405070607010801040206
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Christos Zoulas wrote:

> On May 18, 11:51am, erplefoo@gmail.com (Sean Davis) wrote:
> -- Subject: Re: fxp0: can't handle af118
> 
> | I'm seeing the same thing with tl(4):
> | May 18 11:45:31 eros /netbsd: tl1: can't handle af8
> | 
> | I am also using a catch-all return-rst rule...
> | 
> | It appears to stem from sys/net/if_ethersubr.c (revision 1.114) line 462-465:
> |   462    default:
> |   463       printf("%s: can't handle af%d\n", ifp->if_xname,
> |   464          dst->sa_family);
> |   465       senderr(EAFNOSUPPORT);
> | 
> | if the address family is broken, but different, for fxp, it sounds
> | like it's not getting set somewhere and a value from elsewhere is
> | leaking in, or something similar. I'll see if I can figure out what,
> | but it's been ages since I've looked through the ethernet code.
> | 
> | -Sean
> 
> 
> I think the code that is broken is the code that prepares the dst packet
> somewhere in ip_nat or ip_fil.

The problem appears to have been introduced with the commit of rev 1.6 
of src/sys/netinet/ip_fil_netbsd.c. I am running with the changes from 
1.5, 1.7 and 1.8. The diff against the current head of p_fil_netbsd.c is 
attached, it should be largely identical to changes from rev 1.6.

-- 
     - aew

--------------080405070607010801040206
Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0";
 name="ipnat.diff1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ipnat.diff1"

Index: ip_fil_netbsd.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_fil_netbsd.c,v
retrieving revision 1.8
diff -u -r1.8 ip_fil_netbsd.c
--- ip_fil_netbsd.c	9 May 2004 08:29:30 -0000	1.8
+++ ip_fil_netbsd.c	18 May 2004 21:18:35 -0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_fil_netbsd.c,v 1.8 2004/05/09 08:29:30 taca Exp $	*/
+/*	$NetBSD: ip_fil_netbsd.c,v 1.5 2004/04/22 01:01:41 matt Exp $	*/
 
 /*
  * Copyright (C) 1993-2003 by Darren Reed.
@@ -1001,10 +1001,6 @@
 		}
 	}
 #endif
-#ifdef USE_INET6
-	if (fin->fin_v == 6)
-		return ipfr_fastroute6(m0, mpp, fin, fdp);
-#endif
 
 	hlen = fin->fin_hlen;
 	ip = mtod(m0, struct ip *);
@@ -1016,6 +1012,10 @@
 	m0->m_pkthdr.csuminfo = 0;
 #endif /* __NetBSD__ && M_CSUM_IPv4 */
 
+#ifdef USE_INET6
+	if (fin->fin_v == 6)
+		return ipfr_fastroute6(m0, mpp, fin, fdp);
+#endif
 	/*
 	 * Route packet.
 	 */
@@ -1023,13 +1023,14 @@
 	bzero((caddr_t)ro, sizeof (*ro));
 	dst = (struct sockaddr_in *)&ro->ro_dst;
 	dst->sin_family = AF_INET;
-	dst->sin_addr = ip->ip_dst;
 
 	fr = fin->fin_fr;
 	if (fdp)
 		ifp = fdp->fd_ifp;
-	else
+	else {
 		ifp = fin->fin_ifp;
+		dst->sin_addr = ip->ip_dst;
+	}
 
 	if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) {
 		error = -2;
@@ -1044,26 +1045,27 @@
 		if ((ifp != NULL) && (fdp == &fr->fr_tif))
 			return -1;
 		dst->sin_addr = ip->ip_dst;
-	} else if (fdp != NULL) {
-		if (fdp->fd_ip.s_addr != 0)
+	} else if (fdp) {
+		if (fdp->fd_ip.s_addr) {
 			dst->sin_addr = fdp->fd_ip;
+			ip->ip_dst = fdp->fd_ip;
+		} else
+			dst->sin_addr = ip->ip_dst;
 	}
 
 	dst->sin_len = sizeof(*dst);
 	rtalloc(ro);
-
-	if ((ifp == NULL) && (ro->ro_rt != NULL))
-		ifp = ro->ro_rt->rt_ifp;
-
-	if ((ro->ro_rt == NULL) || (ifp == NULL)) {
-		if (in_localaddr(ip->ip_dst))
-			error = EHOSTUNREACH;
-		else
-			error = ENETUNREACH;
-		goto bad;
+	if (!ifp) {
+		if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
+			if (in_localaddr(ip->ip_dst))
+				error = EHOSTUNREACH;
+			else
+				error = ENETUNREACH;
+			goto bad;
+		}
+		if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+			dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
 	}
-	if (ro->ro_rt->rt_flags & RTF_GATEWAY)
-		dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
 	if (ro->ro_rt)
 		ro->ro_rt->rt_use++;
 
@@ -1072,9 +1074,8 @@
 	 * go back through output filtering and miss their chance to get
 	 * NAT'd and counted.
 	 */
+	fin->fin_ifp = ifp;
 	if (fin->fin_out == 0) {
-		sifp = fin->fin_ifp;
-		fin->fin_ifp = ifp;
 		fin->fin_out = 1;
 		(void) fr_acctpkt(fin, NULL);
 		fin->fin_fr = NULL;
@@ -1084,7 +1085,6 @@
 			(void) fr_checkstate(fin, &pass);
 		}
 		(void) fr_checknatout(fin, NULL);
-		fin->fin_ifp = sifp;
 	} else
 		ip->ip_sum = 0;
 	/*

--------------080405070607010801040206--