summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-12-30 20:22:40 +0000
committersam <sam@FreeBSD.org>2002-12-30 20:22:40 +0000
commitb16cb0a948acd6a3b5f47aa494607a001944c194 (patch)
tree984c2041a8941be016b4cab972816b51adcc818d /sys/netinet6
parent83fcaa45a1be401bd2ecafa45dbfb492a71532b7 (diff)
downloadFreeBSD-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.c3
-rw-r--r--sys/netinet6/icmp6.c17
-rw-r--r--sys/netinet6/ip6_input.c2
-rw-r--r--sys/netinet6/ip6_output.c2
-rw-r--r--sys/netinet6/ipsec.c16
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);
OpenPOWER on IntegriCloud