1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*0Sstevel@tonic-gate * under license from the Regents of the University of California. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * xdr_mblk.c, XDR implementation on kernel streams mblks. 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include <sys/param.h> 42*0Sstevel@tonic-gate #include <sys/types.h> 43*0Sstevel@tonic-gate #include <sys/systm.h> 44*0Sstevel@tonic-gate #include <sys/stream.h> 45*0Sstevel@tonic-gate #include <sys/cmn_err.h> 46*0Sstevel@tonic-gate #include <sys/strsubr.h> 47*0Sstevel@tonic-gate #include <sys/strsun.h> 48*0Sstevel@tonic-gate #include <sys/debug.h> 49*0Sstevel@tonic-gate #include <sys/sysmacros.h> 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate #include <rpc/types.h> 52*0Sstevel@tonic-gate #include <rpc/xdr.h> 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate static bool_t xdrmblk_getint32(XDR *, int32_t *); 55*0Sstevel@tonic-gate static bool_t xdrmblk_putint32(XDR *, int32_t *); 56*0Sstevel@tonic-gate static bool_t xdrmblk_getbytes(XDR *, caddr_t, int); 57*0Sstevel@tonic-gate static bool_t xdrmblk_putbytes(XDR *, caddr_t, int); 58*0Sstevel@tonic-gate static uint_t xdrmblk_getpos(XDR *); 59*0Sstevel@tonic-gate static bool_t xdrmblk_setpos(XDR *, uint_t); 60*0Sstevel@tonic-gate static rpc_inline_t *xdrmblk_inline(XDR *, int); 61*0Sstevel@tonic-gate static void xdrmblk_destroy(XDR *); 62*0Sstevel@tonic-gate static bool_t xdrmblk_control(XDR *, int, void *); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate static mblk_t *xdrmblk_alloc(int); 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate /* 67*0Sstevel@tonic-gate * Xdr on mblks operations vector. 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate struct xdr_ops xdrmblk_ops = { 70*0Sstevel@tonic-gate xdrmblk_getbytes, 71*0Sstevel@tonic-gate xdrmblk_putbytes, 72*0Sstevel@tonic-gate xdrmblk_getpos, 73*0Sstevel@tonic-gate xdrmblk_setpos, 74*0Sstevel@tonic-gate xdrmblk_inline, 75*0Sstevel@tonic-gate xdrmblk_destroy, 76*0Sstevel@tonic-gate xdrmblk_control, 77*0Sstevel@tonic-gate xdrmblk_getint32, 78*0Sstevel@tonic-gate xdrmblk_putint32 79*0Sstevel@tonic-gate }; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate /* 82*0Sstevel@tonic-gate * Initialize xdr stream. 83*0Sstevel@tonic-gate */ 84*0Sstevel@tonic-gate void 85*0Sstevel@tonic-gate xdrmblk_init(XDR *xdrs, mblk_t *m, enum xdr_op op, int sz) 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate xdrs->x_op = op; 88*0Sstevel@tonic-gate xdrs->x_ops = &xdrmblk_ops; 89*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 90*0Sstevel@tonic-gate xdrs->x_public = NULL; 91*0Sstevel@tonic-gate xdrs->x_private = (caddr_t)(uintptr_t)sz; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate if (op == XDR_DECODE) 94*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 95*0Sstevel@tonic-gate else 96*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_datap->db_base); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* ARGSUSED */ 100*0Sstevel@tonic-gate static void 101*0Sstevel@tonic-gate xdrmblk_destroy(XDR *xdrs) 102*0Sstevel@tonic-gate { 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate static bool_t 106*0Sstevel@tonic-gate xdrmblk_getint32(XDR *xdrs, int32_t *int32p) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate mblk_t *m; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* LINTED pointer alignment */ 111*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 112*0Sstevel@tonic-gate if (m == NULL) 113*0Sstevel@tonic-gate return (FALSE); 114*0Sstevel@tonic-gate /* 115*0Sstevel@tonic-gate * If the pointer is not aligned or there is not 116*0Sstevel@tonic-gate * enough bytes, pullupmsg to get enough bytes and 117*0Sstevel@tonic-gate * align the mblk. 118*0Sstevel@tonic-gate */ 119*0Sstevel@tonic-gate if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) || 120*0Sstevel@tonic-gate xdrs->x_handy < sizeof (int32_t)) { 121*0Sstevel@tonic-gate while (!pullupmsg(m, sizeof (int32_t))) { 122*0Sstevel@tonic-gate /* 123*0Sstevel@tonic-gate * Could have failed due to not 124*0Sstevel@tonic-gate * enough data or an allocb failure. 125*0Sstevel@tonic-gate */ 126*0Sstevel@tonic-gate if (xmsgsize(m) < sizeof (int32_t)) 127*0Sstevel@tonic-gate return (FALSE); 128*0Sstevel@tonic-gate delay(hz); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* LINTED pointer alignment */ 134*0Sstevel@tonic-gate *int32p = ntohl(*((int32_t *)(m->b_rptr))); 135*0Sstevel@tonic-gate m->b_rptr += sizeof (int32_t); 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* 138*0Sstevel@tonic-gate * Instead of leaving handy as 0 causing more pullupmsg's 139*0Sstevel@tonic-gate * simply move to the next mblk. 140*0Sstevel@tonic-gate */ 141*0Sstevel@tonic-gate if ((xdrs->x_handy -= sizeof (int32_t)) == 0) { 142*0Sstevel@tonic-gate m = m->b_cont; 143*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 144*0Sstevel@tonic-gate if (m != NULL) 145*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate return (TRUE); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate static bool_t 151*0Sstevel@tonic-gate xdrmblk_putint32(XDR *xdrs, int32_t *int32p) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate mblk_t *m; 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* LINTED pointer alignment */ 156*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 157*0Sstevel@tonic-gate if (m == NULL) 158*0Sstevel@tonic-gate return (FALSE); 159*0Sstevel@tonic-gate if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0) { 160*0Sstevel@tonic-gate if (m->b_cont == NULL) { 161*0Sstevel@tonic-gate m->b_cont = xdrmblk_alloc((int)(uintptr_t) 162*0Sstevel@tonic-gate xdrs->x_private); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate m = m->b_cont; 165*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 166*0Sstevel@tonic-gate if (m == NULL) { 167*0Sstevel@tonic-gate xdrs->x_handy = 0; 168*0Sstevel@tonic-gate return (FALSE); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_rptr - 171*0Sstevel@tonic-gate sizeof (int32_t)); 172*0Sstevel@tonic-gate ASSERT(m->b_rptr == m->b_wptr); 173*0Sstevel@tonic-gate ASSERT(m->b_rptr >= m->b_datap->db_base); 174*0Sstevel@tonic-gate ASSERT(m->b_rptr < m->b_datap->db_lim); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate /* LINTED pointer alignment */ 177*0Sstevel@tonic-gate *(int32_t *)m->b_wptr = htonl(*int32p); 178*0Sstevel@tonic-gate m->b_wptr += sizeof (int32_t); 179*0Sstevel@tonic-gate ASSERT(m->b_wptr <= m->b_datap->db_lim); 180*0Sstevel@tonic-gate return (TRUE); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * We pick 16 as a compromise threshold for most architectures. 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate #define XDRMBLK_BCOPY_LIMIT 16 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate static bool_t 189*0Sstevel@tonic-gate xdrmblk_getbytes(XDR *xdrs, caddr_t addr, int len) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate mblk_t *m; 192*0Sstevel@tonic-gate int i; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate /* LINTED pointer alignment */ 195*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 196*0Sstevel@tonic-gate if (m == NULL) 197*0Sstevel@tonic-gate return (FALSE); 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Performance tweak: converted explicit bcopy() 200*0Sstevel@tonic-gate * call to simple in-line. This function is called 201*0Sstevel@tonic-gate * to process things like readdir reply filenames 202*0Sstevel@tonic-gate * which are small strings--typically 12 bytes or less. 203*0Sstevel@tonic-gate * Overhead of calling bcopy() is obnoxious for such 204*0Sstevel@tonic-gate * small copies. 205*0Sstevel@tonic-gate */ 206*0Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) { 207*0Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) { 208*0Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) { 209*0Sstevel@tonic-gate for (i = 0; i < xdrs->x_handy; i++) 210*0Sstevel@tonic-gate *addr++ = *m->b_rptr++; 211*0Sstevel@tonic-gate } else { 212*0Sstevel@tonic-gate bcopy(m->b_rptr, addr, xdrs->x_handy); 213*0Sstevel@tonic-gate m->b_rptr += xdrs->x_handy; 214*0Sstevel@tonic-gate addr += xdrs->x_handy; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate len -= xdrs->x_handy; 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate m = m->b_cont; 219*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 220*0Sstevel@tonic-gate if (m == NULL) { 221*0Sstevel@tonic-gate xdrs->x_handy = 0; 222*0Sstevel@tonic-gate return (FALSE); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) { 227*0Sstevel@tonic-gate for (i = 0; i < len; i++) 228*0Sstevel@tonic-gate *addr++ = *m->b_rptr++; 229*0Sstevel@tonic-gate } else { 230*0Sstevel@tonic-gate bcopy(m->b_rptr, addr, len); 231*0Sstevel@tonic-gate m->b_rptr += len; 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate return (TRUE); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * Sort of like getbytes except that instead of getting bytes we return the 238*0Sstevel@tonic-gate * mblk chain which contains the data. If the data ends in the middle of 239*0Sstevel@tonic-gate * an mblk, the mblk is dup'd and split, so that the data will end on an 240*0Sstevel@tonic-gate * mblk. Note that it is up to the caller to keep track of the data length 241*0Sstevel@tonic-gate * and not walk too far down the mblk chain. 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate bool_t 245*0Sstevel@tonic-gate xdrmblk_getmblk(XDR *xdrs, mblk_t **mm, uint_t *lenp) 246*0Sstevel@tonic-gate { 247*0Sstevel@tonic-gate mblk_t *m, *nextm; 248*0Sstevel@tonic-gate int len; 249*0Sstevel@tonic-gate int32_t llen; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (!xdrmblk_getint32(xdrs, &llen)) 252*0Sstevel@tonic-gate return (FALSE); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate *lenp = llen; 255*0Sstevel@tonic-gate /* LINTED pointer alignment */ 256*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 257*0Sstevel@tonic-gate *mm = m; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * Walk the mblk chain until we get to the end or we've gathered 261*0Sstevel@tonic-gate * enough data. 262*0Sstevel@tonic-gate */ 263*0Sstevel@tonic-gate len = 0; 264*0Sstevel@tonic-gate llen = roundup(llen, BYTES_PER_XDR_UNIT); 265*0Sstevel@tonic-gate while (m != NULL && len + (int)MBLKL(m) <= llen) { 266*0Sstevel@tonic-gate len += (int)MBLKL(m); 267*0Sstevel@tonic-gate m = m->b_cont; 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate if (len < llen) { 270*0Sstevel@tonic-gate if (m == NULL) { 271*0Sstevel@tonic-gate /* not enough data in XDR stream */ 272*0Sstevel@tonic-gate printf("xdrmblk_getmblk failed\n"); 273*0Sstevel@tonic-gate return (FALSE); 274*0Sstevel@tonic-gate } else { 275*0Sstevel@tonic-gate int tail_bytes = llen - len; 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * Split the mblk with the last chunk of data and 279*0Sstevel@tonic-gate * insert it into the chain. The new mblk goes 280*0Sstevel@tonic-gate * after the existing one so that it will get freed 281*0Sstevel@tonic-gate * properly. 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate nextm = dupb(m); 284*0Sstevel@tonic-gate if (nextm == NULL) 285*0Sstevel@tonic-gate return (FALSE); 286*0Sstevel@tonic-gate nextm->b_cont = m->b_cont; 287*0Sstevel@tonic-gate m->b_cont = nextm; 288*0Sstevel@tonic-gate m->b_wptr = m->b_rptr + tail_bytes; 289*0Sstevel@tonic-gate nextm->b_rptr += tail_bytes; 290*0Sstevel@tonic-gate ASSERT(nextm->b_rptr != nextm->b_wptr); 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate m = nextm; /* for x_base */ 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 296*0Sstevel@tonic-gate xdrs->x_handy = m != NULL ? MBLKL(m) : 0; 297*0Sstevel@tonic-gate return (TRUE); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate static bool_t 301*0Sstevel@tonic-gate xdrmblk_putbytes(XDR *xdrs, caddr_t addr, int len) 302*0Sstevel@tonic-gate { 303*0Sstevel@tonic-gate mblk_t *m; 304*0Sstevel@tonic-gate uint_t i; 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /* LINTED pointer alignment */ 307*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 308*0Sstevel@tonic-gate if (m == NULL) 309*0Sstevel@tonic-gate return (FALSE); 310*0Sstevel@tonic-gate /* 311*0Sstevel@tonic-gate * Performance tweak: converted explicit bcopy() 312*0Sstevel@tonic-gate * call to simple in-line. This function is called 313*0Sstevel@tonic-gate * to process things like readdir reply filenames 314*0Sstevel@tonic-gate * which are small strings--typically 12 bytes or less. 315*0Sstevel@tonic-gate * Overhead of calling bcopy() is obnoxious for such 316*0Sstevel@tonic-gate * small copies. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) { 319*0Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) { 320*0Sstevel@tonic-gate if (xdrs->x_handy < XDRMBLK_BCOPY_LIMIT) { 321*0Sstevel@tonic-gate for (i = 0; i < (uint_t)xdrs->x_handy; i++) 322*0Sstevel@tonic-gate *m->b_wptr++ = *addr++; 323*0Sstevel@tonic-gate } else { 324*0Sstevel@tonic-gate bcopy(addr, m->b_wptr, xdrs->x_handy); 325*0Sstevel@tonic-gate m->b_wptr += xdrs->x_handy; 326*0Sstevel@tonic-gate addr += xdrs->x_handy; 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate len -= xdrs->x_handy; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate /* 332*0Sstevel@tonic-gate * We don't have enough space, so allocate the 333*0Sstevel@tonic-gate * amount we need, or x_private, whichever is larger. 334*0Sstevel@tonic-gate * It is better to let the underlying transport divide 335*0Sstevel@tonic-gate * large chunks than to try and guess what is best. 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate if (m->b_cont == NULL) 338*0Sstevel@tonic-gate m->b_cont = xdrmblk_alloc(MAX(len, 339*0Sstevel@tonic-gate (int)(uintptr_t)xdrs->x_private)); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate m = m->b_cont; 342*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 343*0Sstevel@tonic-gate if (m == NULL) { 344*0Sstevel@tonic-gate xdrs->x_handy = 0; 345*0Sstevel@tonic-gate return (FALSE); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - m->b_rptr); 348*0Sstevel@tonic-gate ASSERT(m->b_rptr == m->b_wptr); 349*0Sstevel@tonic-gate ASSERT(m->b_rptr >= m->b_datap->db_base); 350*0Sstevel@tonic-gate ASSERT(m->b_rptr < m->b_datap->db_lim); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate if (len < XDRMBLK_BCOPY_LIMIT) { 353*0Sstevel@tonic-gate for (i = 0; i < len; i++) 354*0Sstevel@tonic-gate *m->b_wptr++ = *addr++; 355*0Sstevel@tonic-gate } else { 356*0Sstevel@tonic-gate bcopy(addr, m->b_wptr, len); 357*0Sstevel@tonic-gate m->b_wptr += len; 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate ASSERT(m->b_wptr <= m->b_datap->db_lim); 360*0Sstevel@tonic-gate return (TRUE); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* 364*0Sstevel@tonic-gate * We avoid a copy by merely adding this mblk to the list. The caller is 365*0Sstevel@tonic-gate * responsible for allocating and filling in the mblk. If len is 366*0Sstevel@tonic-gate * not a multiple of BYTES_PER_XDR_UNIT, the caller has the option 367*0Sstevel@tonic-gate * of making the data a BYTES_PER_XDR_UNIT multiple (b_wptr - b_rptr is 368*0Sstevel@tonic-gate * a BYTES_PER_XDR_UNIT multiple), but in this case the caller has to ensure 369*0Sstevel@tonic-gate * that the filler bytes are initialized to zero. Note: Doesn't to work for 370*0Sstevel@tonic-gate * chained mblks. 371*0Sstevel@tonic-gate */ 372*0Sstevel@tonic-gate bool_t 373*0Sstevel@tonic-gate xdrmblk_putmblk(XDR *xdrs, mblk_t *m, uint_t len) 374*0Sstevel@tonic-gate { 375*0Sstevel@tonic-gate int32_t llen = (int32_t)len; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0) 378*0Sstevel@tonic-gate return (FALSE); 379*0Sstevel@tonic-gate if (!xdrmblk_putint32(xdrs, &llen)) 380*0Sstevel@tonic-gate return (FALSE); 381*0Sstevel@tonic-gate /* LINTED pointer alignment */ 382*0Sstevel@tonic-gate ((mblk_t *)xdrs->x_base)->b_cont = m; 383*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 384*0Sstevel@tonic-gate xdrs->x_handy = 0; 385*0Sstevel@tonic-gate return (TRUE); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate static uint_t 389*0Sstevel@tonic-gate xdrmblk_getpos(XDR *xdrs) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate uint_t tmp; 392*0Sstevel@tonic-gate mblk_t *m; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* LINTED pointer alignment */ 395*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) 398*0Sstevel@tonic-gate tmp = (uint_t)(m->b_rptr - m->b_datap->db_base); 399*0Sstevel@tonic-gate else 400*0Sstevel@tonic-gate tmp = (uint_t)(m->b_wptr - m->b_datap->db_base); 401*0Sstevel@tonic-gate return (tmp); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate static bool_t 406*0Sstevel@tonic-gate xdrmblk_setpos(XDR *xdrs, uint_t pos) 407*0Sstevel@tonic-gate { 408*0Sstevel@tonic-gate mblk_t *m; 409*0Sstevel@tonic-gate unsigned char *newaddr; 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate /* LINTED pointer alignment */ 412*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 413*0Sstevel@tonic-gate if (m == NULL) 414*0Sstevel@tonic-gate return (FALSE); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* calculate the new address from the base */ 417*0Sstevel@tonic-gate newaddr = m->b_datap->db_base + pos; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 420*0Sstevel@tonic-gate if (newaddr > m->b_wptr) 421*0Sstevel@tonic-gate return (FALSE); 422*0Sstevel@tonic-gate m->b_rptr = newaddr; 423*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - newaddr); 424*0Sstevel@tonic-gate } else { 425*0Sstevel@tonic-gate if (newaddr > m->b_datap->db_lim) 426*0Sstevel@tonic-gate return (FALSE); 427*0Sstevel@tonic-gate m->b_wptr = newaddr; 428*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_datap->db_lim - newaddr); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate return (TRUE); 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate #ifdef DEBUG 435*0Sstevel@tonic-gate static int xdrmblk_inline_hits = 0; 436*0Sstevel@tonic-gate static int xdrmblk_inline_misses = 0; 437*0Sstevel@tonic-gate static int do_xdrmblk_inline = 1; 438*0Sstevel@tonic-gate #endif 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate static rpc_inline_t * 441*0Sstevel@tonic-gate xdrmblk_inline(XDR *xdrs, int len) 442*0Sstevel@tonic-gate { 443*0Sstevel@tonic-gate rpc_inline_t *buf; 444*0Sstevel@tonic-gate mblk_t *m; 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate /* 447*0Sstevel@tonic-gate * Can't inline XDR_FREE calls, doesn't make sense. 448*0Sstevel@tonic-gate */ 449*0Sstevel@tonic-gate if (xdrs->x_op == XDR_FREE) 450*0Sstevel@tonic-gate return (NULL); 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* 453*0Sstevel@tonic-gate * Can't inline if there isn't enough room, don't have an 454*0Sstevel@tonic-gate * mblk pointer, its not 4 byte aligned, or if there is more than 455*0Sstevel@tonic-gate * one reference to the data block associated with this mblk. This last 456*0Sstevel@tonic-gate * check is used because the caller may want to modified 457*0Sstevel@tonic-gate * the data in the inlined portion and someone else is 458*0Sstevel@tonic-gate * holding a reference to the data who may not want it 459*0Sstevel@tonic-gate * to be modified. 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate if (xdrs->x_handy < len || 462*0Sstevel@tonic-gate /* LINTED pointer alignment */ 463*0Sstevel@tonic-gate (m = (mblk_t *)xdrs->x_base) == NULL || 464*0Sstevel@tonic-gate !IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) || 465*0Sstevel@tonic-gate m->b_datap->db_ref != 1) { 466*0Sstevel@tonic-gate #ifdef DEBUG 467*0Sstevel@tonic-gate xdrmblk_inline_misses++; 468*0Sstevel@tonic-gate #endif 469*0Sstevel@tonic-gate return (NULL); 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate #ifdef DEBUG 473*0Sstevel@tonic-gate if (!do_xdrmblk_inline) { 474*0Sstevel@tonic-gate xdrmblk_inline_misses++; 475*0Sstevel@tonic-gate return (NULL); 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate #endif 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate xdrs->x_handy -= len; 480*0Sstevel@tonic-gate if (xdrs->x_op == XDR_DECODE) { 481*0Sstevel@tonic-gate /* LINTED pointer alignment */ 482*0Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_rptr; 483*0Sstevel@tonic-gate m->b_rptr += len; 484*0Sstevel@tonic-gate } else { 485*0Sstevel@tonic-gate /* LINTED pointer alignment */ 486*0Sstevel@tonic-gate buf = (rpc_inline_t *)m->b_wptr; 487*0Sstevel@tonic-gate m->b_wptr += len; 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate #ifdef DEBUG 490*0Sstevel@tonic-gate xdrmblk_inline_hits++; 491*0Sstevel@tonic-gate #endif 492*0Sstevel@tonic-gate return (buf); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate static bool_t 496*0Sstevel@tonic-gate xdrmblk_control(XDR *xdrs, int request, void *info) 497*0Sstevel@tonic-gate { 498*0Sstevel@tonic-gate mblk_t *m; 499*0Sstevel@tonic-gate int32_t *int32p; 500*0Sstevel@tonic-gate int len; 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate switch (request) { 503*0Sstevel@tonic-gate case XDR_PEEK: 504*0Sstevel@tonic-gate /* 505*0Sstevel@tonic-gate * Return the next 4 byte unit in the XDR stream. 506*0Sstevel@tonic-gate */ 507*0Sstevel@tonic-gate if (xdrs->x_handy < sizeof (int32_t)) 508*0Sstevel@tonic-gate return (FALSE); 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate /* LINTED pointer alignment */ 511*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 512*0Sstevel@tonic-gate if (m == NULL) 513*0Sstevel@tonic-gate return (FALSE); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * If the pointer is not aligned, fail the peek 517*0Sstevel@tonic-gate */ 518*0Sstevel@tonic-gate if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t))) 519*0Sstevel@tonic-gate return (FALSE); 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate int32p = (int32_t *)info; 522*0Sstevel@tonic-gate /* LINTED pointer alignment */ 523*0Sstevel@tonic-gate *int32p = ntohl(*((int32_t *)(m->b_rptr))); 524*0Sstevel@tonic-gate return (TRUE); 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate case XDR_SKIPBYTES: 527*0Sstevel@tonic-gate /* LINTED pointer alignment */ 528*0Sstevel@tonic-gate m = (mblk_t *)xdrs->x_base; 529*0Sstevel@tonic-gate if (m == NULL) 530*0Sstevel@tonic-gate return (FALSE); 531*0Sstevel@tonic-gate int32p = (int32_t *)info; 532*0Sstevel@tonic-gate len = RNDUP((int)(*int32p)); 533*0Sstevel@tonic-gate while ((xdrs->x_handy -= len) < 0) { 534*0Sstevel@tonic-gate if ((xdrs->x_handy += len) > 0) { 535*0Sstevel@tonic-gate m->b_rptr += xdrs->x_handy; 536*0Sstevel@tonic-gate len -= xdrs->x_handy; 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate m = m->b_cont; 539*0Sstevel@tonic-gate xdrs->x_base = (caddr_t)m; 540*0Sstevel@tonic-gate if (m == NULL) { 541*0Sstevel@tonic-gate xdrs->x_handy = 0; 542*0Sstevel@tonic-gate return (FALSE); 543*0Sstevel@tonic-gate } 544*0Sstevel@tonic-gate xdrs->x_handy = (int)(m->b_wptr - m->b_rptr); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate m->b_rptr += len; 547*0Sstevel@tonic-gate return (TRUE); 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate default: 550*0Sstevel@tonic-gate return (FALSE); 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate #define HDR_SPACE 128 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate static mblk_t * 557*0Sstevel@tonic-gate xdrmblk_alloc(int sz) 558*0Sstevel@tonic-gate { 559*0Sstevel@tonic-gate mblk_t *mp; 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if (sz == 0) 562*0Sstevel@tonic-gate return (NULL); 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate /* 565*0Sstevel@tonic-gate * Pad the front of the message to allow the lower networking 566*0Sstevel@tonic-gate * layers space to add headers as needed. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate sz += HDR_SPACE; 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate while ((mp = allocb(sz, BPRI_LO)) == NULL) { 571*0Sstevel@tonic-gate if (strwaitbuf(sz, BPRI_LO)) 572*0Sstevel@tonic-gate return (NULL); 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate mp->b_wptr += HDR_SPACE; 576*0Sstevel@tonic-gate mp->b_rptr = mp->b_wptr; 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate return (mp); 579*0Sstevel@tonic-gate } 580