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*7387SRobert.Gordon@Sun.COM * Copyright 2008 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 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 980Sstevel@tonic-gate xdrmblk_destroy(XDR *xdrs) 990Sstevel@tonic-gate { 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate static bool_t 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)) || 117*7387SRobert.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 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 - 168*7387SRobert.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 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 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 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 3640Sstevel@tonic-gate * that the filler bytes are initialized to zero. Note: Doesn't to work for 3650Sstevel@tonic-gate * chained mblks. 3660Sstevel@tonic-gate */ 3670Sstevel@tonic-gate bool_t 3680Sstevel@tonic-gate xdrmblk_putmblk(XDR *xdrs, mblk_t *m, uint_t len) 3690Sstevel@tonic-gate { 3700Sstevel@tonic-gate int32_t llen = (int32_t)len; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0) 3730Sstevel@tonic-gate return (FALSE); 3740Sstevel@tonic-gate if (!xdrmblk_putint32(xdrs, &llen)) 3750Sstevel@tonic-gate return (FALSE); 3760Sstevel@tonic-gate /* LINTED pointer alignment */ 3770Sstevel@tonic-gate ((mblk_t *)xdrs->x_base)->b_cont = m; 3780Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 3790Sstevel@tonic-gate xdrs->x_handy = 0; 3800Sstevel@tonic-gate return (TRUE); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate static uint_t 3840Sstevel@tonic-gate xdrmblk_getpos(XDR *xdrs) 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate uint_t tmp; 3870Sstevel@tonic-gate mblk_t *m; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* LINTED pointer alignment */ 3900Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) 3930Sstevel@tonic-gate tmp = (uint_t)(m->b_rptr - m->b_datap->db_base); 3940Sstevel@tonic-gate else 3950Sstevel@tonic-gate tmp = (uint_t)(m->b_wptr - m->b_datap->db_base); 3960Sstevel@tonic-gate return (tmp); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate static bool_t 4010Sstevel@tonic-gate xdrmblk_setpos(XDR *xdrs, uint_t pos) 4020Sstevel@tonic-gate { 4030Sstevel@tonic-gate mblk_t *m; 4040Sstevel@tonic-gate unsigned char *newaddr; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /* LINTED pointer alignment */ 4070Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 4080Sstevel@tonic-gate if (m == NULL) 4090Sstevel@tonic-gate return (FALSE); 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate /* calculate the new address from the base */ 4120Sstevel@tonic-gate newaddr = m->b_datap->db_base + pos; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 4150Sstevel@tonic-gate if (newaddr > m->b_wptr) 4160Sstevel@tonic-gate return (FALSE); 4170Sstevel@tonic-gate m->b_rptr = newaddr; 4180Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - newaddr); 4190Sstevel@tonic-gate } else { 4200Sstevel@tonic-gate if (newaddr > m->b_datap->db_lim) 4210Sstevel@tonic-gate return (FALSE); 4220Sstevel@tonic-gate m->b_wptr = newaddr; 4230Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - newaddr); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate return (TRUE); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate #ifdef DEBUG 4300Sstevel@tonic-gate static int xdrmblk_inline_hits = 0; 4310Sstevel@tonic-gate static int xdrmblk_inline_misses = 0; 4320Sstevel@tonic-gate static int do_xdrmblk_inline = 1; 4330Sstevel@tonic-gate #endif 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate static rpc_inline_t * 4360Sstevel@tonic-gate xdrmblk_inline(XDR *xdrs, int len) 4370Sstevel@tonic-gate { 4380Sstevel@tonic-gate rpc_inline_t *buf; 4390Sstevel@tonic-gate mblk_t *m; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate /* 4420Sstevel@tonic-gate * Can't inline XDR_FREE calls, doesn't make sense. 4430Sstevel@tonic-gate */ 4440Sstevel@tonic-gate if (xdrs->x_op == XDR_FREE) 4450Sstevel@tonic-gate return (NULL); 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate /* 4480Sstevel@tonic-gate * Can't inline if there isn't enough room, don't have an 4490Sstevel@tonic-gate * mblk pointer, its not 4 byte aligned, or if there is more than 4500Sstevel@tonic-gate * one reference to the data block associated with this mblk. This last 4510Sstevel@tonic-gate * check is used because the caller may want to modified 4520Sstevel@tonic-gate * the data in the inlined portion and someone else is 4530Sstevel@tonic-gate * holding a reference to the data who may not want it 4540Sstevel@tonic-gate * to be modified. 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate if (xdrs->x_handy < len || 4570Sstevel@tonic-gate /* LINTED pointer alignment */ 4580Sstevel@tonic-gate (m = (mblk_t *)xdrs->x_base) == NULL || 4590Sstevel@tonic-gate !IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) || 4600Sstevel@tonic-gate m->b_datap->db_ref != 1) { 4610Sstevel@tonic-gate #ifdef DEBUG 4620Sstevel@tonic-gate xdrmblk_inline_misses++; 4630Sstevel@tonic-gate #endif 4640Sstevel@tonic-gate return (NULL); 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate #ifdef DEBUG 4680Sstevel@tonic-gate if (!do_xdrmblk_inline) { 4690Sstevel@tonic-gate xdrmblk_inline_misses++; 4700Sstevel@tonic-gate return (NULL); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate #endif 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate xdrs->x_handy -= len; 4750Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 4760Sstevel@tonic-gate /* LINTED pointer alignment */ 4770Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_rptr; 4780Sstevel@tonic-gate m->b_rptr += len; 4790Sstevel@tonic-gate } else { 4800Sstevel@tonic-gate /* LINTED pointer alignment */ 4810Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_wptr; 4820Sstevel@tonic-gate m->b_wptr += len; 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate #ifdef DEBUG 4850Sstevel@tonic-gate xdrmblk_inline_hits++; 4860Sstevel@tonic-gate #endif 4870Sstevel@tonic-gate return (buf); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate static bool_t 4910Sstevel@tonic-gate xdrmblk_control(XDR *xdrs, int request, void *info) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate mblk_t *m; 4940Sstevel@tonic-gate int32_t *int32p; 4950Sstevel@tonic-gate int len; 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate switch (request) { 4980Sstevel@tonic-gate case XDR_PEEK: 4990Sstevel@tonic-gate /* 5000Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream. 5010Sstevel@tonic-gate */ 5020Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t)) 5030Sstevel@tonic-gate return (FALSE); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate /* LINTED pointer alignment */ 5060Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 5070Sstevel@tonic-gate if (m == NULL) 5080Sstevel@tonic-gate return (FALSE); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate /* 5110Sstevel@tonic-gate * If the pointer is not aligned, fail the peek 5120Sstevel@tonic-gate */ 5130Sstevel@tonic-gate if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t))) 5140Sstevel@tonic-gate return (FALSE); 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate int32p = (int32_t *)info; 5170Sstevel@tonic-gate /* LINTED pointer alignment */ 5180Sstevel@tonic-gate *int32p = ntohl(*((int32_t *)(m->b_rptr))); 5190Sstevel@tonic-gate return (TRUE); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate case XDR_SKIPBYTES: 5220Sstevel@tonic-gate /* LINTED pointer alignment */ 5230Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 5240Sstevel@tonic-gate if (m == NULL) 5250Sstevel@tonic-gate return (FALSE); 5260Sstevel@tonic-gate int32p = (int32_t *)info; 5270Sstevel@tonic-gate len = RNDUP((int)(*int32p)); 5282627Smaheshvs if (len < 0) 529*7387SRobert.Gordon@Sun.COM return (FALSE); 5300Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) { 5310Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) { 5320Sstevel@tonic-gate m->b_rptr += xdrs->x_handy; 5330Sstevel@tonic-gate len -= xdrs->x_handy; 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate m = m->b_cont; 5360Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 5370Sstevel@tonic-gate if (m == NULL) { 5380Sstevel@tonic-gate xdrs->x_handy = 0; 5390Sstevel@tonic-gate return (FALSE); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate m->b_rptr += len; 5440Sstevel@tonic-gate return (TRUE); 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate default: 5470Sstevel@tonic-gate return (FALSE); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate #define HDR_SPACE 128 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate static mblk_t * 5540Sstevel@tonic-gate xdrmblk_alloc(int sz) 5550Sstevel@tonic-gate { 5560Sstevel@tonic-gate mblk_t *mp; 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate if (sz == 0) 5590Sstevel@tonic-gate return (NULL); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate /* 5620Sstevel@tonic-gate * Pad the front of the message to allow the lower networking 5630Sstevel@tonic-gate * layers space to add headers as needed. 5640Sstevel@tonic-gate */ 5650Sstevel@tonic-gate sz += HDR_SPACE; 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate while ((mp = allocb(sz, BPRI_LO)) == NULL) { 5680Sstevel@tonic-gate if (strwaitbuf(sz, BPRI_LO)) 5690Sstevel@tonic-gate return (NULL); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate mp->b_wptr += HDR_SPACE; 5730Sstevel@tonic-gate mp->b_rptr = mp->b_wptr; 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate return (mp); 5760Sstevel@tonic-gate } 577