16007Sthurlow /*
26007Sthurlow * Copyright (c) 2000, 2001 Boris Popov
36007Sthurlow * All rights reserved.
46007Sthurlow *
56007Sthurlow * Redistribution and use in source and binary forms, with or without
66007Sthurlow * modification, are permitted provided that the following conditions
76007Sthurlow * are met:
86007Sthurlow * 1. Redistributions of source code must retain the above copyright
96007Sthurlow * notice, this list of conditions and the following disclaimer.
106007Sthurlow * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow * notice, this list of conditions and the following disclaimer in the
126007Sthurlow * documentation and/or other materials provided with the distribution.
136007Sthurlow * 3. All advertising materials mentioning features or use of this software
146007Sthurlow * must display the following acknowledgement:
156007Sthurlow * This product includes software developed by Boris Popov.
166007Sthurlow * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow * may be used to endorse or promote products derived from this software
186007Sthurlow * without specific prior written permission.
196007Sthurlow *
206007Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow * SUCH DAMAGE.
316007Sthurlow *
326007Sthurlow * $FreeBSD: src/sys/kern/subr_mchain.c,v 1.1 2001/02/24 15:44:29 bp Exp $
336007Sthurlow */
3410023SGordon.Ross@Sun.COM
356007Sthurlow /*
3610023SGordon.Ross@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
376007Sthurlow * Use is subject to license terms.
386007Sthurlow */
396007Sthurlow
406007Sthurlow #include <sys/param.h>
416007Sthurlow #include <sys/systm.h>
426007Sthurlow #include <sys/errno.h>
436007Sthurlow #include <sys/uio.h>
446007Sthurlow #include <sys/types.h>
456007Sthurlow #include <sys/stream.h>
466007Sthurlow #include <sys/strsun.h>
476007Sthurlow #include <sys/strsubr.h>
4810023SGordon.Ross@Sun.COM #include <sys/sunddi.h>
496007Sthurlow #include <sys/cmn_err.h>
506007Sthurlow
516007Sthurlow #include <netsmb/smb_osdep.h>
526007Sthurlow #include <netsmb/mchain.h>
536007Sthurlow
546007Sthurlow #include <netsmb/smb.h>
556007Sthurlow #include <netsmb/smb_conn.h>
566007Sthurlow #include <netsmb/smb_subr.h>
576007Sthurlow
586007Sthurlow /* BEGIN CSTYLED */
596007Sthurlow /*
606007Sthurlow * BSD-style mbufs, vs SysV-style mblks:
616007Sthurlow * One big difference: the mbuf payload is:
626007Sthurlow * m_data ... (m_data + m_len)
636007Sthurlow * In Unix STREAMS, the mblk payload is:
646007Sthurlow * b_rptr ... b_wptr
656007Sthurlow *
666007Sthurlow * Here are some handy conversion notes:
676007Sthurlow *
686007Sthurlow * struct mbuf struct mblk
696007Sthurlow * m->m_next m->b_cont
706007Sthurlow * m->m_nextpkt m->b_next
716007Sthurlow * m->m_data m->b_rptr
726007Sthurlow * m->m_len MBLKL(m)
736007Sthurlow * m->m_dat[] m->b_datap->db_base
746007Sthurlow * &m->m_dat[MLEN] m->b_datap->db_lim
756007Sthurlow * M_TRAILINGSPACE(m) MBLKTAIL(m)
766007Sthurlow * m_freem(m) freemsg(m)
776007Sthurlow *
786007Sthurlow * Note that mbufs chains also have a special "packet" header,
796007Sthurlow * which has the length of the whole message. In STREAMS one
806007Sthurlow * typically just calls msgdsize(m) to get that.
816007Sthurlow */
826007Sthurlow /* END CSTYLED */
836007Sthurlow
846007Sthurlow
856007Sthurlow /*
866007Sthurlow *
876007Sthurlow * MODULE_VERSION(libmchain, 1);
886007Sthurlow */
896007Sthurlow
906007Sthurlow #ifdef __GNUC__
916007Sthurlow #define MBERROR(format, args...) printf("%s(%d): "format, \
926007Sthurlow __FUNCTION__, __LINE__, ## args)
936007Sthurlow #define MBPANIC(format, args...) printf("%s(%d): "format, \
946007Sthurlow __FUNCTION__, __LINE__, ## args)
956007Sthurlow #else
966007Sthurlow #define MBERROR(...) \
976007Sthurlow smb_errmsg(CE_NOTE, __func__, __VA_ARGS__)
986007Sthurlow #define MBPANIC(...) \
996007Sthurlow smb_errmsg(CE_PANIC, __func__, __VA_ARGS__)
1006007Sthurlow #endif
1016007Sthurlow
1026007Sthurlow /*
1036007Sthurlow * MLEN: The smallest mblk we'll allocate.
1046007Sthurlow *
1056007Sthurlow * There's more to MLEN than you might think.
1066007Sthurlow * Some ethernet drivers may send each mblk as a
1076007Sthurlow * separate frame, so we want MLEN at least 1K.
1086007Sthurlow * We could have used 1K here, but that might
1096007Sthurlow * hurt transports that support larger frames.
1106007Sthurlow * 4K fits nicely in 3 Ethernet frames (3 * 1500)
1116007Sthurlow * leaving about 500 bytes for protocol headers.
1126007Sthurlow *
1136007Sthurlow * XXX: Would Ethernet drivers be happier
1146007Sthurlow * (more efficient) if we used 1K here?
1156007Sthurlow */
1166007Sthurlow #define MLEN 4096
1176007Sthurlow
1186007Sthurlow
1196007Sthurlow /*
1206007Sthurlow * Some UIO routines.
1216007Sthurlow * Taken from Darwin Sourcecs.
1226007Sthurlow */
1236007Sthurlow
1246007Sthurlow /*
12510023SGordon.Ross@Sun.COM * uio_isuserspace - non zero value if the address space
1266007Sthurlow * flag is for a user address space (could be 32 or 64 bit).
1276007Sthurlow */
12810023SGordon.Ross@Sun.COM #define uio_isuserspace(uio) (uio->uio_segflg == UIO_USERSPACE)
1296007Sthurlow
1306007Sthurlow /*
1316007Sthurlow * uio_curriovbase - return the base address of the current iovec associated
1326007Sthurlow * with the given uio_t. May return 0.
1336007Sthurlow */
1346007Sthurlow caddr_t
uio_curriovbase(uio_t * a_uio)1356007Sthurlow uio_curriovbase(uio_t *a_uio)
1366007Sthurlow {
1376007Sthurlow if (a_uio->uio_iovcnt < 1) {
1386007Sthurlow return (0);
1396007Sthurlow }
1406007Sthurlow return ((caddr_t)((uintptr_t)a_uio->uio_iov->iov_base));
1416007Sthurlow }
1426007Sthurlow
1436007Sthurlow /*
1446007Sthurlow * uio_curriovlen - return the length value of the current iovec associated
1456007Sthurlow * with the given uio_t.
1466007Sthurlow */
1476007Sthurlow size_t
uio_curriovlen(uio_t * a_uio)1486007Sthurlow uio_curriovlen(uio_t *a_uio)
1496007Sthurlow {
1506007Sthurlow if (a_uio->uio_iovcnt < 1) {
1516007Sthurlow return (0);
1526007Sthurlow }
1536007Sthurlow return ((size_t)a_uio->uio_iov->iov_len);
1546007Sthurlow }
1556007Sthurlow
1566007Sthurlow
1576007Sthurlow /*
1586007Sthurlow * uio_update - update the given uio_t for a_count of completed IO.
1596007Sthurlow * This call decrements the current iovec length and residual IO value
1606007Sthurlow * and increments the current iovec base address and offset value.
1616007Sthurlow * If the current iovec length is 0 then advance to the next
1626007Sthurlow * iovec (if any).
1636007Sthurlow * If the a_count passed in is 0, than only do the advancement
1646007Sthurlow * over any 0 length iovec's.
1656007Sthurlow */
1666007Sthurlow void
uio_update(uio_t * a_uio,size_t a_count)1676007Sthurlow uio_update(uio_t *a_uio, size_t a_count)
1686007Sthurlow {
1696007Sthurlow if (a_uio->uio_iovcnt < 1) {
1706007Sthurlow return;
1716007Sthurlow }
1726007Sthurlow
1736007Sthurlow /*
1746007Sthurlow * if a_count == 0, then we are asking to skip over
1756007Sthurlow * any empty iovs
1766007Sthurlow */
1776007Sthurlow if (a_count) {
1786007Sthurlow if (a_count > a_uio->uio_iov->iov_len) {
1796007Sthurlow a_uio->uio_iov->iov_base += a_uio->uio_iov->iov_len;
1806007Sthurlow a_uio->uio_iov->iov_len = 0;
1816007Sthurlow } else {
1826007Sthurlow a_uio->uio_iov->iov_base += a_count;
1836007Sthurlow a_uio->uio_iov->iov_len -= a_count;
1846007Sthurlow }
1856007Sthurlow if (a_uio->uio_resid < 0) {
1866007Sthurlow a_uio->uio_resid = 0;
1876007Sthurlow }
1886007Sthurlow if (a_count > (size_t)a_uio->uio_resid) {
18910023SGordon.Ross@Sun.COM a_uio->uio_loffset += a_uio->uio_resid;
1906007Sthurlow a_uio->uio_resid = 0;
1916007Sthurlow } else {
19210023SGordon.Ross@Sun.COM a_uio->uio_loffset += a_count;
1936007Sthurlow a_uio->uio_resid -= a_count;
1946007Sthurlow }
1956007Sthurlow }
1966007Sthurlow /*
1976007Sthurlow * advance to next iovec if current one is totally consumed
1986007Sthurlow */
1996007Sthurlow while (a_uio->uio_iovcnt > 0 && a_uio->uio_iov->iov_len == 0) {
2006007Sthurlow a_uio->uio_iovcnt--;
2016007Sthurlow if (a_uio->uio_iovcnt > 0) {
2026007Sthurlow a_uio->uio_iov++;
2036007Sthurlow }
2046007Sthurlow }
2056007Sthurlow }
2066007Sthurlow
20710023SGordon.Ross@Sun.COM /*
20810023SGordon.Ross@Sun.COM * This is now used only to extend an existing mblk chain,
20910023SGordon.Ross@Sun.COM * so don't need to use allocb_cred_wait here.
21010023SGordon.Ross@Sun.COM */
2116007Sthurlow /*ARGSUSED*/
2126007Sthurlow mblk_t *
m_getblk(int size,int type)2136007Sthurlow m_getblk(int size, int type)
2146007Sthurlow {
2156007Sthurlow mblk_t *mblk;
2166007Sthurlow int error;
2176007Sthurlow
2186007Sthurlow /* Make size at least MLEN. */
2196007Sthurlow if (size < MLEN)
2206007Sthurlow size = MLEN;
2216007Sthurlow mblk = allocb_wait(size, BPRI_LO, STR_NOSIG, &error);
2226007Sthurlow ASSERT(mblk);
2236007Sthurlow return (mblk);
2246007Sthurlow }
2256007Sthurlow
2266007Sthurlow void
mb_done(struct mbchain * mbp)2276007Sthurlow mb_done(struct mbchain *mbp)
2286007Sthurlow {
2296007Sthurlow if (mbp->mb_top) {
2306007Sthurlow freemsg(mbp->mb_top);
2316007Sthurlow mbp->mb_top = NULL;
2326007Sthurlow }
2336007Sthurlow /* Avoid dangling references */
2346007Sthurlow mbp->mb_cur = NULL;
2356007Sthurlow }
2366007Sthurlow
2376007Sthurlow unsigned int
m_length(mblk_t * mblk)2386007Sthurlow m_length(mblk_t *mblk)
2396007Sthurlow {
2406007Sthurlow uint64_t diff;
2416007Sthurlow
2426007Sthurlow diff = (uintptr_t)mblk->b_datap->db_lim -
2436007Sthurlow (uintptr_t)mblk->b_datap->db_base;
2446007Sthurlow ASSERT(diff == (uint64_t)((unsigned int)diff));
2456007Sthurlow return ((unsigned int)diff);
2466007Sthurlow }
2476007Sthurlow
2486007Sthurlow void
mb_initm(struct mbchain * mbp,mblk_t * m)2496007Sthurlow mb_initm(struct mbchain *mbp, mblk_t *m)
2506007Sthurlow {
2516007Sthurlow bzero(mbp, sizeof (*mbp));
2526007Sthurlow mbp->mb_top = mbp->mb_cur = m;
2536007Sthurlow }
2546007Sthurlow
2556007Sthurlow
2566007Sthurlow int
mb_init(struct mbchain * mbp)2576007Sthurlow mb_init(struct mbchain *mbp)
2586007Sthurlow {
25910023SGordon.Ross@Sun.COM cred_t *cr;
2606007Sthurlow mblk_t *mblk;
26110023SGordon.Ross@Sun.COM int error;
2626007Sthurlow
26310023SGordon.Ross@Sun.COM /*
26410023SGordon.Ross@Sun.COM * This message will be the head of a new mblk chain,
26510023SGordon.Ross@Sun.COM * so we'd like its db_credp set. If we extend this
26610023SGordon.Ross@Sun.COM * chain later, we'll just use allocb_wait()
26710023SGordon.Ross@Sun.COM */
26810023SGordon.Ross@Sun.COM cr = ddi_get_cred();
26910023SGordon.Ross@Sun.COM mblk = allocb_cred_wait(MLEN, STR_NOSIG, &error, cr, NOPID);
2706007Sthurlow
2716007Sthurlow /*
2726007Sthurlow * Leave room in this first mblk so we can
2736007Sthurlow * prepend a 4-byte NetBIOS header.
2746007Sthurlow * See smb_nbst_send()
2756007Sthurlow */
2766007Sthurlow mblk->b_wptr += 4;
2776007Sthurlow mblk->b_rptr = mblk->b_wptr;
2786007Sthurlow
2796007Sthurlow mb_initm(mbp, mblk);
2806007Sthurlow return (0);
2816007Sthurlow }
2826007Sthurlow
2836007Sthurlow
2846007Sthurlow /*
2856007Sthurlow * mb_detach() function returns the value of mbp->mb_top field
2866007Sthurlow * and sets its * value to NULL.
2876007Sthurlow */
2886007Sthurlow
2896007Sthurlow mblk_t *
mb_detach(struct mbchain * mbp)2906007Sthurlow mb_detach(struct mbchain *mbp)
2916007Sthurlow {
2926007Sthurlow mblk_t *m;
2936007Sthurlow
2946007Sthurlow m = mbp->mb_top;
2956007Sthurlow mbp->mb_top = mbp->mb_cur = NULL;
2966007Sthurlow return (m);
2976007Sthurlow }
2986007Sthurlow
2996007Sthurlow /*
3006007Sthurlow * Returns the length of the mblk_t data.
30110023SGordon.Ross@Sun.COM * Should be m_totlen() perhaps?
3026007Sthurlow */
3036007Sthurlow int
m_fixhdr(mblk_t * m0)3046007Sthurlow m_fixhdr(mblk_t *m0)
3056007Sthurlow {
3066007Sthurlow size_t dsz;
3076007Sthurlow
3086007Sthurlow dsz = msgdsize(m0);
3096007Sthurlow return ((int)dsz);
3106007Sthurlow }
3116007Sthurlow
3126007Sthurlow /*
3136007Sthurlow * BSD code set the message header length here, and
3146007Sthurlow * returned the length. We don't have that field, so
3156007Sthurlow * just return the message length.
3166007Sthurlow */
3176007Sthurlow int
mb_fixhdr(struct mbchain * mbp)3186007Sthurlow mb_fixhdr(struct mbchain *mbp)
3196007Sthurlow {
3206007Sthurlow return (m_fixhdr(mbp->mb_top));
3216007Sthurlow }
3226007Sthurlow
3236007Sthurlow
3246007Sthurlow /*
3256007Sthurlow * Check if object of size 'size' fit to the current position and
3266007Sthurlow * allocate new mbuf if not. Advance pointers and increase len. of mbuf(s).
3276007Sthurlow * Return pointer to the object placeholder or NULL if any error occured.
3286007Sthurlow * Note: size should be <= MLEN
3296007Sthurlow */
3306007Sthurlow void *
mb_reserve(struct mbchain * mbp,int size)3316007Sthurlow mb_reserve(struct mbchain *mbp, int size)
3326007Sthurlow {
3336007Sthurlow mblk_t *m, *mn;
3346007Sthurlow void *bpos;
3356007Sthurlow
3366007Sthurlow m = mbp->mb_cur;
3376007Sthurlow /*
3386007Sthurlow * If the requested size is more than the space left.
3396007Sthurlow * Allocate and appenad a new mblk.
3406007Sthurlow */
3416007Sthurlow if (MBLKTAIL(m) < size) {
3426007Sthurlow mn = m_getblk(size, 1);
3436007Sthurlow if (mn == NULL)
3446007Sthurlow return (NULL);
3456007Sthurlow mbp->mb_cur = m->b_cont = mn;
3466007Sthurlow m = mn;
3476007Sthurlow }
3486007Sthurlow /*
3496007Sthurlow * If 'size' bytes fits into the buffer, then
3506007Sthurlow * 1. increment the write pointer to the size.
3516007Sthurlow * 2. return the position from where the memory is reserved.
3526007Sthurlow */
3536007Sthurlow bpos = m->b_wptr;
3546007Sthurlow m->b_wptr += size;
3556007Sthurlow mbp->mb_count += size;
3566007Sthurlow return (bpos);
3576007Sthurlow }
3586007Sthurlow
3596007Sthurlow /*
3606007Sthurlow * All mb_put_*() functions perform an actual copy of the data into mbuf
3616007Sthurlow * chain. Functions which have le or be suffixes will perform conversion to
3626007Sthurlow * the little- or big-endian data formats.
36310023SGordon.Ross@Sun.COM *
36410023SGordon.Ross@Sun.COM * Inline version of mb_put_mem(). Handles the easy case in-line,
36510023SGordon.Ross@Sun.COM * and calls mb_put_mem() if crossing mblk boundaries, etc.
36610023SGordon.Ross@Sun.COM *
36710023SGordon.Ross@Sun.COM * We build with -xspace, which causes these inline functions
36810023SGordon.Ross@Sun.COM * to not be inlined. Using macros instead for now.
36910023SGordon.Ross@Sun.COM */
37010023SGordon.Ross@Sun.COM #ifdef INLINE_WORKS
37110023SGordon.Ross@Sun.COM
37210023SGordon.Ross@Sun.COM static inline int
mb_put_inline(struct mbchain * mbp,void * src,int size)37310023SGordon.Ross@Sun.COM mb_put_inline(struct mbchain *mbp, void *src, int size)
37410023SGordon.Ross@Sun.COM {
37510023SGordon.Ross@Sun.COM mblk_t *m = mbp->mb_cur;
37610023SGordon.Ross@Sun.COM
37710023SGordon.Ross@Sun.COM if (m != NULL && size <= MBLKTAIL(m)) {
37810023SGordon.Ross@Sun.COM uchar_t *p = src;
37910023SGordon.Ross@Sun.COM int n = size;
38010023SGordon.Ross@Sun.COM while (n--)
38110023SGordon.Ross@Sun.COM *(m->b_wptr)++ = *p++;
38210023SGordon.Ross@Sun.COM mbp->mb_count += size;
38310023SGordon.Ross@Sun.COM return (0);
38410023SGordon.Ross@Sun.COM }
38510023SGordon.Ross@Sun.COM return (mb_put_mem(mbp, src, size, MB_MINLINE));
38610023SGordon.Ross@Sun.COM }
38710023SGordon.Ross@Sun.COM #define MB_PUT_INLINE(MBP, SRC, SZ) \
38810023SGordon.Ross@Sun.COM return (mb_put_inline(MBP, SRC, SZ))
38910023SGordon.Ross@Sun.COM
39010023SGordon.Ross@Sun.COM #else /* INLINE_WORKS */
39110023SGordon.Ross@Sun.COM
39210023SGordon.Ross@Sun.COM #define MB_PUT_INLINE(MBP, SRC, SZ) \
39310023SGordon.Ross@Sun.COM mblk_t *m = MBP->mb_cur; \
39410023SGordon.Ross@Sun.COM if (m != NULL && SZ <= MBLKTAIL(m)) { \
39510023SGordon.Ross@Sun.COM uchar_t *p = (void *) SRC; \
39610023SGordon.Ross@Sun.COM int n = SZ; \
39710023SGordon.Ross@Sun.COM while (n--) \
39810023SGordon.Ross@Sun.COM *(m->b_wptr)++ = *p++; \
39910023SGordon.Ross@Sun.COM MBP->mb_count += SZ; \
40010023SGordon.Ross@Sun.COM return (0); \
40110023SGordon.Ross@Sun.COM } \
40210023SGordon.Ross@Sun.COM return (mb_put_mem(MBP, SRC, SZ, MB_MINLINE))
40310023SGordon.Ross@Sun.COM
40410023SGordon.Ross@Sun.COM #endif /* INLINE_WORKS */
40510023SGordon.Ross@Sun.COM
40610023SGordon.Ross@Sun.COM /*
40710023SGordon.Ross@Sun.COM * Assumes total data length in previous mblks is EVEN.
40810023SGordon.Ross@Sun.COM * Might need to compute the offset from mb_top instead.
4096007Sthurlow */
4106007Sthurlow int
mb_put_padbyte(struct mbchain * mbp)4116007Sthurlow mb_put_padbyte(struct mbchain *mbp)
4126007Sthurlow {
41310023SGordon.Ross@Sun.COM uintptr_t dst;
41410023SGordon.Ross@Sun.COM char v = 0;
4156007Sthurlow
41610023SGordon.Ross@Sun.COM dst = (uintptr_t)mbp->mb_cur->b_wptr;
4176007Sthurlow /* only add padding if address is odd */
41810023SGordon.Ross@Sun.COM if (dst & 1) {
41910023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
42010023SGordon.Ross@Sun.COM }
42110023SGordon.Ross@Sun.COM
42210023SGordon.Ross@Sun.COM return (0);
4236007Sthurlow }
4246007Sthurlow
4256007Sthurlow int
mb_put_uint8(struct mbchain * mbp,u_int8_t x)4266007Sthurlow mb_put_uint8(struct mbchain *mbp, u_int8_t x)
4276007Sthurlow {
42810023SGordon.Ross@Sun.COM u_int8_t v = x;
42910023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4306007Sthurlow }
4316007Sthurlow
4326007Sthurlow int
mb_put_uint16be(struct mbchain * mbp,u_int16_t x)4336007Sthurlow mb_put_uint16be(struct mbchain *mbp, u_int16_t x)
4346007Sthurlow {
43510023SGordon.Ross@Sun.COM u_int16_t v = htobes(x);
43610023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4376007Sthurlow }
4386007Sthurlow
4396007Sthurlow int
mb_put_uint16le(struct mbchain * mbp,u_int16_t x)4406007Sthurlow mb_put_uint16le(struct mbchain *mbp, u_int16_t x)
4416007Sthurlow {
44210023SGordon.Ross@Sun.COM u_int16_t v = htoles(x);
44310023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4446007Sthurlow }
4456007Sthurlow
4466007Sthurlow int
mb_put_uint32be(struct mbchain * mbp,u_int32_t x)4476007Sthurlow mb_put_uint32be(struct mbchain *mbp, u_int32_t x)
4486007Sthurlow {
44910023SGordon.Ross@Sun.COM u_int32_t v = htobel(x);
45010023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4516007Sthurlow }
4526007Sthurlow
4536007Sthurlow int
mb_put_uint32le(struct mbchain * mbp,u_int32_t x)4546007Sthurlow mb_put_uint32le(struct mbchain *mbp, u_int32_t x)
4556007Sthurlow {
45610023SGordon.Ross@Sun.COM u_int32_t v = htolel(x);
45710023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4586007Sthurlow }
4596007Sthurlow
4606007Sthurlow int
mb_put_uint64be(struct mbchain * mbp,u_int64_t x)4616007Sthurlow mb_put_uint64be(struct mbchain *mbp, u_int64_t x)
4626007Sthurlow {
46310023SGordon.Ross@Sun.COM u_int64_t v = htobeq(x);
46410023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4656007Sthurlow }
4666007Sthurlow
4676007Sthurlow int
mb_put_uint64le(struct mbchain * mbp,u_int64_t x)4686007Sthurlow mb_put_uint64le(struct mbchain *mbp, u_int64_t x)
4696007Sthurlow {
47010023SGordon.Ross@Sun.COM u_int64_t v = htoleq(x);
47110023SGordon.Ross@Sun.COM MB_PUT_INLINE(mbp, &v, sizeof (v));
4726007Sthurlow }
4736007Sthurlow
4746007Sthurlow /*
4756007Sthurlow * mb_put_mem() function copies size bytes of data specified by the source
4766007Sthurlow * argument to an mbuf chain. The type argument specifies the method used
4776007Sthurlow * to perform a copy
4786007Sthurlow */
4796007Sthurlow int
mb_put_mem(struct mbchain * mbp,const void * vsrc,int size,int type)48010023SGordon.Ross@Sun.COM mb_put_mem(struct mbchain *mbp, const void *vsrc, int size, int type)
4816007Sthurlow {
48210023SGordon.Ross@Sun.COM mblk_t *n, *m = mbp->mb_cur;
48310023SGordon.Ross@Sun.COM c_caddr_t source = vsrc;
4846007Sthurlow c_caddr_t src;
48510023SGordon.Ross@Sun.COM caddr_t dst;
4866007Sthurlow uint64_t diff;
48710023SGordon.Ross@Sun.COM int cplen, mleft, count;
4886007Sthurlow
4896007Sthurlow diff = MBLKTAIL(m);
4906007Sthurlow ASSERT(diff == (uint64_t)((int)diff));
4916007Sthurlow mleft = (int)diff;
4926007Sthurlow
4936007Sthurlow while (size > 0) {
4946007Sthurlow if (mleft == 0) {
4956007Sthurlow if (m->b_cont == NULL) {
4966007Sthurlow /*
4976007Sthurlow * Changed m_getm() to m_getblk()
4986007Sthurlow * with the requested size, so we
4996007Sthurlow * don't need m_getm() anymore.
5006007Sthurlow */
5016007Sthurlow n = m_getblk(size, 1);
5026007Sthurlow if (n == NULL)
5036007Sthurlow return (ENOBUFS);
5046007Sthurlow m->b_cont = n;
5056007Sthurlow }
5066007Sthurlow m = m->b_cont;
5076007Sthurlow diff = MBLKTAIL(m);
5086007Sthurlow ASSERT(diff == (uint64_t)((int)diff));
5096007Sthurlow mleft = (int)diff;
5106007Sthurlow continue;
5116007Sthurlow }
5126007Sthurlow cplen = mleft > size ? size : mleft;
5136007Sthurlow dst = (caddr_t)m->b_wptr;
5146007Sthurlow switch (type) {
5156007Sthurlow case MB_MINLINE:
5166007Sthurlow for (src = source, count = cplen; count; count--)
5176007Sthurlow *dst++ = *src++;
5186007Sthurlow break;
5196007Sthurlow case MB_MSYSTEM:
5206007Sthurlow bcopy(source, dst, cplen);
5216007Sthurlow break;
5226007Sthurlow case MB_MUSER:
52310023SGordon.Ross@Sun.COM if (copyin((void *)source, dst, cplen))
52410023SGordon.Ross@Sun.COM return (EFAULT);
5256007Sthurlow break;
5266007Sthurlow case MB_MZERO:
5276007Sthurlow bzero(dst, cplen);
5286007Sthurlow break;
5296007Sthurlow }
5306007Sthurlow size -= cplen;
5316007Sthurlow source += cplen;
5326007Sthurlow mleft -= cplen;
5336007Sthurlow m->b_wptr += cplen;
5346007Sthurlow mbp->mb_count += cplen;
5356007Sthurlow }
5366007Sthurlow mbp->mb_cur = m;
5376007Sthurlow return (0);
5386007Sthurlow }
5396007Sthurlow
5406007Sthurlow /*
5416007Sthurlow * Append an mblk to the chain.
5426007Sthurlow */
5436007Sthurlow int
mb_put_mbuf(struct mbchain * mbp,mblk_t * m)5446007Sthurlow mb_put_mbuf(struct mbchain *mbp, mblk_t *m)
5456007Sthurlow {
5466007Sthurlow mblk_t *mb;
5476007Sthurlow
5486007Sthurlow /* See: linkb(9f) */
5496007Sthurlow for (mb = mbp->mb_cur; mb->b_cont; mb = mb->b_cont)
5506007Sthurlow ;
5516007Sthurlow mb->b_cont = m;
5526007Sthurlow mbp->mb_cur = m;
5536007Sthurlow mbp->mb_count += msgdsize(m);
5546007Sthurlow
5556007Sthurlow return (0);
5566007Sthurlow }
5576007Sthurlow
5586007Sthurlow /*
5596007Sthurlow * copies a uio scatter/gather list to an mbuf chain.
5606007Sthurlow */
5616007Sthurlow int
mb_put_uio(struct mbchain * mbp,uio_t * uiop,size_t size)56210023SGordon.Ross@Sun.COM mb_put_uio(struct mbchain *mbp, uio_t *uiop, size_t size)
5636007Sthurlow {
56410023SGordon.Ross@Sun.COM size_t left;
5656007Sthurlow int mtype, error;
5666007Sthurlow
5676007Sthurlow mtype = (uio_isuserspace(uiop) ? MB_MUSER : MB_MSYSTEM);
5686007Sthurlow while (size > 0 && uiop->uio_resid) {
56910023SGordon.Ross@Sun.COM if (uiop->uio_iovcnt <= 0 ||
57010023SGordon.Ross@Sun.COM uio_curriovbase(uiop) == USER_ADDR_NULL)
5716007Sthurlow return (EFBIG);
5726007Sthurlow left = uio_curriovlen(uiop);
5736007Sthurlow if (left > size)
5746007Sthurlow left = size;
5756007Sthurlow error = mb_put_mem(mbp, CAST_DOWN(caddr_t,
5766007Sthurlow uio_curriovbase(uiop)), left, mtype);
5776007Sthurlow if (error)
5786007Sthurlow return (error);
5796007Sthurlow uio_update(uiop, left);
5806007Sthurlow size -= left;
5816007Sthurlow }
5826007Sthurlow return (0);
5836007Sthurlow }
5846007Sthurlow
5856007Sthurlow /*
5866007Sthurlow * Routines for fetching data from an mbuf chain
5876007Sthurlow */
5886007Sthurlow
5896007Sthurlow void
md_initm(struct mdchain * mdp,mblk_t * m)5906007Sthurlow md_initm(struct mdchain *mdp, mblk_t *m)
5916007Sthurlow {
5926007Sthurlow bzero(mdp, sizeof (*mdp));
5936007Sthurlow mdp->md_top = mdp->md_cur = m;
5946007Sthurlow mdp->md_pos = m->b_rptr;
5956007Sthurlow }
5966007Sthurlow
5976007Sthurlow void
md_done(struct mdchain * mdp)5986007Sthurlow md_done(struct mdchain *mdp)
5996007Sthurlow {
6006007Sthurlow mblk_t *m;
6016007Sthurlow
6026007Sthurlow /*
6036007Sthurlow * Deal with the fact that we can error out of
6046007Sthurlow * smb_t2_reply or smb_nt_reply without using up
6056007Sthurlow * all the "records" added by md_append_record().
6066007Sthurlow */
6076007Sthurlow while ((m = mdp->md_top) != NULL) {
6086007Sthurlow mdp->md_top = m->b_next;
6096007Sthurlow m->b_next = NULL;
6106007Sthurlow freemsg(m);
6116007Sthurlow }
6126007Sthurlow /* Avoid dangling references */
6136007Sthurlow mdp->md_cur = NULL;
6146007Sthurlow mdp->md_pos = NULL;
6156007Sthurlow }
6166007Sthurlow
6176007Sthurlow /*
6186007Sthurlow * Append a new message (separate mbuf chain).
6196007Sthurlow * It is caller responsibility to prevent
6206007Sthurlow * multiple calls to fetch/record routines.
621*11332SGordon.Ross@Sun.COM * Note unusual use of mblk->b_next here.
6226007Sthurlow */
6236007Sthurlow void
md_append_record(struct mdchain * mdp,mblk_t * top)6246007Sthurlow md_append_record(struct mdchain *mdp, mblk_t *top)
6256007Sthurlow {
6266007Sthurlow mblk_t *m;
6276007Sthurlow
6286007Sthurlow top->b_next = NULL;
6296007Sthurlow if (mdp->md_top == NULL) {
6306007Sthurlow md_initm(mdp, top);
6316007Sthurlow return;
6326007Sthurlow }
6336007Sthurlow m = mdp->md_top;
6346007Sthurlow /* Get to last message (not b_cont chain) */
6356007Sthurlow while (m->b_next)
6366007Sthurlow m = m->b_next;
6376007Sthurlow m->b_next = top;
6386007Sthurlow }
6396007Sthurlow
6406007Sthurlow /*
6416007Sthurlow * Advance mdp->md_top to the next message.
642*11332SGordon.Ross@Sun.COM * Note unusual use of mblk->b_next here.
6436007Sthurlow */
644*11332SGordon.Ross@Sun.COM void
md_next_record(struct mdchain * mdp)6456007Sthurlow md_next_record(struct mdchain *mdp)
6466007Sthurlow {
647*11332SGordon.Ross@Sun.COM mblk_t *m, *top;
648*11332SGordon.Ross@Sun.COM
649*11332SGordon.Ross@Sun.COM if ((top = mdp->md_top) == NULL)
650*11332SGordon.Ross@Sun.COM return;
6516007Sthurlow
652*11332SGordon.Ross@Sun.COM /*
653*11332SGordon.Ross@Sun.COM * Get the next message, if any,
654*11332SGordon.Ross@Sun.COM * stored by md_append_record.
655*11332SGordon.Ross@Sun.COM * Note: NOT b_cont chain
656*11332SGordon.Ross@Sun.COM */
657*11332SGordon.Ross@Sun.COM m = top->b_next;
658*11332SGordon.Ross@Sun.COM top->b_next = NULL;
659*11332SGordon.Ross@Sun.COM
660*11332SGordon.Ross@Sun.COM /* Done with old "top". */
6616007Sthurlow md_done(mdp);
6626007Sthurlow if (m == NULL)
663*11332SGordon.Ross@Sun.COM return;
664*11332SGordon.Ross@Sun.COM
665*11332SGordon.Ross@Sun.COM /* Setup new "top". */
6666007Sthurlow md_initm(mdp, m);
6676007Sthurlow }
6686007Sthurlow
66910023SGordon.Ross@Sun.COM /*
67010023SGordon.Ross@Sun.COM * Inline version of md_get_mem(). Handles the easy case in-line,
67110023SGordon.Ross@Sun.COM * and calls md_get_mem() if crossing mblk boundaries, etc.
67210023SGordon.Ross@Sun.COM */
67310023SGordon.Ross@Sun.COM #ifdef INLINE_WORKS /* see above */
67410023SGordon.Ross@Sun.COM
67510023SGordon.Ross@Sun.COM static inline int
md_get_inline(struct mdchain * mdp,void * dst,int size)67610023SGordon.Ross@Sun.COM md_get_inline(struct mdchain *mdp, void *dst, int size)
67710023SGordon.Ross@Sun.COM {
67810023SGordon.Ross@Sun.COM mblk_t *m = mdp->md_cur;
67910023SGordon.Ross@Sun.COM
68010023SGordon.Ross@Sun.COM if (m != NULL && mdp->md_pos + size <= m->b_wptr) {
68110023SGordon.Ross@Sun.COM uchar_t *p = dst;
68210023SGordon.Ross@Sun.COM int n = size;
68310023SGordon.Ross@Sun.COM while (n--)
68410023SGordon.Ross@Sun.COM *p++ = *(mdp->md_pos)++;
68510023SGordon.Ross@Sun.COM /* no md_count += size */
68610023SGordon.Ross@Sun.COM return (0);
68710023SGordon.Ross@Sun.COM }
68810023SGordon.Ross@Sun.COM return (md_get_mem(mdp, dst, size, MB_MINLINE));
68910023SGordon.Ross@Sun.COM }
69010023SGordon.Ross@Sun.COM #define MD_GET_INLINE(MDP, DST, SZ) \
69110023SGordon.Ross@Sun.COM error = md_get_inline(MDP, DST, SZ)
69210023SGordon.Ross@Sun.COM
69310023SGordon.Ross@Sun.COM #else /* INLINE_WORKS */
69410023SGordon.Ross@Sun.COM
69510023SGordon.Ross@Sun.COM /* Note, sets variable: error */
69610023SGordon.Ross@Sun.COM #define MD_GET_INLINE(MDP, DST, SZ) \
69710023SGordon.Ross@Sun.COM mblk_t *m = MDP->md_cur; \
69810023SGordon.Ross@Sun.COM if (m != NULL && MDP->md_pos + SZ <= m->b_wptr) { \
69910023SGordon.Ross@Sun.COM uchar_t *p = (void *) DST; \
70010023SGordon.Ross@Sun.COM int n = SZ; \
70110023SGordon.Ross@Sun.COM while (n--) \
70210023SGordon.Ross@Sun.COM *p++ = *(mdp->md_pos)++; \
70310023SGordon.Ross@Sun.COM /* no md_count += SZ */ \
70410023SGordon.Ross@Sun.COM error = 0; \
70510023SGordon.Ross@Sun.COM } else \
70610023SGordon.Ross@Sun.COM error = md_get_mem(MDP, DST, SZ, MB_MINLINE)
70710023SGordon.Ross@Sun.COM
70810023SGordon.Ross@Sun.COM #endif /* INLINE_WORKS */
70910023SGordon.Ross@Sun.COM
71010023SGordon.Ross@Sun.COM
7116007Sthurlow int
md_get_uint8(struct mdchain * mdp,u_int8_t * x)7126007Sthurlow md_get_uint8(struct mdchain *mdp, u_int8_t *x)
7136007Sthurlow {
71410023SGordon.Ross@Sun.COM uint8_t v;
71510023SGordon.Ross@Sun.COM int error;
71610023SGordon.Ross@Sun.COM
71710023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
71810023SGordon.Ross@Sun.COM if (x)
71910023SGordon.Ross@Sun.COM *x = v;
72010023SGordon.Ross@Sun.COM return (error);
7216007Sthurlow }
7226007Sthurlow
7236007Sthurlow int
md_get_uint16be(struct mdchain * mdp,u_int16_t * x)72410023SGordon.Ross@Sun.COM md_get_uint16be(struct mdchain *mdp, u_int16_t *x) {
72510023SGordon.Ross@Sun.COM u_int16_t v;
72610023SGordon.Ross@Sun.COM int error;
72710023SGordon.Ross@Sun.COM
72810023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
72910023SGordon.Ross@Sun.COM if (x)
73010023SGordon.Ross@Sun.COM *x = betohs(v);
73110023SGordon.Ross@Sun.COM return (error);
7326007Sthurlow }
7336007Sthurlow
7346007Sthurlow int
md_get_uint16le(struct mdchain * mdp,u_int16_t * x)7356007Sthurlow md_get_uint16le(struct mdchain *mdp, u_int16_t *x)
7366007Sthurlow {
7376007Sthurlow u_int16_t v;
73810023SGordon.Ross@Sun.COM int error;
7396007Sthurlow
74010023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
7416007Sthurlow if (x)
7426007Sthurlow *x = letohs(v);
7436007Sthurlow return (error);
7446007Sthurlow }
7456007Sthurlow
7466007Sthurlow int
md_get_uint32be(struct mdchain * mdp,u_int32_t * x)7476007Sthurlow md_get_uint32be(struct mdchain *mdp, u_int32_t *x)
7486007Sthurlow {
7496007Sthurlow u_int32_t v;
7506007Sthurlow int error;
7516007Sthurlow
75210023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
7536007Sthurlow if (x)
7546007Sthurlow *x = betohl(v);
7556007Sthurlow return (error);
7566007Sthurlow }
7576007Sthurlow
7586007Sthurlow int
md_get_uint32le(struct mdchain * mdp,u_int32_t * x)7596007Sthurlow md_get_uint32le(struct mdchain *mdp, u_int32_t *x)
7606007Sthurlow {
7616007Sthurlow u_int32_t v;
7626007Sthurlow int error;
7636007Sthurlow
76410023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
7656007Sthurlow if (x)
7666007Sthurlow *x = letohl(v);
7676007Sthurlow return (error);
7686007Sthurlow }
7696007Sthurlow
7706007Sthurlow int
md_get_uint64be(struct mdchain * mdp,u_int64_t * x)7716007Sthurlow md_get_uint64be(struct mdchain *mdp, u_int64_t *x)
7726007Sthurlow {
7736007Sthurlow u_int64_t v;
7746007Sthurlow int error;
7756007Sthurlow
77610023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
7776007Sthurlow if (x)
7786007Sthurlow *x = betohq(v);
7796007Sthurlow return (error);
7806007Sthurlow }
7816007Sthurlow
7826007Sthurlow int
md_get_uint64le(struct mdchain * mdp,u_int64_t * x)7836007Sthurlow md_get_uint64le(struct mdchain *mdp, u_int64_t *x)
7846007Sthurlow {
7856007Sthurlow u_int64_t v;
7866007Sthurlow int error;
7876007Sthurlow
78810023SGordon.Ross@Sun.COM MD_GET_INLINE(mdp, &v, sizeof (v));
7896007Sthurlow if (x)
7906007Sthurlow *x = letohq(v);
7916007Sthurlow return (error);
7926007Sthurlow }
7936007Sthurlow
7946007Sthurlow int
md_get_mem(struct mdchain * mdp,void * vdst,int size,int type)79510023SGordon.Ross@Sun.COM md_get_mem(struct mdchain *mdp, void *vdst, int size, int type)
7966007Sthurlow {
7976007Sthurlow mblk_t *m = mdp->md_cur;
79810023SGordon.Ross@Sun.COM caddr_t target = vdst;
7996007Sthurlow unsigned char *s;
8006007Sthurlow uint64_t diff;
80110023SGordon.Ross@Sun.COM int count;
8026007Sthurlow
8036007Sthurlow while (size > 0) {
8046007Sthurlow if (m == NULL) {
8056007Sthurlow SMBSDEBUG("incomplete copy\n");
8066007Sthurlow return (EBADRPC);
8076007Sthurlow }
8086007Sthurlow
8096007Sthurlow /*
8106007Sthurlow * Offset in the current MBUF.
8116007Sthurlow */
8126007Sthurlow s = mdp->md_pos;
8136007Sthurlow ASSERT((m->b_rptr <= s) && (s <= m->b_wptr));
8146007Sthurlow
8156007Sthurlow /* Data remaining. */
8166007Sthurlow diff = (uintptr_t)m->b_wptr - (uintptr_t)s;
8176007Sthurlow ASSERT(diff == (uint64_t)((int)diff));
8186007Sthurlow count = (int)diff;
8196007Sthurlow
8206007Sthurlow /*
8216007Sthurlow * Check if the no. of bytes remaining is less than
8226007Sthurlow * the bytes requested.
8236007Sthurlow */
8246007Sthurlow if (count == 0) {
8256007Sthurlow m = m->b_cont;
8266007Sthurlow if (m) {
8276007Sthurlow mdp->md_cur = m;
8286007Sthurlow mdp->md_pos = s = m->b_rptr;
8296007Sthurlow }
8306007Sthurlow continue;
8316007Sthurlow }
8326007Sthurlow if (count > size)
8336007Sthurlow count = size;
8346007Sthurlow size -= count;
8356007Sthurlow mdp->md_pos += count;
8366007Sthurlow if (target == NULL)
8376007Sthurlow continue;
8386007Sthurlow switch (type) {
8396007Sthurlow case MB_MUSER:
84010023SGordon.Ross@Sun.COM if (copyout(s, target, count))
84110023SGordon.Ross@Sun.COM return (EFAULT);
8426007Sthurlow break;
8436007Sthurlow case MB_MSYSTEM:
8446007Sthurlow bcopy(s, target, count);
8456007Sthurlow break;
8466007Sthurlow case MB_MINLINE:
8476007Sthurlow while (count--)
8486007Sthurlow *target++ = *s++;
8496007Sthurlow continue;
8506007Sthurlow }
8516007Sthurlow target += count;
8526007Sthurlow }
8536007Sthurlow return (0);
8546007Sthurlow }
8556007Sthurlow
8566007Sthurlow /*
8576007Sthurlow * Get the next SIZE bytes as a separate mblk.
8586007Sthurlow */
8596007Sthurlow int
md_get_mbuf(struct mdchain * mdp,int size,mblk_t ** ret)8606007Sthurlow md_get_mbuf(struct mdchain *mdp, int size, mblk_t **ret)
8616007Sthurlow {
8626007Sthurlow mblk_t *m, *rm;
8636007Sthurlow
8646007Sthurlow unsigned char *s;
8656007Sthurlow uint64_t diff;
8666007Sthurlow int off;
8676007Sthurlow
8686007Sthurlow /*
8696007Sthurlow * Offset in the current MBUF.
8706007Sthurlow */
8716007Sthurlow m = mdp->md_cur;
8726007Sthurlow s = mdp->md_pos;
8736007Sthurlow ASSERT((m->b_rptr <= s) && (s <= m->b_wptr));
8746007Sthurlow diff = (uintptr_t)s - (uintptr_t)m->b_rptr;
8756007Sthurlow ASSERT(diff == (uint64_t)((int)diff));
8766007Sthurlow off = (int)diff;
8776007Sthurlow
8786007Sthurlow rm = m_copym(m, off, size, M_WAITOK);
8796007Sthurlow if (rm == NULL)
8806007Sthurlow return (EBADRPC);
8816007Sthurlow
8826007Sthurlow *ret = rm;
8836007Sthurlow return (0);
8846007Sthurlow }
8856007Sthurlow
8866007Sthurlow int
md_get_uio(struct mdchain * mdp,uio_t * uiop,size_t size)88710023SGordon.Ross@Sun.COM md_get_uio(struct mdchain *mdp, uio_t *uiop, size_t size)
8886007Sthurlow {
8896007Sthurlow size_t left;
8906007Sthurlow int mtype, error;
8916007Sthurlow
8926007Sthurlow mtype = (uio_isuserspace(uiop) ? MB_MUSER : MB_MSYSTEM);
8936007Sthurlow while (size > 0 && uiop->uio_resid) {
8946007Sthurlow if (uiop->uio_iovcnt <= 0 ||
8956007Sthurlow uio_curriovbase(uiop) == USER_ADDR_NULL)
8966007Sthurlow return (EFBIG);
8976007Sthurlow left = uio_curriovlen(uiop);
8986007Sthurlow if (left > size)
8996007Sthurlow left = size;
9006007Sthurlow error = md_get_mem(mdp, CAST_DOWN(caddr_t,
9016007Sthurlow uio_curriovbase(uiop)), left, mtype);
9026007Sthurlow if (error)
9036007Sthurlow return (error);
9046007Sthurlow uio_update(uiop, left);
9056007Sthurlow size -= left;
9066007Sthurlow }
9076007Sthurlow return (0);
9086007Sthurlow }
9096007Sthurlow
9106007Sthurlow /*
9116007Sthurlow * Additions for Solaris
9126007Sthurlow */
9136007Sthurlow
9146007Sthurlow /*
9156007Sthurlow * concatenate mblk chain n to m.
9166007Sthurlow * go till end of data in m.
9176007Sthurlow * then add the link of b_cont to n.
9186007Sthurlow * See: linkb(9f)
9196007Sthurlow */
9206007Sthurlow
m_cat(mblk_t * m,mblk_t * n)9216007Sthurlow void m_cat(
9226007Sthurlow mblk_t *m,
9236007Sthurlow mblk_t *n)
9246007Sthurlow {
9256007Sthurlow if (!n)
9266007Sthurlow return;
9276007Sthurlow while (m->b_cont) {
9286007Sthurlow m = m->b_cont;
9296007Sthurlow }
9306007Sthurlow m->b_cont = n;
9316007Sthurlow }
9326007Sthurlow
9336007Sthurlow /*ARGSUSED*/
9346007Sthurlow mblk_t *
m_copym(mblk_t * m,int off,int len,int wait)9356007Sthurlow m_copym(mblk_t *m, int off, int len, int wait)
9366007Sthurlow {
9376007Sthurlow mblk_t *n;
9386007Sthurlow size_t dsz;
9396007Sthurlow ssize_t adj;
9406007Sthurlow
9416007Sthurlow dsz = msgdsize(m);
9426007Sthurlow if (len == M_COPYALL) {
9436007Sthurlow if (off > dsz)
9446007Sthurlow return (0);
9456007Sthurlow } else {
9466007Sthurlow if ((off + len) > dsz)
9476007Sthurlow return (0);
9486007Sthurlow }
9496007Sthurlow
9506007Sthurlow if ((n = dupmsg(m)) == NULL)
9516007Sthurlow return (0);
9526007Sthurlow
9536007Sthurlow /* trim from head */
9546007Sthurlow adj = off;
9556007Sthurlow if (!adjmsg(n, adj)) {
9566007Sthurlow freemsg(n);
9576007Sthurlow return (0);
9586007Sthurlow }
9596007Sthurlow
9606007Sthurlow /* trim from tail */
9616007Sthurlow if (len != M_COPYALL) {
9626007Sthurlow dsz = msgdsize(n);
9636007Sthurlow ASSERT(len <= dsz);
9646007Sthurlow if (len < dsz) {
9656007Sthurlow adj = (ssize_t)len - (ssize_t)dsz;
9666007Sthurlow ASSERT(adj < 0);
967*11332SGordon.Ross@Sun.COM (void) adjmsg(n, adj);
9686007Sthurlow }
9696007Sthurlow }
9706007Sthurlow
9716007Sthurlow return (n);
9726007Sthurlow }
9736007Sthurlow
9746007Sthurlow /*
9756007Sthurlow * Get "rqlen" contiguous bytes into the first mblk of a chain.
9766007Sthurlow */
9776007Sthurlow mblk_t *
m_pullup(mblk_t * m,int rqlen)9786007Sthurlow m_pullup(
9796007Sthurlow mblk_t *m,
9806007Sthurlow int rqlen)
9816007Sthurlow {
9826007Sthurlow ptrdiff_t diff;
9836007Sthurlow
9846007Sthurlow diff = MBLKL(m);
9856007Sthurlow ASSERT(diff == (ptrdiff_t)((int)diff));
9866007Sthurlow if ((int)diff < rqlen) {
9876007Sthurlow /* This should be rare. */
9886007Sthurlow if (!pullupmsg(m, rqlen)) {
9896007Sthurlow SMBSDEBUG("pullupmsg failed!\n");
9906007Sthurlow freemsg(m);
9916007Sthurlow return (NULL);
9926007Sthurlow }
9936007Sthurlow }
9946007Sthurlow return (m);
9956007Sthurlow }
9966007Sthurlow
9976007Sthurlow
9986007Sthurlow /*
9996007Sthurlow * m_split : split the mblk from the offset(len0) to the end.
10006007Sthurlow * Partition an mbuf chain in two pieces, returning the tail --
10016007Sthurlow * all but the first len0 bytes. In case of failure, it returns NULL and
10026007Sthurlow * attempts to restore the chain to its original state.
10036007Sthurlow * Similar to dupmsg() + adjmsg() on Solaris.
10046007Sthurlow */
10056007Sthurlow /*ARGSUSED*/
10066007Sthurlow mblk_t *
m_split(mblk_t * m0,int len0,int wait)10076007Sthurlow m_split(
10086007Sthurlow mblk_t *m0,
10096007Sthurlow int len0,
10106007Sthurlow int wait)
10116007Sthurlow {
10126007Sthurlow mblk_t *m, *n;
10136007Sthurlow int mbl, len = len0;
10146007Sthurlow ptrdiff_t diff;
10156007Sthurlow
10166007Sthurlow #if 0 /* If life were simple, this would be: */
10176007Sthurlow for (m = m0; m && len > MBLKL(m); m = m->b_cont)
10186007Sthurlow len -= MBLKL(m);
10196007Sthurlow #else /* but with LP64 and picky lint we have: */
10206007Sthurlow for (m = m0; m; m = m->b_cont) {
10216007Sthurlow diff = MBLKL(m);
10226007Sthurlow ASSERT(diff == (ptrdiff_t)((int)diff));
10236007Sthurlow mbl = (int)diff;
10246007Sthurlow if (len <= mbl)
10256007Sthurlow break;
10266007Sthurlow len -= mbl;
10276007Sthurlow }
10286007Sthurlow #endif
10296007Sthurlow
10306007Sthurlow if (m == 0)
10316007Sthurlow return (0);
10326007Sthurlow
10336007Sthurlow /* This is the one to split (dupb, adjust) */
10346007Sthurlow if ((n = dupb(m)) == 0)
10356007Sthurlow return (0);
10366007Sthurlow
10376007Sthurlow ASSERT(len <= MBLKL(m));
10386007Sthurlow
10396007Sthurlow m->b_wptr = m->b_rptr + len;
10406007Sthurlow n->b_rptr += len;
10416007Sthurlow
10426007Sthurlow /* Move any b_cont (tail) to the new head. */
10436007Sthurlow n->b_cont = m->b_cont;
10446007Sthurlow m->b_cont = NULL;
10456007Sthurlow
10466007Sthurlow return (n);
10476007Sthurlow }
1048