Subject: Re: bridged IPv6 packets rewritten with embedded scope IDs
To: None <tech-net@NetBSD.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-net
Date: 03/23/2006 14:41:30
--9amGYk9869ThD9tj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Mar 22, 2006 at 11:26:37PM -0600, David Young wrote:
> Here is an (untested) patch that may fix the problem.

I think that m_makewritable() should be moved closer to the place where
it will be written. With your patch, the packet may be dropped
immediatly after being made writable.

What about the attached patch (also untested) instead ?
Also note that this may also be a problem with Xen, which may pass
mbufs pointing to read-only mapped areas to the network stacks.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--9amGYk9869ThD9tj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: in6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.h,v
retrieving revision 1.52
diff -u -r1.52 in6.h
--- in6.h	16 Feb 2006 20:17:20 -0000	1.52
+++ in6.h	23 Mar 2006 13:39:22 -0000
@@ -359,6 +359,9 @@
 	((IN6_IS_ADDR_LINKLOCAL(a)) ||	\
 	 (IN6_IS_ADDR_MC_LINKLOCAL(a)))
 
+#define	IN6_IS_SCOPE_EMBEDDABLE(__a)	\
+    (IN6_IS_SCOPE_LINKLOCAL(__a) || IN6_IS_ADDR_MC_INTFACELOCAL(__a))
+
 #define IFA6_IS_DEPRECATED(a) \
 	((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
 	 (u_int32_t)((time.tv_sec - (a)->ia6_updatetime)) > \
Index: ip6_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.83
diff -u -r1.83 ip6_input.c
--- ip6_input.c	5 Mar 2006 23:47:08 -0000	1.83
+++ ip6_input.c	23 Mar 2006 13:39:22 -0000
@@ -399,6 +399,22 @@
 	}
 #endif
 
+        /*
+	 * If we will embed a scope identifier in either the source or
+	 * destination address or both, then make them both writable.
+	 */
+	if (IN6_IS_SCOPE_EMBEDDABLE(&ip6->ip6_src) ||
+	      IN6_IS_SCOPE_EMBEDDABLE(&ip6->ip6_dst)) {
+		if (m_makewritable(&m, offsetof(struct ip6_hdr, ip6_src),
+		    sizeof(struct ip6_hdr) - offsetof(struct ip6_hdr, ip6_src),
+		    M_DONTWAIT) != 0) {
+			struct ifnet *inifp = m->m_pkthdr.rcvif;
+			ip6stat.ip6s_toosmall++;	/* XXXDCY new stat */
+			in6_ifstat_inc(inifp, ifs6_in_hdrerr);	/* XXX DCY new stat */
+			goto bad;
+		} else
+			ip6 = mtod(m, struct ip6_hdr *);
+	}
 	/*
 	 * Disambiguate address scope zones (if there is ambiguity).
 	 * We first make sure that the original source or destination address
Index: scope6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/scope6.c,v
retrieving revision 1.2
diff -u -r1.2 scope6.c
--- scope6.c	5 Mar 2006 01:28:51 -0000	1.2
+++ scope6.c	23 Mar 2006 13:39:22 -0000
@@ -427,7 +427,7 @@
 	if (ret_id != NULL)
 		*ret_id = zoneid;
 
-	if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
+	if (IN6_IS_SCOPE_EMBEDDABLE(in6))
 		in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
 
 	return (0);

--9amGYk9869ThD9tj--