summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-06-03 13:43:46 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-06-03 13:43:46 +0000
commit1309103a5af60e521eff3468a62c7335d5ebb679 (patch)
treef8acb14d2de0ac46e5ce7d42e90ef3814231d8bf /sys
parent41139e24cad367ca2f7140351bb0e3808d3831d6 (diff)
deep-copy ip6 header on ip6_mloopback, to avoid overwriting cluster mbuf.
correct frag header append operation. some cosmetic (like do {} while (0) to multiline macro) (sync with kame)
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/ip6_output.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index a0f15b59b8a..84525bf53e3 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ip6_output.c,v 1.7 2000/05/19 20:12:10 itojun Exp $ */
-/* $KAME: ip6_output.c,v 1.104 2000/05/19 19:10:07 itojun Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.8 2000/06/03 13:43:45 itojun Exp $ */
+/* $KAME: ip6_output.c,v 1.110 2000/06/03 12:43:49 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -162,8 +162,8 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp)
ip6 = mtod(m, struct ip6_hdr *);
#endif /* IPSEC */
-#define MAKE_EXTHDR(hp,mp) \
- { \
+#define MAKE_EXTHDR(hp, mp) \
+ do { \
if (hp) { \
struct ip6_ext *eh = (struct ip6_ext *)(hp); \
error = ip6_copyexthdr((mp), (caddr_t)(hp), \
@@ -171,7 +171,7 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp)
if (error) \
goto freehdrs; \
} \
- }
+ } while (0)
bzero(&exthdrs, sizeof(exthdrs));
if (opt) {
@@ -310,8 +310,8 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp)
ip6->ip6_nxt = IPPROTO_DSTOPTS;
}
-#define MAKE_CHAIN(m,mp,p,i)\
- {\
+#define MAKE_CHAIN(m, mp, p, i)\
+ do {\
if (m) {\
if (!hdrsplit) \
panic("assumption failed: hdr not split"); \
@@ -322,7 +322,7 @@ ip6_output(m0, opt, ro, flags, im6o, ifpp)
(mp)->m_next = (m);\
(mp) = (m);\
}\
- }
+ } while (0)
/*
* result: IPv6 hbh dest1 rthdr dest2 payload
* m will point to IPv6 header. mprev will point to the
@@ -1137,7 +1137,7 @@ ip6_insertfraghdr(m0, m, hlen, frghdrp)
;
if ((mlast->m_flags & M_EXT) == 0 &&
- M_TRAILINGSPACE(mlast) < sizeof(struct ip6_frag)) {
+ M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
/* use the trailing space of the last mbuf for the fragment hdr */
*frghdrp =
(struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
@@ -1184,6 +1184,7 @@ ip6_ctloutput(op, so, level, optname, mp)
case PRCO_SETOPT:
switch (optname) {
case IPV6_PKTOPTIONS:
+ /* m is freed in ip6_pcbopts */
return(ip6_pcbopts(&inp->inp_outputopts6,
m, so));
case IPV6_HOPOPTS:
@@ -2079,12 +2080,46 @@ ip6_mloopback(ifp, m, dst)
register struct mbuf *m;
register struct sockaddr_in6 *dst;
{
- struct mbuf *copym;
+ struct mbuf *copym;
+ struct ip6_hdr *ip6;
copym = m_copy(m, 0, M_COPYALL);
- if (copym != NULL) {
- (void)looutput(ifp, copym, (struct sockaddr *)dst, NULL);
+ if (copym == NULL)
+ return;
+
+ /*
+ * Make sure to deep-copy IPv6 header portion in case the data
+ * is in an mbuf cluster, so that we can safely override the IPv6
+ * header portion later.
+ */
+ if ((copym->m_flags & M_EXT) != 0 ||
+ copym->m_len < sizeof(struct ip6_hdr)) {
+ copym = m_pullup(copym, sizeof(struct ip6_hdr));
+ if (copym == NULL)
+ return;
+ }
+
+#ifdef DIAGNOSTIC
+ if (copym->m_len < sizeof(*ip6)) {
+ m_freem(copym);
+ return;
+ }
+#endif
+
+#ifndef FAKE_LOOPBACK_IF
+ if ((ifp->if_flags & IFF_LOOPBACK) == 0)
+#else
+ if (1)
+#endif
+ {
+ ip6 = mtod(copym, struct ip6_hdr *);
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
+ ip6->ip6_src.s6_addr16[1] = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
+ ip6->ip6_dst.s6_addr16[1] = 0;
}
+
+ (void)looutput(ifp, copym, (struct sockaddr *)dst, NULL);
}
/*