summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_mbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r--sys/kern/uipc_mbuf.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 3dfee69..52b6bb1 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -755,6 +755,73 @@ out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
m->m_pkthdr.len = totlen;
}
+/*
+ * Apply function f to the data in an mbuf chain starting "off" bytes from
+ * the beginning, continuing for "len" bytes.
+ */
+int
+m_apply(struct mbuf *m, int off, int len,
+ int (*f)(void *, caddr_t, unsigned int), void *arg)
+{
+ unsigned int count;
+ int rval;
+
+ KASSERT(off >= 0, ("m_apply, negative off %d", off));
+ KASSERT(len >= 0, ("m_apply, negative len %d", len));
+
+ while (off > 0) {
+ KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain"));
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ while (len > 0) {
+ KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain"));
+ count = min(m->m_len - off, len);
+
+ rval = (*f)(arg, mtod(m, caddr_t) + off, count);
+ if (rval)
+ return (rval);
+
+ len -= count;
+ off = 0;
+ m = m->m_next;
+ }
+
+ return (0);
+}
+
+/*
+ * Return a pointer to mbuf/offset of location in mbuf chain.
+ */
+struct mbuf *
+m_getptr(struct mbuf *m, int loc, int *off)
+{
+
+ while (loc >= 0) {
+ /* Normal end of search */
+ if (m->m_len > loc) {
+ *off = loc;
+ return (m);
+ } else {
+ loc -= m->m_len;
+
+ if (m->m_next == NULL) {
+ if (loc == 0) {
+ /* Point at the end of valid data */
+ *off = m->m_len;
+ return (m);
+ } else
+ return (NULL);
+ } else
+ m = m->m_next;
+ }
+ }
+
+ return (NULL);
+}
+
void
m_print(const struct mbuf *m)
{
OpenPOWER on IntegriCloud