diff options
-rw-r--r-- | share/man/man9/mbuf.9 | 29 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf.c | 48 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 1 |
3 files changed, 78 insertions, 0 deletions
diff --git a/share/man/man9/mbuf.9 b/share/man/man9/mbuf.9 index 0a7e580..e606232 100644 --- a/share/man/man9/mbuf.9 +++ b/share/man/man9/mbuf.9 @@ -95,6 +95,8 @@ .Ft struct mbuf * .Fn m_prepend "struct mbuf *mbuf" "int len" "int how" .Ft struct mbuf * +.Fn m_copyup "struct mbuf *mbuf" "int len" "int dstoff" +.Ft struct mbuf * .Fn m_pullup "struct mbuf *mbuf" "int len" .Ft struct mbuf * .Fn m_copym "struct mbuf *mbuf" "int offset" "int len" "int how" @@ -614,6 +616,33 @@ depending on the .Dv M_PKTHDR flag setting. .\" +.It Fn m_copyup mbuf len dstoff +Similar to +.Fn m_pullup +but copies +.Fa len +bytes of data into a new mbuf at +.Fa dstoff +bytes into the mbuf. +The +.Fa dstoff +argument aligns the data and leaves room for a link layer header. +Return the new +.Vt mbuf chain +on success, +and frees the +.Vt mbuf chain +and returns +.Dv NULL +on failure. +.Sy Note : +The function does not allocate +.Vt mbuf clusters , +so +.Fa len + dstoff +must be less than +.Dv MHLEN . +.\" .It Fn m_pullup mbuf len Arrange that the first .Fa len diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 8a236a6..f5ba9ab 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -767,6 +767,54 @@ bad: } /* + * Like m_pullup(), except a new mbuf is always allocated, and we allow + * the amount of empty space before the data in the new mbuf to be specified + * (in the event that the caller expects to prepend later). + */ +int MSFail; + +struct mbuf * +m_copyup(struct mbuf *n, int len, int dstoff) +{ + struct mbuf *m; + int count, space; + + if (len > (MHLEN - dstoff)) + goto bad; + MGET(m, M_DONTWAIT, n->m_type); + if (m == NULL) + goto bad; + m->m_len = 0; + if (n->m_flags & M_PKTHDR) + M_MOVE_PKTHDR(m, n); + m->m_data += dstoff; + space = &m->m_dat[MLEN] - (m->m_data + m->m_len); + do { + count = min(min(max(len, max_protohdr), space), n->m_len); + memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), + (unsigned)count); + len -= count; + m->m_len += count; + n->m_len -= count; + space -= count; + if (n->m_len) + n->m_data += count; + else + n = m_free(n); + } while (len > 0 && n); + if (len > 0) { + (void) m_free(m); + goto bad; + } + m->m_next = n; + return (m); + bad: + m_freem(n); + MSFail++; + return (NULL); +} + +/* * Partition an mbuf chain in two pieces, returning the tail -- * all but the first len0 bytes. In case of failure, it returns NULL and * attempts to restore the chain to its original state. diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 0703916..a3d2a61 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -564,6 +564,7 @@ void m_copydata(const struct mbuf *, int, int, caddr_t); struct mbuf *m_copym(struct mbuf *, int, int, int); struct mbuf *m_copypacket(struct mbuf *, int); void m_copy_pkthdr(struct mbuf *, struct mbuf *); +struct mbuf *m_copyup(struct mbuf *n, int len, int dstoff); struct mbuf *m_defrag(struct mbuf *, int); struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)(char *, caddr_t, u_int)); |