diff options
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 67 |
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) { |