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