xref: /titanic_50/usr/src/lib/libnsl/rpc/xdr_mem.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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