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 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * xdr_mem.h, XDR implementation using memory buffers. 39 * 40 * If you have some data to be interpreted as external data representation 41 * or to be converted to external data representation in a memory buffer, 42 * then this is the package for you. 43 */ 44 45 #include "mt.h" 46 #include "rpc_mt.h" 47 #include <sys/types.h> 48 #include <rpc/types.h> 49 #include <rpc/xdr.h> 50 #include <memory.h> 51 #include <inttypes.h> 52 53 static struct xdr_ops *xdrmem_ops(void); 54 55 /* 56 * Meaning of the private areas of the xdr struct for xdr_mem 57 * x_base : Base from where the xdr stream starts 58 * x_private : The current position of the stream. 59 * x_handy : The size of the stream buffer. 60 */ 61 62 /* 63 * The procedure xdrmem_create initializes a stream descriptor for a 64 * memory buffer. 65 */ 66 void 67 xdrmem_create(XDR *xdrs, const caddr_t addr, const uint_t size, 68 const enum xdr_op op) 69 { 70 caddr_t eaddr = addr; 71 72 xdrs->x_op = op; 73 xdrs->x_ops = xdrmem_ops(); 74 xdrs->x_private = xdrs->x_base = 0; 75 /* 76 * We check here that the size is with in the range of the 77 * address space. If not we set x_handy to zero. This will cause 78 * all xdrmem entry points to fail. 79 */ 80 eaddr = addr + size; 81 82 if (eaddr < addr) 83 xdrs->x_handy = 0; 84 else { 85 xdrs->x_handy = size; 86 xdrs->x_private = xdrs->x_base = addr; 87 } 88 } 89 90 /* ARGSUSED */ 91 static void 92 xdrmem_destroy(XDR *xdrs) 93 { 94 } 95 96 static bool_t 97 xdrmem_getlong(XDR *xdrs, long *lp) 98 { 99 if (sizeof (int32_t) > (uint32_t)xdrs->x_handy) { 100 xdrs->x_private += (uint_t)xdrs->x_handy; 101 xdrs->x_handy = 0; 102 return (FALSE); 103 } 104 xdrs->x_handy -= sizeof (int32_t); 105 /* LINTED pointer cast */ 106 *lp = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private)))); 107 xdrs->x_private += sizeof (int32_t); 108 return (TRUE); 109 } 110 111 static bool_t 112 xdrmem_putlong(XDR *xdrs, long *lp) 113 { 114 #if defined(_LP64) 115 if ((*lp > INT32_MAX) || (*lp < INT32_MIN)) 116 return (FALSE); 117 #endif 118 119 if ((sizeof (int32_t) > (uint32_t)xdrs->x_handy)) { 120 xdrs->x_private += (uint_t)xdrs->x_handy; 121 xdrs->x_handy = 0; 122 return (FALSE); 123 } 124 xdrs->x_handy -= sizeof (int32_t); 125 /* LINTED pointer cast */ 126 *(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*lp)); 127 xdrs->x_private += sizeof (int32_t); 128 return (TRUE); 129 } 130 131 #if defined(_LP64) 132 static bool_t 133 xdrmem_getint32(XDR *xdrs, int32_t *ip) 134 { 135 if (sizeof (int32_t) > (uint_t)xdrs->x_handy) { 136 xdrs->x_private += (uint_t)xdrs->x_handy; 137 xdrs->x_handy = 0; 138 return (FALSE); 139 } 140 xdrs->x_handy -= sizeof (int32_t); 141 /* LINTED pointer cast */ 142 *ip = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private)))); 143 xdrs->x_private += sizeof (int32_t); 144 return (TRUE); 145 } 146 147 static bool_t 148 xdrmem_putint32(XDR *xdrs, int32_t *ip) 149 { 150 if (sizeof (int32_t) > (uint32_t)xdrs->x_handy) { 151 xdrs->x_private += (uint_t)xdrs->x_handy; 152 xdrs->x_handy = 0; 153 return (FALSE); 154 } 155 xdrs->x_handy -= sizeof (int32_t); 156 /* LINTED pointer cast */ 157 *(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*ip)); 158 xdrs->x_private += sizeof (int32_t); 159 return (TRUE); 160 } 161 #endif /* _LP64 */ 162 163 static bool_t 164 xdrmem_getbytes(XDR *xdrs, caddr_t addr, int len) 165 { 166 if ((uint32_t)len > (uint32_t)xdrs->x_handy) { 167 xdrs->x_private += (uint_t)xdrs->x_handy; 168 xdrs->x_handy = 0; 169 return (FALSE); 170 } 171 xdrs->x_handy -= len; 172 (void) memcpy(addr, xdrs->x_private, (uint_t)len); 173 xdrs->x_private += (uint_t)len; 174 return (TRUE); 175 } 176 177 static bool_t 178 xdrmem_putbytes(XDR *xdrs, caddr_t addr, int len) 179 { 180 if ((uint32_t)len > (uint32_t)xdrs->x_handy) { 181 xdrs->x_private += (uint_t)xdrs->x_handy; 182 xdrs->x_handy = 0; 183 return (FALSE); 184 } 185 xdrs->x_handy -= len; 186 (void) memcpy(xdrs->x_private, addr, (uint_t)len); 187 xdrs->x_private += (uint_t)len; 188 return (TRUE); 189 } 190 191 static uint_t 192 xdrmem_getpos(XDR *xdrs) 193 { 194 return (uint_t)((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_base); 195 } 196 197 static bool_t 198 xdrmem_setpos(XDR *xdrs, uint_t pos) 199 { 200 caddr_t newaddr = xdrs->x_base + pos; 201 caddr_t lastaddr = xdrs->x_private + (uint_t)xdrs->x_handy; 202 203 if ((long)newaddr > (long)lastaddr) 204 return (FALSE); 205 xdrs->x_private = newaddr; 206 xdrs->x_handy = (int)((uintptr_t)lastaddr - (uintptr_t)newaddr); 207 return (TRUE); 208 } 209 210 static rpc_inline_t * 211 xdrmem_inline(XDR *xdrs, int len) 212 { 213 rpc_inline_t *buf = 0; 214 215 if ((uint32_t)xdrs->x_handy >= (uint32_t)len) { 216 xdrs->x_handy -= len; 217 /* LINTED pointer cast */ 218 buf = (rpc_inline_t *)xdrs->x_private; 219 xdrs->x_private += (uint_t)len; 220 } 221 return (buf); 222 } 223 224 static bool_t 225 xdrmem_control(XDR *xdrs, int request, void *info) 226 { 227 xdr_bytesrec *xptr; 228 229 switch (request) { 230 case XDR_GET_BYTES_AVAIL: 231 xptr = (xdr_bytesrec *) info; 232 xptr->xc_is_last_record = TRUE; 233 xptr->xc_num_avail = xdrs->x_handy; 234 return (TRUE); 235 default: 236 return (FALSE); 237 238 } 239 240 } 241 242 static struct xdr_ops * 243 xdrmem_ops(void) 244 { 245 static struct xdr_ops ops; 246 extern mutex_t ops_lock; 247 248 /* VARIABLES PROTECTED BY ops_lock: ops */ 249 (void) mutex_lock(&ops_lock); 250 if (ops.x_getlong == NULL) { 251 ops.x_getlong = xdrmem_getlong; 252 ops.x_putlong = xdrmem_putlong; 253 ops.x_getbytes = xdrmem_getbytes; 254 ops.x_putbytes = xdrmem_putbytes; 255 ops.x_getpostn = xdrmem_getpos; 256 ops.x_setpostn = xdrmem_setpos; 257 ops.x_inline = xdrmem_inline; 258 ops.x_destroy = xdrmem_destroy; 259 ops.x_control = xdrmem_control; 260 #if defined(_LP64) 261 ops.x_getint32 = xdrmem_getint32; 262 ops.x_putint32 = xdrmem_putint32; 263 #endif 264 } 265 (void) mutex_unlock(&ops_lock); 266 return (&ops); 267 } 268