summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man9/mbuf.929
-rw-r--r--sys/kern/uipc_mbuf.c48
-rw-r--r--sys/sys/mbuf.h1
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));
OpenPOWER on IntegriCloud