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>
This commit is contained in:
parent
28788ed563
commit
9967cafc49
@ -1326,7 +1326,7 @@ awi_fix_rxhdr(sc, m0)
|
||||
m_freem(m0);
|
||||
return NULL;
|
||||
}
|
||||
M_COPY_PKTHDR(n, m0);
|
||||
M_MOVE_PKTHDR(n, m0);
|
||||
n->m_len = MHLEN;
|
||||
} else {
|
||||
MGET(n, M_DONTWAIT, MT_DATA);
|
||||
|
@ -323,7 +323,7 @@ awi_wep_encrypt(sc, m0, txflag)
|
||||
n0 = n;
|
||||
if (n == NULL)
|
||||
goto fail;
|
||||
M_COPY_PKTHDR(n, m);
|
||||
M_MOVE_PKTHDR(n, m);
|
||||
len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
|
||||
if (txflag) {
|
||||
n->m_pkthdr.len += len;
|
||||
|
@ -1843,7 +1843,7 @@ STATIC int en_makeexclusive(sc, mm, prev)
|
||||
return(0);
|
||||
}
|
||||
if (m->m_flags & M_PKTHDR)
|
||||
M_COPY_PKTHDR(new, m);
|
||||
M_MOVE_PKTHDR(new, m);
|
||||
MCLGET(new, M_DONTWAIT);
|
||||
if ((new->m_flags & M_EXT) == 0) {
|
||||
m_free(new);
|
||||
|
@ -1668,6 +1668,10 @@ hifn_crypto(
|
||||
if (cmd->src_m->m_flags & M_PKTHDR) {
|
||||
len = MHLEN;
|
||||
MGETHDR(m0, M_DONTWAIT, MT_DATA);
|
||||
if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_DONTWAIT)) {
|
||||
m_free(m0);
|
||||
m0 = NULL;
|
||||
}
|
||||
} else {
|
||||
len = MLEN;
|
||||
MGET(m0, M_DONTWAIT, MT_DATA);
|
||||
@ -1677,9 +1681,6 @@ hifn_crypto(
|
||||
err = dma->cmdu ? ERESTART : ENOMEM;
|
||||
goto err_srcmap;
|
||||
}
|
||||
if (len == MHLEN) {
|
||||
M_COPY_PKTHDR(m0, cmd->src_m);
|
||||
}
|
||||
if (totlen >= MINCLSIZE) {
|
||||
MCLGET(m0, M_DONTWAIT);
|
||||
if ((m0->m_flags & M_EXT) == 0) {
|
||||
|
@ -1269,6 +1269,10 @@ ubsec_process(void *arg, struct cryptop *crp, int hint)
|
||||
if (q->q_src_m->m_flags & M_PKTHDR) {
|
||||
len = MHLEN;
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m && !m_dup_pkthdr(m, q->q_src_m, M_DONTWAIT)) {
|
||||
m_free(m);
|
||||
m = NULL;
|
||||
}
|
||||
} else {
|
||||
len = MLEN;
|
||||
MGET(m, M_DONTWAIT, MT_DATA);
|
||||
@ -1278,8 +1282,6 @@ ubsec_process(void *arg, struct cryptop *crp, int hint)
|
||||
err = sc->sc_nqueue ? ERESTART : ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
if (len == MHLEN)
|
||||
M_COPY_PKTHDR(m, q->q_src_m);
|
||||
if (totlen >= MINCLSIZE) {
|
||||
MCLGET(m, M_DONTWAIT);
|
||||
if ((m->m_flags & M_EXT) == 0) {
|
||||
|
@ -66,30 +66,70 @@ SYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RW,
|
||||
&max_datalen, 0, "");
|
||||
|
||||
/*
|
||||
* Copy mbuf pkthdr from "from" to "to".
|
||||
* "Move" mbuf pkthdr from "from" to "to".
|
||||
* "from" must have M_PKTHDR set, and "to" must be empty.
|
||||
* aux pointer will be moved to "to".
|
||||
*/
|
||||
void
|
||||
m_copy_pkthdr(struct mbuf *to, struct mbuf *from)
|
||||
m_move_pkthdr(struct mbuf *to, struct mbuf *from)
|
||||
{
|
||||
|
||||
#if 0
|
||||
/* see below for why these are not enabled */
|
||||
KASSERT(to->m_flags & M_PKTHDR,
|
||||
("m_copy_pkthdr() called on non-header"));
|
||||
("m_move_pkthdr: called on non-header"));
|
||||
KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags),
|
||||
("m_move_pkthdr: to has tags"));
|
||||
#endif
|
||||
KASSERT((to->m_flags & M_EXT) == 0, ("m_move_pkthdr: to has cluster"));
|
||||
#ifdef MAC
|
||||
if (to->m_flags & M_PKTHDR)
|
||||
mac_destroy_mbuf(to);
|
||||
#endif
|
||||
to->m_data = to->m_pktdat;
|
||||
to->m_flags = from->m_flags & M_COPYFLAGS;
|
||||
to->m_data = to->m_pktdat;
|
||||
to->m_pkthdr = from->m_pkthdr; /* especially tags */
|
||||
#ifdef MAC
|
||||
mac_init_mbuf(to, 1); /* XXXMAC no way to fail */
|
||||
mac_create_mbuf_from_mbuf(from, to);
|
||||
#endif
|
||||
SLIST_INIT(&from->m_pkthdr.tags); /* purge tags from src */
|
||||
from->m_flags &= ~M_PKTHDR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate "from"'s mbuf pkthdr in "to".
|
||||
* "from" must have M_PKTHDR set, and "to" must be empty.
|
||||
* In particular, this does a deep copy of the packet tags.
|
||||
*/
|
||||
int
|
||||
m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
|
||||
{
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* The mbuf allocator only initializes the pkthdr
|
||||
* when the mbuf is allocated with MGETHDR. Many users
|
||||
* (e.g. m_copy*, m_prepend) use MGET and then
|
||||
* smash the pkthdr as needed causing these
|
||||
* assertions to trip. For now just disable them.
|
||||
*/
|
||||
KASSERT(to->m_flags & M_PKTHDR, ("m_dup_pkthdr: called on non-header"));
|
||||
KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags), ("m_dup_pkthdr: to has tags"));
|
||||
#endif
|
||||
KASSERT((to->m_flags & M_EXT) == 0, ("m_dup_pkthdr: to has cluster"));
|
||||
#ifdef MAC
|
||||
if (to->m_flags & M_PKTHDR)
|
||||
mac_destroy_mbuf(to);
|
||||
#endif
|
||||
to->m_flags = from->m_flags & M_COPYFLAGS;
|
||||
to->m_data = to->m_pktdat;
|
||||
to->m_pkthdr = from->m_pkthdr;
|
||||
#ifdef MAC
|
||||
mac_init_mbuf(to, 1); /* XXXMAC no way to fail */
|
||||
mac_create_mbuf_from_mbuf(from, to);
|
||||
#endif
|
||||
SLIST_INIT(&from->m_pkthdr.tags);
|
||||
SLIST_INIT(&to->m_pkthdr.tags);
|
||||
return (m_tag_copy_chain(to, from, how));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,11 +148,10 @@ m_prepend(struct mbuf *m, int len, int how)
|
||||
return (NULL);
|
||||
}
|
||||
if (m->m_flags & M_PKTHDR) {
|
||||
M_COPY_PKTHDR(mn, m);
|
||||
M_MOVE_PKTHDR(mn, m);
|
||||
#ifdef MAC
|
||||
mac_destroy_mbuf(m);
|
||||
#endif
|
||||
m->m_flags &= ~M_PKTHDR;
|
||||
}
|
||||
mn->m_next = m;
|
||||
m = mn;
|
||||
@ -161,7 +200,8 @@ m_copym(struct mbuf *m, int off0, int len, int wait)
|
||||
if (n == NULL)
|
||||
goto nospace;
|
||||
if (copyhdr) {
|
||||
M_COPY_PKTHDR(n, m);
|
||||
if (!m_dup_pkthdr(n, m, wait))
|
||||
goto nospace;
|
||||
if (len == M_COPYALL)
|
||||
n->m_pkthdr.len -= off0;
|
||||
else
|
||||
@ -212,7 +252,8 @@ m_copypacket(struct mbuf *m, int how)
|
||||
if (n == NULL)
|
||||
goto nospace;
|
||||
|
||||
M_COPY_PKTHDR(n, m);
|
||||
if (!m_dup_pkthdr(n, m, how))
|
||||
goto nospace;
|
||||
n->m_len = m->m_len;
|
||||
if (m->m_flags & M_EXT) {
|
||||
n->m_data = m->m_data;
|
||||
@ -309,7 +350,8 @@ m_dup(struct mbuf *m, int how)
|
||||
if (n == NULL)
|
||||
goto nospace;
|
||||
if (top == NULL) { /* first one, must be PKTHDR */
|
||||
M_COPY_PKTHDR(n, m);
|
||||
if (!m_dup_pkthdr(n, m, how))
|
||||
goto nospace;
|
||||
nsize = MHLEN;
|
||||
} else /* not the first one */
|
||||
nsize = MLEN;
|
||||
@ -484,10 +526,8 @@ m_pullup(struct mbuf *n, int len)
|
||||
if (m == NULL)
|
||||
goto bad;
|
||||
m->m_len = 0;
|
||||
if (n->m_flags & M_PKTHDR) {
|
||||
M_COPY_PKTHDR(m, n);
|
||||
n->m_flags &= ~M_PKTHDR;
|
||||
}
|
||||
if (n->m_flags & M_PKTHDR)
|
||||
M_MOVE_PKTHDR(m, n);
|
||||
}
|
||||
space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
|
||||
do {
|
||||
|
@ -298,8 +298,10 @@ m_dup1(struct mbuf *m, int off, int len, int wait)
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
if (copyhdr)
|
||||
M_COPY_PKTHDR(n, m);
|
||||
if (copyhdr && !m_dup_pkthdr(n, m, wait)) {
|
||||
m_free(n);
|
||||
return NULL;
|
||||
}
|
||||
m_copydata(m, off, len, mtod(n, caddr_t));
|
||||
return n;
|
||||
}
|
||||
@ -392,12 +394,12 @@ m_tag_locate(struct mbuf *m, u_int32_t cookie, int type, struct m_tag *t)
|
||||
|
||||
/* Copy a single tag. */
|
||||
struct m_tag *
|
||||
m_tag_copy(struct m_tag *t)
|
||||
m_tag_copy(struct m_tag *t, int how)
|
||||
{
|
||||
struct m_tag *p;
|
||||
|
||||
KASSERT(t, ("m_tag_copy: null tag"));
|
||||
p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, M_NOWAIT);
|
||||
p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how);
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
|
||||
@ -411,7 +413,7 @@ m_tag_copy(struct m_tag *t)
|
||||
* destination mbuf.
|
||||
*/
|
||||
int
|
||||
m_tag_copy_chain(struct mbuf *to, struct mbuf *from)
|
||||
m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how)
|
||||
{
|
||||
struct m_tag *p, *t, *tprev = NULL;
|
||||
|
||||
@ -419,7 +421,7 @@ m_tag_copy_chain(struct mbuf *to, struct mbuf *from)
|
||||
("m_tag_copy_chain: null argument, to %p from %p", to, from));
|
||||
m_tag_delete_chain(to, NULL);
|
||||
SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
|
||||
t = m_tag_copy(p);
|
||||
t = m_tag_copy(p, how);
|
||||
if (t == NULL) {
|
||||
m_tag_delete_chain(to, NULL);
|
||||
return 0;
|
||||
|
@ -214,19 +214,11 @@ looutput(ifp, m, dst, rt)
|
||||
if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
|
||||
struct mbuf *n;
|
||||
|
||||
/* XXX MT_HEADER should be m->m_type */
|
||||
MGETHDR(n, M_DONTWAIT, MT_HEADER);
|
||||
if (!n)
|
||||
goto contiguousfail;
|
||||
MCLGET(n, M_DONTWAIT);
|
||||
if (! (n->m_flags & M_EXT)) {
|
||||
m_freem(n);
|
||||
goto contiguousfail;
|
||||
}
|
||||
|
||||
m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
|
||||
n->m_pkthdr = m->m_pkthdr;
|
||||
n->m_len = m->m_pkthdr.len;
|
||||
SLIST_INIT(&m->m_pkthdr.tags);
|
||||
M_MOVE_PKTHDR(n, m);
|
||||
#ifdef MAC
|
||||
/*
|
||||
* XXXMAC: Once we put labels in tags and proper
|
||||
@ -235,6 +227,14 @@ looutput(ifp, m, dst, rt)
|
||||
*/
|
||||
m->m_pkthdr.label.l_flags &= ~MAC_FLAG_INITIALIZED;
|
||||
#endif
|
||||
MCLGET(n, M_DONTWAIT);
|
||||
if (! (n->m_flags & M_EXT)) {
|
||||
m_freem(n);
|
||||
goto contiguousfail;
|
||||
}
|
||||
|
||||
m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
|
||||
n->m_len = m->m_pkthdr.len;
|
||||
m_freem(m);
|
||||
m = n;
|
||||
}
|
||||
|
@ -178,8 +178,7 @@ typedef struct mbuf KBuffer;
|
||||
}
|
||||
#define KB_LINKHEAD(new, head) { \
|
||||
if ((head) && KB_ISPKT(new) && KB_ISPKT(head)) {\
|
||||
M_COPY_PKTHDR((new), (head)); \
|
||||
(head)->m_flags &= ~M_PKTHDR; \
|
||||
M_MOVE_PKTHDR((new), (head)); \
|
||||
} \
|
||||
(new)->m_next = (head); \
|
||||
}
|
||||
|
@ -1763,8 +1763,17 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
|
||||
* data in a cluster may change before we reach icmp_error().
|
||||
*/
|
||||
MGET(mcopy, M_DONTWAIT, m->m_type);
|
||||
if (mcopy != NULL && !m_dup_pkthdr(mcopy, m, M_DONTWAIT)) {
|
||||
/*
|
||||
* It's probably ok if the pkthdr dup fails (because
|
||||
* the deep copy of the tag chain failed), but for now
|
||||
* be conservative and just discard the copy since
|
||||
* code below may some day want the tags.
|
||||
*/
|
||||
m_free(mcopy);
|
||||
mcopy = NULL;
|
||||
}
|
||||
if (mcopy != NULL) {
|
||||
M_COPY_PKTHDR(mcopy, m);
|
||||
mcopy->m_len = imin((ip->ip_hl << 2) + 8,
|
||||
(int)ip->ip_len);
|
||||
m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
/*
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -101,7 +101,7 @@ m_clone(struct mbuf *m0)
|
||||
m_freem(m0);
|
||||
return (NULL);
|
||||
}
|
||||
M_COPY_PKTHDR(n, m);
|
||||
M_MOVE_PKTHDR(n, m);
|
||||
MCLGET(n, M_DONTWAIT);
|
||||
if ((n->m_flags & M_EXT) == 0) {
|
||||
m_free(n);
|
||||
|
@ -474,7 +474,7 @@ ipsec6_splithdr(struct mbuf *m)
|
||||
m_freem(m);
|
||||
return NULL;
|
||||
}
|
||||
M_COPY_PKTHDR(mh, m);
|
||||
M_MOVE_PKTHDR(mh, m);
|
||||
MH_ALIGN(mh, hlen);
|
||||
m->m_len -= hlen;
|
||||
m->m_data += hlen;
|
||||
|
@ -177,8 +177,9 @@ struct mbuf {
|
||||
/*
|
||||
* Flags copied when copying m_pkthdr.
|
||||
*/
|
||||
#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \
|
||||
M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|M_FRAG|M_RDONLY)
|
||||
#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\
|
||||
M_PROTO3|M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|\
|
||||
M_FRAG|M_FIRSTFRAG|M_LASTFRAG)
|
||||
|
||||
/*
|
||||
* Flags indicating hw checksum support and sw checksum requirements.
|
||||
@ -294,7 +295,8 @@ struct mbstat {
|
||||
* mbuf, cluster, and external object allocation macros
|
||||
* (for compatibility purposes).
|
||||
*/
|
||||
#define M_COPY_PKTHDR(to, from) m_copy_pkthdr((to), (from))
|
||||
/* NB: M_COPY_PKTHDR is deprecated, use M_MOVE_PKTHDR or m_dup_pktdr */
|
||||
#define M_MOVE_PKTHDR(to, from) m_move_pkthdr((to), (from))
|
||||
#define m_getclr(how, type) m_get_clrd((how), (type))
|
||||
#define MGET(m, how, type) ((m) = m_get((how), (type)))
|
||||
#define MGETHDR(m, how, type) ((m) = m_gethdr((how), (type)))
|
||||
@ -428,6 +430,7 @@ void m_copy_pkthdr(struct mbuf *, struct mbuf *);
|
||||
struct mbuf *m_devget(char *, int, int, struct ifnet *,
|
||||
void (*)(char *, caddr_t, u_int));
|
||||
struct mbuf *m_dup(struct mbuf *, int);
|
||||
int m_dup_pkthdr(struct mbuf *, struct mbuf *, int);
|
||||
u_int m_fixhdr(struct mbuf *);
|
||||
struct mbuf *m_free(struct mbuf *);
|
||||
void m_freem(struct mbuf *);
|
||||
@ -438,6 +441,7 @@ struct mbuf *m_gethdr(int, short);
|
||||
struct mbuf *m_gethdr_clrd(int, short);
|
||||
struct mbuf *m_getm(struct mbuf *, int, int, short);
|
||||
u_int m_length(struct mbuf *, struct mbuf **);
|
||||
void m_move_pkthdr(struct mbuf *, struct mbuf *);
|
||||
struct mbuf *m_prepend(struct mbuf *, int, int);
|
||||
void m_print(const struct mbuf *);
|
||||
struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
|
||||
@ -528,8 +532,8 @@ void m_tag_unlink(struct mbuf *, struct m_tag *);
|
||||
void m_tag_delete(struct mbuf *, struct m_tag *);
|
||||
void m_tag_delete_chain(struct mbuf *, struct m_tag *);
|
||||
struct m_tag *m_tag_locate(struct mbuf *, u_int32_t, int, struct m_tag *);
|
||||
struct m_tag *m_tag_copy(struct m_tag *);
|
||||
int m_tag_copy_chain(struct mbuf *, struct mbuf *);
|
||||
struct m_tag *m_tag_copy(struct m_tag *, int);
|
||||
int m_tag_copy_chain(struct mbuf *, struct mbuf *, int);
|
||||
void m_tag_init(struct mbuf *);
|
||||
struct m_tag *m_tag_first(struct mbuf *);
|
||||
struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user