10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52627Smaheshvs * Common Development and Distribution License (the "License").
62627Smaheshvs * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11539SChunli.Zhang@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
310Sstevel@tonic-gate * under license from the Regents of the University of California.
320Sstevel@tonic-gate */
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * xdr_mblk.c, XDR implementation on kernel streams mblks.
360Sstevel@tonic-gate */
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <sys/param.h>
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/systm.h>
410Sstevel@tonic-gate #include <sys/stream.h>
420Sstevel@tonic-gate #include <sys/cmn_err.h>
430Sstevel@tonic-gate #include <sys/strsubr.h>
440Sstevel@tonic-gate #include <sys/strsun.h>
450Sstevel@tonic-gate #include <sys/debug.h>
460Sstevel@tonic-gate #include <sys/sysmacros.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate #include <rpc/types.h>
490Sstevel@tonic-gate #include <rpc/xdr.h>
500Sstevel@tonic-gate
510Sstevel@tonic-gate static bool_t xdrmblk_getint32(XDR *, int32_t *);
520Sstevel@tonic-gate static bool_t xdrmblk_putint32(XDR *, int32_t *);
530Sstevel@tonic-gate static bool_t xdrmblk_getbytes(XDR *, caddr_t, int);
540Sstevel@tonic-gate static bool_t xdrmblk_putbytes(XDR *, caddr_t, int);
550Sstevel@tonic-gate static uint_t xdrmblk_getpos(XDR *);
560Sstevel@tonic-gate static bool_t xdrmblk_setpos(XDR *, uint_t);
570Sstevel@tonic-gate static rpc_inline_t *xdrmblk_inline(XDR *, int);
580Sstevel@tonic-gate static void xdrmblk_destroy(XDR *);
590Sstevel@tonic-gate static bool_t xdrmblk_control(XDR *, int, void *);
600Sstevel@tonic-gate
610Sstevel@tonic-gate static mblk_t *xdrmblk_alloc(int);
620Sstevel@tonic-gate
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate * Xdr on mblks operations vector.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate struct xdr_ops xdrmblk_ops = {
670Sstevel@tonic-gate xdrmblk_getbytes,
680Sstevel@tonic-gate xdrmblk_putbytes,
690Sstevel@tonic-gate xdrmblk_getpos,
700Sstevel@tonic-gate xdrmblk_setpos,
710Sstevel@tonic-gate xdrmblk_inline,
720Sstevel@tonic-gate xdrmblk_destroy,
730Sstevel@tonic-gate xdrmblk_control,
740Sstevel@tonic-gate xdrmblk_getint32,
750Sstevel@tonic-gate xdrmblk_putint32
760Sstevel@tonic-gate };
770Sstevel@tonic-gate
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate * Initialize xdr stream.
800Sstevel@tonic-gate */
810Sstevel@tonic-gate void
xdrmblk_init(XDR * xdrs,mblk_t * m,enum xdr_op op,int sz)820Sstevel@tonic-gate xdrmblk_init(XDR *xdrs, mblk_t *m, enum xdr_op op, int sz)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate xdrs->x_op = op;
850Sstevel@tonic-gate xdrs->x_ops = &xdrmblk_ops;
860Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
870Sstevel@tonic-gate xdrs->x_public = NULL;
880Sstevel@tonic-gate xdrs->x_private = (caddr_t)(uintptr_t)sz;
890Sstevel@tonic-gate
900Sstevel@tonic-gate if (op == XDR_DECODE)
910Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
920Sstevel@tonic-gate else
930Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_datap->db_base);
940Sstevel@tonic-gate }
950Sstevel@tonic-gate
960Sstevel@tonic-gate /* ARGSUSED */
970Sstevel@tonic-gate static void
xdrmblk_destroy(XDR * xdrs)980Sstevel@tonic-gate xdrmblk_destroy(XDR *xdrs)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate static bool_t
xdrmblk_getint32(XDR * xdrs,int32_t * int32p)1030Sstevel@tonic-gate xdrmblk_getint32(XDR *xdrs, int32_t *int32p)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate mblk_t *m;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /* LINTED pointer alignment */
1080Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
1090Sstevel@tonic-gate if (m == NULL)
1100Sstevel@tonic-gate return (FALSE);
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * If the pointer is not aligned or there is not
1130Sstevel@tonic-gate * enough bytes, pullupmsg to get enough bytes and
1140Sstevel@tonic-gate * align the mblk.
1150Sstevel@tonic-gate */
1160Sstevel@tonic-gate if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) ||
1177387SRobert.Gordon@Sun.COM xdrs->x_handy < sizeof (int32_t)) {
1180Sstevel@tonic-gate while (!pullupmsg(m, sizeof (int32_t))) {
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * Could have failed due to not
1210Sstevel@tonic-gate * enough data or an allocb failure.
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate if (xmsgsize(m) < sizeof (int32_t))
1240Sstevel@tonic-gate return (FALSE);
1250Sstevel@tonic-gate delay(hz);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate /* LINTED pointer alignment */
1310Sstevel@tonic-gate *int32p = ntohl(*((int32_t *)(m->b_rptr)));
1320Sstevel@tonic-gate m->b_rptr += sizeof (int32_t);
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate * Instead of leaving handy as 0 causing more pullupmsg's
1360Sstevel@tonic-gate * simply move to the next mblk.
1370Sstevel@tonic-gate */
1380Sstevel@tonic-gate if ((xdrs->x_handy -= sizeof (int32_t)) == 0) {
1390Sstevel@tonic-gate m = m->b_cont;
1400Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
1410Sstevel@tonic-gate if (m != NULL)
1420Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate return (TRUE);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate static bool_t
xdrmblk_putint32(XDR * xdrs,int32_t * int32p)1480Sstevel@tonic-gate xdrmblk_putint32(XDR *xdrs, int32_t *int32p)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate mblk_t *m;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate /* LINTED pointer alignment */
1530Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
1540Sstevel@tonic-gate if (m == NULL)
1550Sstevel@tonic-gate return (FALSE);
1560Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) {
1570Sstevel@tonic-gate if (m->b_cont == NULL) {
1580Sstevel@tonic-gate m->b_cont = xdrmblk_alloc((int)(uintptr_t)
1590Sstevel@tonic-gate xdrs->x_private);
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate m = m->b_cont;
1620Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
1630Sstevel@tonic-gate if (m == NULL) {
1640Sstevel@tonic-gate xdrs->x_handy = 0;
1650Sstevel@tonic-gate return (FALSE);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_rptr -
1687387SRobert.Gordon@Sun.COM sizeof (int32_t));
1690Sstevel@tonic-gate ASSERT(m->b_rptr == m->b_wptr);
1700Sstevel@tonic-gate ASSERT(m->b_rptr >= m->b_datap->db_base);
1710Sstevel@tonic-gate ASSERT(m->b_rptr < m->b_datap->db_lim);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate /* LINTED pointer alignment */
1740Sstevel@tonic-gate *(int32_t *)m->b_wptr = htonl(*int32p);
1750Sstevel@tonic-gate m->b_wptr += sizeof (int32_t);
1760Sstevel@tonic-gate ASSERT(m->b_wptr <= m->b_datap->db_lim);
1770Sstevel@tonic-gate return (TRUE);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /*
1810Sstevel@tonic-gate * We pick 16 as a compromise threshold for most architectures.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate #define XDRMBLK_BCOPY_LIMIT 16
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate static bool_t
xdrmblk_getbytes(XDR * xdrs,caddr_t addr,int len)1860Sstevel@tonic-gate xdrmblk_getbytes(XDR *xdrs, caddr_t addr, int len)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate mblk_t *m;
1890Sstevel@tonic-gate int i;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /* LINTED pointer alignment */
1920Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
1930Sstevel@tonic-gate if (m == NULL)
1940Sstevel@tonic-gate return (FALSE);
1950Sstevel@tonic-gate /*
1960Sstevel@tonic-gate * Performance tweak: converted explicit bcopy()
1970Sstevel@tonic-gate * call to simple in-line. This function is called
1980Sstevel@tonic-gate * to process things like readdir reply filenames
1990Sstevel@tonic-gate * which are small strings--typically 12 bytes or less.
2000Sstevel@tonic-gate * Overhead of calling bcopy() is obnoxious for such
2010Sstevel@tonic-gate * small copies.
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) {
2040Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) {
2050Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) {
2060Sstevel@tonic-gate for (i = 0; i < xdrs->x_handy; i++)
2070Sstevel@tonic-gate *addr++ = *m->b_rptr++;
2080Sstevel@tonic-gate } else {
2090Sstevel@tonic-gate bcopy(m->b_rptr, addr, xdrs->x_handy);
2100Sstevel@tonic-gate m->b_rptr += xdrs->x_handy;
2110Sstevel@tonic-gate addr += xdrs->x_handy;
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate len -= xdrs->x_handy;
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate m = m->b_cont;
2160Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
2170Sstevel@tonic-gate if (m == NULL) {
2180Sstevel@tonic-gate xdrs->x_handy = 0;
2190Sstevel@tonic-gate return (FALSE);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) {
2240Sstevel@tonic-gate for (i = 0; i < len; i++)
2250Sstevel@tonic-gate *addr++ = *m->b_rptr++;
2260Sstevel@tonic-gate } else {
2270Sstevel@tonic-gate bcopy(m->b_rptr, addr, len);
2280Sstevel@tonic-gate m->b_rptr += len;
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate return (TRUE);
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate * Sort of like getbytes except that instead of getting bytes we return the
2350Sstevel@tonic-gate * mblk chain which contains the data. If the data ends in the middle of
2360Sstevel@tonic-gate * an mblk, the mblk is dup'd and split, so that the data will end on an
2370Sstevel@tonic-gate * mblk. Note that it is up to the caller to keep track of the data length
2380Sstevel@tonic-gate * and not walk too far down the mblk chain.
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate bool_t
xdrmblk_getmblk(XDR * xdrs,mblk_t ** mm,uint_t * lenp)2420Sstevel@tonic-gate xdrmblk_getmblk(XDR *xdrs, mblk_t **mm, uint_t *lenp)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate mblk_t *m, *nextm;
2450Sstevel@tonic-gate int len;
2460Sstevel@tonic-gate int32_t llen;
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (!xdrmblk_getint32(xdrs, &llen))
2490Sstevel@tonic-gate return (FALSE);
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate *lenp = llen;
2520Sstevel@tonic-gate /* LINTED pointer alignment */
2530Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
2540Sstevel@tonic-gate *mm = m;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate /*
2570Sstevel@tonic-gate * Walk the mblk chain until we get to the end or we've gathered
2580Sstevel@tonic-gate * enough data.
2590Sstevel@tonic-gate */
2600Sstevel@tonic-gate len = 0;
2610Sstevel@tonic-gate llen = roundup(llen, BYTES_PER_XDR_UNIT);
2620Sstevel@tonic-gate while (m != NULL && len + (int)MBLKL(m) <= llen) {
2630Sstevel@tonic-gate len += (int)MBLKL(m);
2640Sstevel@tonic-gate m = m->b_cont;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate if (len < llen) {
2670Sstevel@tonic-gate if (m == NULL) {
2680Sstevel@tonic-gate return (FALSE);
2690Sstevel@tonic-gate } else {
2700Sstevel@tonic-gate int tail_bytes = llen - len;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * Split the mblk with the last chunk of data and
2740Sstevel@tonic-gate * insert it into the chain. The new mblk goes
2750Sstevel@tonic-gate * after the existing one so that it will get freed
2760Sstevel@tonic-gate * properly.
2770Sstevel@tonic-gate */
2780Sstevel@tonic-gate nextm = dupb(m);
2790Sstevel@tonic-gate if (nextm == NULL)
2800Sstevel@tonic-gate return (FALSE);
2810Sstevel@tonic-gate nextm->b_cont = m->b_cont;
2820Sstevel@tonic-gate m->b_cont = nextm;
2830Sstevel@tonic-gate m->b_wptr = m->b_rptr + tail_bytes;
2840Sstevel@tonic-gate nextm->b_rptr += tail_bytes;
2850Sstevel@tonic-gate ASSERT(nextm->b_rptr != nextm->b_wptr);
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate m = nextm; /* for x_base */
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
2910Sstevel@tonic-gate xdrs->x_handy = m != NULL ? MBLKL(m) : 0;
2920Sstevel@tonic-gate return (TRUE);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate static bool_t
xdrmblk_putbytes(XDR * xdrs,caddr_t addr,int len)2960Sstevel@tonic-gate xdrmblk_putbytes(XDR *xdrs, caddr_t addr, int len)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate mblk_t *m;
2990Sstevel@tonic-gate uint_t i;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate /* LINTED pointer alignment */
3020Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
3030Sstevel@tonic-gate if (m == NULL)
3040Sstevel@tonic-gate return (FALSE);
3050Sstevel@tonic-gate /*
3060Sstevel@tonic-gate * Performance tweak: converted explicit bcopy()
3070Sstevel@tonic-gate * call to simple in-line. This function is called
3080Sstevel@tonic-gate * to process things like readdir reply filenames
3090Sstevel@tonic-gate * which are small strings--typically 12 bytes or less.
3100Sstevel@tonic-gate * Overhead of calling bcopy() is obnoxious for such
3110Sstevel@tonic-gate * small copies.
3120Sstevel@tonic-gate */
3130Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) {
3140Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) {
3150Sstevel@tonic-gate if (xdrs->x_handy < XDRMBLK_BCOPY_LIMIT) {
3160Sstevel@tonic-gate for (i = 0; i < (uint_t)xdrs->x_handy; i++)
3170Sstevel@tonic-gate *m->b_wptr++ = *addr++;
3180Sstevel@tonic-gate } else {
3190Sstevel@tonic-gate bcopy(addr, m->b_wptr, xdrs->x_handy);
3200Sstevel@tonic-gate m->b_wptr += xdrs->x_handy;
3210Sstevel@tonic-gate addr += xdrs->x_handy;
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate len -= xdrs->x_handy;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate /*
3270Sstevel@tonic-gate * We don't have enough space, so allocate the
3280Sstevel@tonic-gate * amount we need, or x_private, whichever is larger.
3290Sstevel@tonic-gate * It is better to let the underlying transport divide
3300Sstevel@tonic-gate * large chunks than to try and guess what is best.
3310Sstevel@tonic-gate */
3320Sstevel@tonic-gate if (m->b_cont == NULL)
3330Sstevel@tonic-gate m->b_cont = xdrmblk_alloc(MAX(len,
3340Sstevel@tonic-gate (int)(uintptr_t)xdrs->x_private));
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate m = m->b_cont;
3370Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
3380Sstevel@tonic-gate if (m == NULL) {
3390Sstevel@tonic-gate xdrs->x_handy = 0;
3400Sstevel@tonic-gate return (FALSE);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_rptr);
3430Sstevel@tonic-gate ASSERT(m->b_rptr == m->b_wptr);
3440Sstevel@tonic-gate ASSERT(m->b_rptr >= m->b_datap->db_base);
3450Sstevel@tonic-gate ASSERT(m->b_rptr < m->b_datap->db_lim);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) {
3480Sstevel@tonic-gate for (i = 0; i < len; i++)
3490Sstevel@tonic-gate *m->b_wptr++ = *addr++;
3500Sstevel@tonic-gate } else {
3510Sstevel@tonic-gate bcopy(addr, m->b_wptr, len);
3520Sstevel@tonic-gate m->b_wptr += len;
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate ASSERT(m->b_wptr <= m->b_datap->db_lim);
3550Sstevel@tonic-gate return (TRUE);
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate /*
3590Sstevel@tonic-gate * We avoid a copy by merely adding this mblk to the list. The caller is
3600Sstevel@tonic-gate * responsible for allocating and filling in the mblk. If len is
3610Sstevel@tonic-gate * not a multiple of BYTES_PER_XDR_UNIT, the caller has the option
3620Sstevel@tonic-gate * of making the data a BYTES_PER_XDR_UNIT multiple (b_wptr - b_rptr is
3630Sstevel@tonic-gate * a BYTES_PER_XDR_UNIT multiple), but in this case the caller has to ensure
364*11539SChunli.Zhang@Sun.COM * that the filler bytes are initialized to zero.
3650Sstevel@tonic-gate */
3660Sstevel@tonic-gate bool_t
xdrmblk_putmblk(XDR * xdrs,mblk_t * m,uint_t len)3670Sstevel@tonic-gate xdrmblk_putmblk(XDR *xdrs, mblk_t *m, uint_t len)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate int32_t llen = (int32_t)len;
3700Sstevel@tonic-gate
371*11539SChunli.Zhang@Sun.COM if ((DLEN(m) % BYTES_PER_XDR_UNIT) != 0)
3720Sstevel@tonic-gate return (FALSE);
3730Sstevel@tonic-gate if (!xdrmblk_putint32(xdrs, &llen))
3740Sstevel@tonic-gate return (FALSE);
375*11539SChunli.Zhang@Sun.COM
3760Sstevel@tonic-gate /* LINTED pointer alignment */
3770Sstevel@tonic-gate ((mblk_t *)xdrs->x_base)->b_cont = m;
378*11539SChunli.Zhang@Sun.COM
379*11539SChunli.Zhang@Sun.COM /* base points to the last mblk */
380*11539SChunli.Zhang@Sun.COM while (m->b_cont)
381*11539SChunli.Zhang@Sun.COM m = m->b_cont;
3820Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
3830Sstevel@tonic-gate xdrs->x_handy = 0;
3840Sstevel@tonic-gate return (TRUE);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate static uint_t
xdrmblk_getpos(XDR * xdrs)3880Sstevel@tonic-gate xdrmblk_getpos(XDR *xdrs)
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate uint_t tmp;
3910Sstevel@tonic-gate mblk_t *m;
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate /* LINTED pointer alignment */
3940Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE)
3970Sstevel@tonic-gate tmp = (uint_t)(m->b_rptr - m->b_datap->db_base);
3980Sstevel@tonic-gate else
3990Sstevel@tonic-gate tmp = (uint_t)(m->b_wptr - m->b_datap->db_base);
4000Sstevel@tonic-gate return (tmp);
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate static bool_t
xdrmblk_setpos(XDR * xdrs,uint_t pos)4050Sstevel@tonic-gate xdrmblk_setpos(XDR *xdrs, uint_t pos)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate mblk_t *m;
4080Sstevel@tonic-gate unsigned char *newaddr;
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate /* LINTED pointer alignment */
4110Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
4120Sstevel@tonic-gate if (m == NULL)
4130Sstevel@tonic-gate return (FALSE);
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate /* calculate the new address from the base */
4160Sstevel@tonic-gate newaddr = m->b_datap->db_base + pos;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) {
4190Sstevel@tonic-gate if (newaddr > m->b_wptr)
4200Sstevel@tonic-gate return (FALSE);
4210Sstevel@tonic-gate m->b_rptr = newaddr;
4220Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - newaddr);
4230Sstevel@tonic-gate } else {
4240Sstevel@tonic-gate if (newaddr > m->b_datap->db_lim)
4250Sstevel@tonic-gate return (FALSE);
4260Sstevel@tonic-gate m->b_wptr = newaddr;
4270Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - newaddr);
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate return (TRUE);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate #ifdef DEBUG
4340Sstevel@tonic-gate static int xdrmblk_inline_hits = 0;
4350Sstevel@tonic-gate static int xdrmblk_inline_misses = 0;
4360Sstevel@tonic-gate static int do_xdrmblk_inline = 1;
4370Sstevel@tonic-gate #endif
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate static rpc_inline_t *
xdrmblk_inline(XDR * xdrs,int len)4400Sstevel@tonic-gate xdrmblk_inline(XDR *xdrs, int len)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate rpc_inline_t *buf;
4430Sstevel@tonic-gate mblk_t *m;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate /*
4460Sstevel@tonic-gate * Can't inline XDR_FREE calls, doesn't make sense.
4470Sstevel@tonic-gate */
4480Sstevel@tonic-gate if (xdrs->x_op == XDR_FREE)
4490Sstevel@tonic-gate return (NULL);
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate /*
4520Sstevel@tonic-gate * Can't inline if there isn't enough room, don't have an
4530Sstevel@tonic-gate * mblk pointer, its not 4 byte aligned, or if there is more than
4540Sstevel@tonic-gate * one reference to the data block associated with this mblk. This last
4550Sstevel@tonic-gate * check is used because the caller may want to modified
4560Sstevel@tonic-gate * the data in the inlined portion and someone else is
4570Sstevel@tonic-gate * holding a reference to the data who may not want it
4580Sstevel@tonic-gate * to be modified.
4590Sstevel@tonic-gate */
4600Sstevel@tonic-gate if (xdrs->x_handy < len ||
4610Sstevel@tonic-gate /* LINTED pointer alignment */
4620Sstevel@tonic-gate (m = (mblk_t *)xdrs->x_base) == NULL ||
4630Sstevel@tonic-gate !IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) ||
4640Sstevel@tonic-gate m->b_datap->db_ref != 1) {
4650Sstevel@tonic-gate #ifdef DEBUG
4660Sstevel@tonic-gate xdrmblk_inline_misses++;
4670Sstevel@tonic-gate #endif
4680Sstevel@tonic-gate return (NULL);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate #ifdef DEBUG
4720Sstevel@tonic-gate if (!do_xdrmblk_inline) {
4730Sstevel@tonic-gate xdrmblk_inline_misses++;
4740Sstevel@tonic-gate return (NULL);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate #endif
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate xdrs->x_handy -= len;
4790Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) {
4800Sstevel@tonic-gate /* LINTED pointer alignment */
4810Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_rptr;
4820Sstevel@tonic-gate m->b_rptr += len;
4830Sstevel@tonic-gate } else {
4840Sstevel@tonic-gate /* LINTED pointer alignment */
4850Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_wptr;
4860Sstevel@tonic-gate m->b_wptr += len;
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate #ifdef DEBUG
4890Sstevel@tonic-gate xdrmblk_inline_hits++;
4900Sstevel@tonic-gate #endif
4910Sstevel@tonic-gate return (buf);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate static bool_t
xdrmblk_control(XDR * xdrs,int request,void * info)4950Sstevel@tonic-gate xdrmblk_control(XDR *xdrs, int request, void *info)
4960Sstevel@tonic-gate {
4970Sstevel@tonic-gate mblk_t *m;
4980Sstevel@tonic-gate int32_t *int32p;
4990Sstevel@tonic-gate int len;
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate switch (request) {
5020Sstevel@tonic-gate case XDR_PEEK:
5030Sstevel@tonic-gate /*
5040Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream.
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t))
5070Sstevel@tonic-gate return (FALSE);
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate /* LINTED pointer alignment */
5100Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
5110Sstevel@tonic-gate if (m == NULL)
5120Sstevel@tonic-gate return (FALSE);
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate /*
5150Sstevel@tonic-gate * If the pointer is not aligned, fail the peek
5160Sstevel@tonic-gate */
5170Sstevel@tonic-gate if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)))
5180Sstevel@tonic-gate return (FALSE);
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate int32p = (int32_t *)info;
5210Sstevel@tonic-gate /* LINTED pointer alignment */
5220Sstevel@tonic-gate *int32p = ntohl(*((int32_t *)(m->b_rptr)));
5230Sstevel@tonic-gate return (TRUE);
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate case XDR_SKIPBYTES:
5260Sstevel@tonic-gate /* LINTED pointer alignment */
5270Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base;
5280Sstevel@tonic-gate if (m == NULL)
5290Sstevel@tonic-gate return (FALSE);
5300Sstevel@tonic-gate int32p = (int32_t *)info;
5310Sstevel@tonic-gate len = RNDUP((int)(*int32p));
5322627Smaheshvs if (len < 0)
5337387SRobert.Gordon@Sun.COM return (FALSE);
5340Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) {
5350Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) {
5360Sstevel@tonic-gate m->b_rptr += xdrs->x_handy;
5370Sstevel@tonic-gate len -= xdrs->x_handy;
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate m = m->b_cont;
5400Sstevel@tonic-gate xdrs->x_base = (caddr_t)m;
5410Sstevel@tonic-gate if (m == NULL) {
5420Sstevel@tonic-gate xdrs->x_handy = 0;
5430Sstevel@tonic-gate return (FALSE);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate m->b_rptr += len;
5480Sstevel@tonic-gate return (TRUE);
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate default:
5510Sstevel@tonic-gate return (FALSE);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate #define HDR_SPACE 128
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate static mblk_t *
xdrmblk_alloc(int sz)5580Sstevel@tonic-gate xdrmblk_alloc(int sz)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate mblk_t *mp;
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate if (sz == 0)
5630Sstevel@tonic-gate return (NULL);
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate /*
5660Sstevel@tonic-gate * Pad the front of the message to allow the lower networking
5670Sstevel@tonic-gate * layers space to add headers as needed.
5680Sstevel@tonic-gate */
5690Sstevel@tonic-gate sz += HDR_SPACE;
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate while ((mp = allocb(sz, BPRI_LO)) == NULL) {
5720Sstevel@tonic-gate if (strwaitbuf(sz, BPRI_LO))
5730Sstevel@tonic-gate return (NULL);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate mp->b_wptr += HDR_SPACE;
5770Sstevel@tonic-gate mp->b_rptr = mp->b_wptr;
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate return (mp);
5800Sstevel@tonic-gate }
581