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
xdrmem_create(XDR * xdrs,const caddr_t addr,const uint_t size,const enum xdr_op op)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
xdrmem_destroy(XDR * xdrs)92 xdrmem_destroy(XDR *xdrs)
93 {
94 }
95
96 static bool_t
xdrmem_getlong(XDR * xdrs,long * lp)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
xdrmem_putlong(XDR * xdrs,long * lp)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
xdrmem_getint32(XDR * xdrs,int32_t * ip)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
xdrmem_putint32(XDR * xdrs,int32_t * ip)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
xdrmem_getbytes(XDR * xdrs,caddr_t addr,int len)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
xdrmem_putbytes(XDR * xdrs,caddr_t addr,int len)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
xdrmem_getpos(XDR * xdrs)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
xdrmem_setpos(XDR * xdrs,uint_t pos)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 *
xdrmem_inline(XDR * xdrs,int len)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
xdrmem_control(XDR * xdrs,int request,void * info)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 *
xdrmem_ops(void)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