xref: /illumos-gate/usr/src/lib/libnsl/rpc/xdr_mem.c (revision 6a1c6faa6f0834799d7de3e77fac2ec32d923f9a)
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