1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26 /* All Rights Reserved */ 27 /* 28 * Portions of this source code were derived from Berkeley 29 * 4.3 BSD under license from the Regents of the University of 30 * California. 31 */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 /* 36 * xdr_mem.h, XDR implementation using memory buffers. 37 * 38 * If you have some data to be interpreted as external data representation 39 * or to be converted to external data representation in a memory buffer, 40 * then this is the package for you. 41 * 42 */ 43 44 #ifdef KERNEL 45 #include <sys/param.h> 46 #endif 47 48 #include "mt.h" 49 #include "rpc_mt.h" 50 #include <sys/types.h> 51 #include <rpc/trace.h> 52 #include <rpc/types.h> 53 #include <rpc/xdr.h> 54 #include <memory.h> 55 #include <inttypes.h> 56 57 static struct xdr_ops *xdrmem_ops(void); 58 59 /* 60 * Meaning of the private areas of the xdr struct for xdr_mem 61 * x_base : Base from where the xdr stream starts 62 * x_private : The current position of the stream. 63 * x_handy : The size of the stream buffer. 64 */ 65 66 /* 67 * The procedure xdrmem_create initializes a stream descriptor for a 68 * memory buffer. 69 */ 70 void 71 xdrmem_create(XDR *xdrs, caddr_t addr, uint_t size, enum xdr_op op) 72 { 73 caddr_t eaddr = addr; 74 75 trace2(TR_xdrmem_create, 0, size); 76 xdrs->x_op = op; 77 xdrs->x_ops = xdrmem_ops(); 78 xdrs->x_private = xdrs->x_base = 0; 79 /* 80 * We check here that the size is with in the range of the 81 * address space. If not we set x_handy to zero. This will cause 82 * all xdrmem entry points to fail. 83 */ 84 eaddr = addr + size; 85 86 if (eaddr < addr) 87 xdrs->x_handy = 0; 88 else { 89 xdrs->x_handy = size; 90 xdrs->x_private = xdrs->x_base = addr; 91 } 92 trace2(TR_xdrmem_create, 1, size); 93 } 94 95 static void 96 xdrmem_destroy(XDR *xdrs) 97 { 98 trace1(TR_xdrmem_destroy, 0); 99 trace1(TR_xdrmem_destroy, 1); 100 } 101 102 static bool_t 103 xdrmem_getlong(XDR *xdrs, long *lp) 104 { 105 trace1(TR_xdrmem_getlong, 0); 106 if (sizeof (int32_t) > (uint32_t)xdrs->x_handy) { 107 xdrs->x_private += (uint_t)xdrs->x_handy; 108 xdrs->x_handy = 0; 109 trace1(TR_xdrmem_getlong, 1); 110 return (FALSE); 111 } 112 xdrs->x_handy -= sizeof (int32_t); 113 *lp = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private)))); 114 xdrs->x_private += sizeof (int32_t); 115 trace1(TR_xdrmem_getlong, 1); 116 return (TRUE); 117 } 118 119 static bool_t 120 xdrmem_putlong(XDR *xdrs, long *lp) 121 { 122 trace1(TR_xdrmem_putlong, 0); 123 #if defined(_LP64) 124 if ((*lp > INT32_MAX) || (*lp < INT32_MIN)) { 125 return (FALSE); 126 } 127 #endif 128 129 if ((sizeof (int32_t) > (uint32_t)xdrs->x_handy)) { 130 xdrs->x_private += (uint_t)xdrs->x_handy; 131 xdrs->x_handy = 0; 132 trace1(TR_xdrmem_putlong, 1); 133 return (FALSE); 134 } 135 xdrs->x_handy -= sizeof (int32_t); 136 *(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*lp)); 137 xdrs->x_private += sizeof (int32_t); 138 trace1(TR_xdrmem_putlong, 1); 139 return (TRUE); 140 } 141 142 #if defined(_LP64) 143 144 static bool_t 145 xdrmem_getint32(XDR *xdrs, int32_t *ip) 146 { 147 trace1(TR_xdrmem_getint32, 0); 148 if (sizeof (int32_t) > (uint_t)xdrs->x_handy) { 149 xdrs->x_private += (uint_t)xdrs->x_handy; 150 xdrs->x_handy = 0; 151 trace1(TR_xdrmem_putlong, 1); 152 return (FALSE); 153 } 154 xdrs->x_handy -= sizeof (int32_t); 155 *ip = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private)))); 156 xdrs->x_private += sizeof (int32_t); 157 trace1(TR_xdrmem_getint32, 1); 158 return (TRUE); 159 } 160 161 static bool_t 162 xdrmem_putint32(XDR *xdrs, int32_t *ip) 163 { 164 trace1(TR_xdrmem_putint32, 0); 165 if (sizeof (int32_t) > (uint32_t)xdrs->x_handy) { 166 xdrs->x_private += (uint_t)xdrs->x_handy; 167 xdrs->x_handy = 0; 168 trace1(TR_xdrmem_putlong, 1); 169 return (FALSE); 170 } 171 xdrs->x_handy -= sizeof (int32_t); 172 *(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*ip)); 173 xdrs->x_private += sizeof (int32_t); 174 trace1(TR_xdrmem_putint32, 1); 175 return (TRUE); 176 } 177 178 #endif /* _LP64 */ 179 180 static bool_t 181 xdrmem_getbytes(XDR *xdrs, caddr_t addr, int len) 182 { 183 trace2(TR_xdrmem_getbytes, 0, len); 184 if ((uint32_t)len > (uint32_t)xdrs->x_handy) { 185 xdrs->x_private += (uint_t)xdrs->x_handy; 186 xdrs->x_handy = 0; 187 trace1(TR_xdrmem_getbytes, 1); 188 return (FALSE); 189 } 190 xdrs->x_handy -= len; 191 (void) memcpy(addr, xdrs->x_private, (uint_t)len); 192 xdrs->x_private += (uint_t)len; 193 trace1(TR_xdrmem_getbytes, 1); 194 return (TRUE); 195 } 196 197 static bool_t 198 xdrmem_putbytes(XDR *xdrs, caddr_t addr, int len) 199 { 200 trace2(TR_xdrmem_putbytes, 0, len); 201 if ((uint32_t)len > (uint32_t)xdrs->x_handy) { 202 xdrs->x_private += (uint_t)xdrs->x_handy; 203 xdrs->x_handy = 0; 204 trace1(TR_xdrmem_putbytes, 1); 205 return (FALSE); 206 } 207 xdrs->x_handy -= len; 208 (void) memcpy(xdrs->x_private, addr, (uint_t)len); 209 xdrs->x_private += (uint_t)len; 210 trace1(TR_xdrmem_putbytes, 1); 211 return (TRUE); 212 } 213 214 static uint_t 215 xdrmem_getpos(xdrs) 216 XDR *xdrs; 217 { 218 trace1(TR_xdrmem_getpos, 0); 219 trace1(TR_xdrmem_getpos, 1); 220 return (uint_t)((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_base); 221 } 222 223 static bool_t 224 xdrmem_setpos(xdrs, pos) 225 XDR *xdrs; 226 uint_t pos; 227 { 228 caddr_t newaddr = xdrs->x_base + pos; 229 caddr_t lastaddr = xdrs->x_private + (uint_t)xdrs->x_handy; 230 231 trace2(TR_xdrmem_setpos, 0, pos); 232 if ((long)newaddr > (long)lastaddr) { 233 trace1(TR_xdrmem_setpos, 1); 234 return (FALSE); 235 } 236 xdrs->x_private = newaddr; 237 xdrs->x_handy = (int)((uintptr_t)lastaddr - (uintptr_t)newaddr); 238 trace1(TR_xdrmem_setpos, 1); 239 return (TRUE); 240 } 241 242 static rpc_inline_t * 243 xdrmem_inline(XDR *xdrs, int len) 244 { 245 rpc_inline_t *buf = 0; 246 247 trace2(TR_xdrmem_inline, 0, len); 248 if ((uint32_t)xdrs->x_handy >= (uint32_t)len) { 249 xdrs->x_handy -= len; 250 buf = (rpc_inline_t *)xdrs->x_private; 251 xdrs->x_private += (uint_t)len; 252 } 253 trace2(TR_xdrmem_inline, 1, len); 254 return (buf); 255 } 256 257 static bool_t 258 xdrmem_control(XDR *xdrs, int request, void *info) 259 { 260 xdr_bytesrec *xptr; 261 262 switch (request) { 263 264 case XDR_GET_BYTES_AVAIL: 265 xptr = (xdr_bytesrec *) info; 266 xptr->xc_is_last_record = TRUE; 267 xptr->xc_num_avail = xdrs->x_handy; 268 return (TRUE); 269 default: 270 return (FALSE); 271 272 } 273 274 } 275 276 static struct xdr_ops * 277 xdrmem_ops() 278 { 279 static struct xdr_ops ops; 280 extern mutex_t ops_lock; 281 282 /* VARIABLES PROTECTED BY ops_lock: ops */ 283 284 285 trace1(TR_xdrmem_ops, 0); 286 mutex_lock(&ops_lock); 287 if (ops.x_getlong == NULL) { 288 ops.x_getlong = xdrmem_getlong; 289 ops.x_putlong = xdrmem_putlong; 290 ops.x_getbytes = xdrmem_getbytes; 291 ops.x_putbytes = xdrmem_putbytes; 292 ops.x_getpostn = xdrmem_getpos; 293 ops.x_setpostn = xdrmem_setpos; 294 ops.x_inline = xdrmem_inline; 295 ops.x_destroy = xdrmem_destroy; 296 ops.x_control = xdrmem_control; 297 #if defined(_LP64) 298 ops.x_getint32 = xdrmem_getint32; 299 ops.x_putint32 = xdrmem_putint32; 300 #endif 301 } 302 mutex_unlock(&ops_lock); 303 trace1(TR_xdrmem_ops, 1); 304 return (&ops); 305 } 306