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.c55
1 files changed, 25 insertions, 30 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 4134623..a4d3674 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1078,29 +1078,26 @@ extpacket:
}
/*
* Routine to copy from device local memory into mbufs.
+ * Note that `off' argument is offset into first mbuf of target chain from
+ * which to begin copying the data to.
*/
struct mbuf *
-m_devget(char *buf, int totlen, int off0, struct ifnet *ifp,
+m_devget(char *buf, int totlen, int off, struct ifnet *ifp,
void (*copy)(char *from, caddr_t to, u_int len))
{
struct mbuf *m;
struct mbuf *top = 0, **mp = ⊤
- int off = off0, len;
- char *cp;
- char *epkt;
-
- cp = buf;
- epkt = cp + totlen;
- if (off) {
- cp += off + 2 * sizeof(u_short);
- totlen -= 2 * sizeof(u_short);
- }
+ int len;
+
+ if (off < 0 || off > MHLEN)
+ return (NULL);
+
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL)
return (NULL);
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = totlen;
- m->m_len = MHLEN;
+ len = MHLEN;
while (totlen > 0) {
if (top) {
@@ -1109,37 +1106,35 @@ m_devget(char *buf, int totlen, int off0, struct ifnet *ifp,
m_freem(top);
return (NULL);
}
- m->m_len = MLEN;
+ len = MLEN;
}
- len = min(totlen, epkt - cp);
- if (len >= MINCLSIZE) {
+ if (totlen + off >= MINCLSIZE) {
MCLGET(m, M_DONTWAIT);
if (m->m_flags & M_EXT)
- m->m_len = len = min(len, MCLBYTES);
- else
- len = m->m_len;
+ len = MCLBYTES;
} else {
/*
* Place initial small packet/header at end of mbuf.
*/
- if (len < m->m_len) {
- if (top == NULL && len +
- max_linkhdr <= m->m_len)
- m->m_data += max_linkhdr;
- m->m_len = len;
- } else
- len = m->m_len;
+ if (top == NULL && totlen + off + max_linkhdr <= len) {
+ m->m_data += max_linkhdr;
+ len -= max_linkhdr;
+ }
+ }
+ if (off) {
+ m->m_data += off;
+ len -= off;
+ off = 0;
}
+ m->m_len = len = min(totlen, len);
if (copy)
- copy(cp, mtod(m, caddr_t), (unsigned)len);
+ copy(buf, mtod(m, caddr_t), (unsigned)len);
else
- bcopy(cp, mtod(m, caddr_t), (unsigned)len);
- cp += len;
+ bcopy(buf, mtod(m, caddr_t), (unsigned)len);
+ buf += len;
*mp = m;
mp = &m->m_next;
totlen -= len;
- if (cp == epkt)
- cp = buf;
}
return (top);
}
OpenPOWER on IntegriCloud