Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/uipc_mbuf.c
Show First 20 Lines • Show All 1,443 Lines • ▼ Show 20 Lines | |||||
* > 0 each fragment will be of the specified length | * > 0 each fragment will be of the specified length | ||||
* -1 each fragment will be the same random value in length | * -1 each fragment will be the same random value in length | ||||
* -2 each fragment's length will be entirely random | * -2 each fragment's length will be entirely random | ||||
* (Random values range from 1 to 256) | * (Random values range from 1 to 256) | ||||
*/ | */ | ||||
struct mbuf * | struct mbuf * | ||||
m_fragment(struct mbuf *m0, int how, int length) | m_fragment(struct mbuf *m0, int how, int length) | ||||
{ | { | ||||
struct mbuf *m_new = NULL, *m_final = NULL; | struct mbuf *m_first, *m_last; | ||||
int progress = 0; | int divisor = 255, progress = 0, fraglen; | ||||
if (!(m0->m_flags & M_PKTHDR)) | if (!(m0->m_flags & M_PKTHDR)) | ||||
return (m0); | return (m0); | ||||
if ((length == 0) || (length < -2)) | if (length == 0 || length < -2) | ||||
return (m0); | return (m0); | ||||
if (length > MCLBYTES) | |||||
length = MCLBYTES; | |||||
if (length < 0 && divisor > MCLBYTES) | |||||
divisor = MCLBYTES; | |||||
if (length == -1) | |||||
length = 1 + (arc4random() % divisor); | |||||
if (length > 0) | |||||
fraglen = length; | |||||
m_fixhdr(m0); /* Needed sanity check */ | m_fixhdr(m0); /* Needed sanity check */ | ||||
m_final = m_getcl(how, MT_DATA, M_PKTHDR); | m_first = m_getcl(how, MT_DATA, M_PKTHDR); | ||||
if (m_first == NULL) | |||||
if (m_final == NULL) | |||||
goto nospace; | goto nospace; | ||||
if (m_dup_pkthdr(m_final, m0, how) == 0) | if (m_dup_pkthdr(m_first, m0, how) == 0) | ||||
goto nospace; | goto nospace; | ||||
m_new = m_final; | m_last = m_first; | ||||
if (length == -1) | |||||
length = 1 + (arc4random() & 255); | |||||
while (progress < m0->m_pkthdr.len) { | while (progress < m0->m_pkthdr.len) { | ||||
int fraglen; | if (length == -2) | ||||
fraglen = 1 + (arc4random() % divisor); | |||||
if (length > 0) | |||||
fraglen = length; | |||||
else | |||||
fraglen = 1 + (arc4random() & 255); | |||||
if (fraglen > m0->m_pkthdr.len - progress) | if (fraglen > m0->m_pkthdr.len - progress) | ||||
fraglen = m0->m_pkthdr.len - progress; | fraglen = m0->m_pkthdr.len - progress; | ||||
if (fraglen > MCLBYTES) | if (progress != 0) { | ||||
fraglen = MCLBYTES; | struct mbuf *m_new = m_getcl(how, MT_DATA, 0); | ||||
if (m_new == NULL) { | |||||
m_new = m_getcl(how, MT_DATA, 0); | |||||
if (m_new == NULL) | if (m_new == NULL) | ||||
goto nospace; | goto nospace; | ||||
m_last->m_next = m_new; | |||||
m_last = m_new; | |||||
} | } | ||||
m_copydata(m0, progress, fraglen, mtod(m_new, caddr_t)); | m_copydata(m0, progress, fraglen, mtod(m_last, caddr_t)); | ||||
progress += fraglen; | progress += fraglen; | ||||
m_new->m_len = fraglen; | m_last->m_len = fraglen; | ||||
if (m_new != m_final) | |||||
m_cat(m_final, m_new); | |||||
m_new = NULL; | |||||
} | } | ||||
m_freem(m0); | m_freem(m0); | ||||
m0 = m_final; | m0 = m_first; | ||||
return (m0); | return (m0); | ||||
nospace: | nospace: | ||||
if (m_final) | if (m_first) | ||||
m_freem(m_final); | m_freem(m_first); | ||||
/* Return the original chain on failure */ | /* Return the original chain on failure */ | ||||
return (m0); | return (m0); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Copy the contents of uio into a properly sized mbuf chain. | * Copy the contents of uio into a properly sized mbuf chain. | ||||
▲ Show 20 Lines • Show All 364 Lines • Show Last 20 Lines |