diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-06-03 13:43:46 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-06-03 13:43:46 +0000 |
commit | 1309103a5af60e521eff3468a62c7335d5ebb679 (patch) | |
tree | f8acb14d2de0ac46e5ce7d42e90ef3814231d8bf /sys | |
parent | 41139e24cad367ca2f7140351bb0e3808d3831d6 (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.c | 59 |
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); } /* |