diff options
author | sam <sam@FreeBSD.org> | 2002-12-30 20:22:40 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2002-12-30 20:22:40 +0000 |
commit | b16cb0a948acd6a3b5f47aa494607a001944c194 (patch) | |
tree | 984c2041a8941be016b4cab972816b51adcc818d /sys/netinet6 | |
parent | 83fcaa45a1be401bd2ecafa45dbfb492a71532b7 (diff) | |
download | FreeBSD-src-b16cb0a948acd6a3b5f47aa494607a001944c194.zip FreeBSD-src-b16cb0a948acd6a3b5f47aa494607a001944c194.tar.gz |
Correct mbuf packet header propagation. Previously, packet headers
were sometimes propagated using M_COPY_PKTHDR which actually did
something between a "move" and a "copy" operation. This is replaced
by M_MOVE_PKTHDR (which copies the pkthdr contents and "removes" it
from the source mbuf) and m_dup_pkthdr which copies the packet
header contents including any m_tag chain. This corrects numerous
problems whereby mbuf tags could be lost during packet manipulations.
These changes also introduce arguments to m_tag_copy and m_tag_copy_chain
to specify if the tag copy work should potentially block. This
introduces an incompatibility with openbsd which we may want to revisit.
Note that move/dup of packet headers does not handle target mbufs
that have a cluster bound to them. We may want to support this;
for now we watch for it with an assert.
Finally, M_COPYFLAGS was updated to include M_FIRSTFRAG|M_LASTFRAG.
Supported by: Vernier Networks
Reviewed by: Robert Watson <rwatson@FreeBSD.org>
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/esp_input.c | 3 | ||||
-rw-r--r-- | sys/netinet6/icmp6.c | 17 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 2 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 2 | ||||
-rw-r--r-- | sys/netinet6/ipsec.c | 16 |
5 files changed, 21 insertions, 19 deletions
diff --git a/sys/netinet6/esp_input.c b/sys/netinet6/esp_input.c index b038f6c..ad40e64 100644 --- a/sys/netinet6/esp_input.c +++ b/sys/netinet6/esp_input.c @@ -813,7 +813,7 @@ noreplaycheck: MGETHDR(n, M_DONTWAIT, MT_HEADER); maxlen = MHLEN; if (n) - M_COPY_PKTHDR(n, m); + M_MOVE_PKTHDR(n, m); if (n && m->m_pkthdr.len > maxlen) { MCLGET(n, M_DONTWAIT); maxlen = MCLBYTES; @@ -839,7 +839,6 @@ noreplaycheck: n->m_pkthdr.len = m->m_pkthdr.len; n->m_next = m; m_adj(m, maxlen); - m->m_flags &= ~M_PKTHDR; } m = n; } diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 9e3015d..a0bc165 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -574,7 +574,7 @@ icmp6_input(mp, offp, proto) m_freem(n0); break; } - M_COPY_PKTHDR(n, n0); + M_MOVE_PKTHDR(n, n0); /* * Copy IPv6 and ICMPv6 only. */ @@ -592,7 +592,6 @@ icmp6_input(mp, offp, proto) m_adj(n0, off + sizeof(struct icmp6_hdr)); n->m_pkthdr.len += n0->m_pkthdr.len; n->m_next = n0; - n0->m_flags &= ~M_PKTHDR; } else { nip6 = mtod(n, struct ip6_hdr *); nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off); @@ -690,6 +689,17 @@ icmp6_input(mp, offp, proto) n = NULL; } } + if (!m_dup_pkthdr(n, m, M_DONTWAIT)) { + /* + * Previous code did a blind M_COPY_PKTHDR + * and said "just for rcvif". If true, then + * we could tolerate the dup failing (due to + * the deep copy of the tag chain). For now + * be conservative and just fail. + */ + m_free(n); + n = NULL; + } if (n == NULL) { /* Give up remote */ break; @@ -710,7 +720,6 @@ icmp6_input(mp, offp, proto) bzero(p, 4); bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */ noff = sizeof(struct ip6_hdr); - M_COPY_PKTHDR(n, m); /* just for rcvif */ n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4 + maxhlen; nicmp6->icmp6_type = ICMP6_WRUREPLY; @@ -1387,7 +1396,7 @@ ni6_input(m, off) m_freem(m); return(NULL); } - M_COPY_PKTHDR(n, m); /* just for recvif */ + M_MOVE_PKTHDR(n, m); /* just for recvif */ if (replylen > MHLEN) { if (replylen > MCLBYTES) { /* diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index e76727f..15a44bb 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -319,7 +319,7 @@ ip6_input(m) MGETHDR(n, M_DONTWAIT, MT_HEADER); if (n) - M_COPY_PKTHDR(n, m); + M_MOVE_PKTHDR(n, m); if (n && m->m_pkthdr.len > MHLEN) { MCLGET(n, M_DONTWAIT); if ((n->m_flags & M_EXT) == 0) { diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 94be84a..75ed4dc 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -2575,7 +2575,7 @@ ip6_splithdr(m, exthdrs) m_freem(m); return ENOBUFS; } - M_COPY_PKTHDR(mh, m); + M_MOVE_PKTHDR(mh, m); MH_ALIGN(mh, sizeof(*ip6)); m->m_flags &= ~M_PKTHDR; m->m_len -= sizeof(*ip6); diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c index b91470e..c25b1bf 100644 --- a/sys/netinet6/ipsec.c +++ b/sys/netinet6/ipsec.c @@ -3124,7 +3124,7 @@ ipsec4_splithdr(m) m_freem(m); return NULL; } - M_COPY_PKTHDR(mh, m); + M_MOVE_PKTHDR(mh, m); MH_ALIGN(mh, hlen); m->m_flags &= ~M_PKTHDR; m->m_len -= hlen; @@ -3161,7 +3161,7 @@ ipsec6_splithdr(m) m_freem(m); return NULL; } - M_COPY_PKTHDR(mh, m); + M_MOVE_PKTHDR(mh, m); MH_ALIGN(mh, hlen); m->m_flags &= ~M_PKTHDR; m->m_len -= hlen; @@ -3371,16 +3371,10 @@ ipsec_copypkt(m) MGETHDR(mnew, M_DONTWAIT, MT_HEADER); if (mnew == NULL) goto fail; - mnew->m_pkthdr = n->m_pkthdr; -#if 0 - if (n->m_pkthdr.aux) { - mnew->m_pkthdr.aux = - m_copym(n->m_pkthdr.aux, - 0, M_COPYALL, M_DONTWAIT); + if (!m_dup_pkthdr(mnew, n, M_DONTWAIT)) { + m_free(mnew); + goto fail; } -#endif - M_COPY_PKTHDR(mnew, n); - mnew->m_flags = n->m_flags & M_COPYFLAGS; } else { MGET(mnew, M_DONTWAIT, MT_DATA); |