1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  *   contributors may be used to endorse or promote products derived
14  *   from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * xdr_mem.h, XDR implementation using memory buffers.
31  *
32  * Copyright (C) 1984, Sun Microsystems, Inc.
33  *
34  * If you have some data to be interpreted as external data representation
35  * or to be converted to external data representation in a memory buffer,
36  * then this is the package for you.
37  *
38  */
39 
40 #define _DEFAULT_SOURCE
41 #include <sys/types.h>
42 #include <string.h>
43 #include <limits.h>
44 
45 #include <rpc/types.h>
46 #include <rpc/xdr.h>
47 
48 #include "xdr_private.h"
49 
50 #ifndef ntohl
51 # define ntohl(x) xdr_ntohl(x)
52 #endif
53 #ifndef htonl
54 # define htonl(x) xdr_htonl(x)
55 #endif
56 
57 static void xdrmem_destroy (XDR *);
58 static bool_t xdrmem_getlong_aligned (XDR *, long *);
59 static bool_t xdrmem_putlong_aligned (XDR *, const long *);
60 static bool_t xdrmem_getlong_unaligned (XDR *, long *);
61 static bool_t xdrmem_putlong_unaligned (XDR *, const long *);
62 static bool_t xdrmem_getbytes (XDR *, char *, u_int);
63 static bool_t xdrmem_putbytes (XDR *, const char *, u_int);
64 /* XXX: w/64-bit pointers, u_int not enough! */
65 static u_int xdrmem_getpos (XDR *);
66 static bool_t xdrmem_setpos (XDR *, u_int);
67 static int32_t * xdrmem_inline_aligned (XDR *, u_int);
68 static int32_t * xdrmem_inline_unaligned (XDR *, u_int);
69 static bool_t  xdrmem_getint32_aligned (XDR *, int32_t *);
70 static bool_t  xdrmem_putint32_aligned (XDR *, const int32_t *);
71 static bool_t  xdrmem_getint32_unaligned (XDR *, int32_t *);
72 static bool_t  xdrmem_putint32_unaligned (XDR *, const int32_t *);
73 
74 static const struct xdr_ops xdrmem_ops_aligned = {
75   xdrmem_getlong_aligned,
76   xdrmem_putlong_aligned,
77   xdrmem_getbytes,
78   xdrmem_putbytes,
79   xdrmem_getpos,
80   xdrmem_setpos,
81   xdrmem_inline_aligned,
82   xdrmem_destroy,
83   xdrmem_getint32_aligned,
84   xdrmem_putint32_aligned
85 };
86 
87 static const struct xdr_ops xdrmem_ops_unaligned = {
88   xdrmem_getlong_unaligned,
89   xdrmem_putlong_unaligned,
90   xdrmem_getbytes,
91   xdrmem_putbytes,
92   xdrmem_getpos,
93   xdrmem_setpos,
94   xdrmem_inline_unaligned,
95   xdrmem_destroy,
96   xdrmem_getint32_unaligned,
97   xdrmem_putint32_unaligned
98 };
99 
100 /*
101  * The procedure xdrmem_create initializes a stream descriptor for a
102  * memory buffer.
103  */
104 void
xdrmem_create(XDR * xdrs,caddr_t addr,u_int size,enum xdr_op op)105 xdrmem_create (XDR * xdrs,
106 	caddr_t addr,
107 	u_int size,
108 	enum xdr_op op)
109 {
110   xdrs->x_op = op;
111   xdrs->x_ops = ((uintptr_t)addr & (sizeof (int32_t) - 1))
112     ? (struct xdr_ops *)&xdrmem_ops_unaligned
113     : (struct xdr_ops *)&xdrmem_ops_aligned;
114   xdrs->x_private = xdrs->x_base = addr;
115   xdrs->x_handy = size;
116 }
117 
118 static void
xdrmem_destroy(XDR * xdrs)119 xdrmem_destroy (XDR * xdrs)
120 {
121   (void) xdrs;
122 }
123 
124 static bool_t
xdrmem_getlong_aligned(XDR * xdrs,long * lp)125 xdrmem_getlong_aligned (XDR * xdrs,
126 	long *lp)
127 {
128   if (xdrs->x_handy < sizeof (int32_t))
129     return FALSE;
130   xdrs->x_handy -= sizeof (int32_t);
131   *lp = (int32_t) ntohl (*(u_int32_t *) xdrs->x_private);
132   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
133   return TRUE;
134 }
135 
136 static bool_t
xdrmem_putlong_aligned(XDR * xdrs,const long * lp)137 xdrmem_putlong_aligned (XDR * xdrs,
138 	const long *lp)
139 {
140   if (xdrs->x_handy < sizeof (int32_t))
141     return FALSE;
142   xdrs->x_handy -= sizeof (int32_t);
143   *(u_int32_t *) xdrs->x_private = htonl ((u_int32_t) * lp);
144   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
145   return TRUE;
146 }
147 
148 static bool_t
xdrmem_getlong_unaligned(XDR * xdrs,long * lp)149 xdrmem_getlong_unaligned (XDR * xdrs,
150 	long *lp)
151 {
152   u_int32_t l;
153 
154   if (xdrs->x_handy < sizeof (int32_t))
155     return FALSE;
156   xdrs->x_handy -= sizeof (int32_t);
157   memmove (&l, xdrs->x_private, sizeof (int32_t));
158   *lp = ntohl (l);
159   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
160   return TRUE;
161 }
162 
163 static bool_t
xdrmem_putlong_unaligned(XDR * xdrs,const long * lp)164 xdrmem_putlong_unaligned (XDR * xdrs,
165 	const long *lp)
166 {
167   u_int32_t l;
168 
169   if (xdrs->x_handy < sizeof (int32_t))
170     return FALSE;
171   xdrs->x_handy -= sizeof (int32_t);
172   l = htonl ((u_int32_t) * lp);
173   memmove (xdrs->x_private, &l, sizeof (int32_t));
174   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
175   return TRUE;
176 }
177 
178 static bool_t
xdrmem_getbytes(XDR * xdrs,char * addr,u_int len)179 xdrmem_getbytes (XDR * xdrs,
180 	char *addr,
181 	u_int len)
182 {
183   if (xdrs->x_handy < len)
184     return FALSE;
185   xdrs->x_handy -= len;
186   memmove (addr, xdrs->x_private, len);
187   xdrs->x_private = (char *) xdrs->x_private + len;
188   return TRUE;
189 }
190 
191 static bool_t
xdrmem_putbytes(XDR * xdrs,const char * addr,u_int len)192 xdrmem_putbytes (XDR * xdrs,
193 	const char *addr,
194 	u_int len)
195 {
196   if (xdrs->x_handy < len)
197     return FALSE;
198   xdrs->x_handy -= len;
199   memmove (xdrs->x_private, addr, len);
200   xdrs->x_private = (char *) xdrs->x_private + len;
201   return TRUE;
202 }
203 
204 static u_int
xdrmem_getpos(XDR * xdrs)205 xdrmem_getpos (XDR * xdrs)
206 {
207   /* XXX w/64-bit pointers, u_int not enough! */
208   return (u_int) ((uintptr_t) xdrs->x_private - (uintptr_t) xdrs->x_base);
209 }
210 
211 static bool_t
xdrmem_setpos(XDR * xdrs,u_int pos)212 xdrmem_setpos (XDR * xdrs,
213 	u_int pos)
214 {
215   caddr_t newaddr = xdrs->x_base + pos;
216   caddr_t lastaddr = (caddr_t) xdrs->x_private + xdrs->x_handy;
217   size_t handy = lastaddr - newaddr;
218 
219   if (newaddr > lastaddr
220       || newaddr < xdrs->x_base
221       || handy != (u_int) handy)
222     return FALSE;
223 
224   xdrs->x_private = newaddr;
225   xdrs->x_handy = (u_int) handy;
226   /* XXX sizeof(u_int) <? sizeof(ptrdiff_t) */
227   return TRUE;
228 }
229 
230 static int32_t *
xdrmem_inline_aligned(XDR * xdrs,u_int len)231 xdrmem_inline_aligned (XDR * xdrs,
232 	u_int len)
233 {
234   int32_t *buf = 0;
235 
236   if (xdrs->x_handy >= len)
237     {
238       xdrs->x_handy -= len;
239       buf = (int32_t *) xdrs->x_private;
240       xdrs->x_private = (char *) xdrs->x_private + len;
241     }
242   return (buf);
243 }
244 
245 static int32_t *
xdrmem_inline_unaligned(XDR * xdrs,u_int len)246 xdrmem_inline_unaligned (XDR * xdrs,
247 	u_int len)
248 {
249   (void) xdrs;
250   (void) len;
251   return (0);
252 }
253 
254 static bool_t
xdrmem_getint32_aligned(XDR * xdrs,int32_t * ip)255 xdrmem_getint32_aligned (XDR *xdrs,
256 	int32_t *ip)
257 {
258   if (xdrs->x_handy < sizeof(int32_t))
259     return FALSE;
260   xdrs->x_handy -= sizeof(int32_t);
261   *ip = (int32_t) ntohl (*(u_int32_t *) xdrs->x_private);
262   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
263   return TRUE;
264 }
265 
266 static bool_t
xdrmem_putint32_aligned(XDR * xdrs,const int32_t * ip)267 xdrmem_putint32_aligned (XDR *xdrs,
268 	const int32_t *ip)
269 {
270   if (xdrs->x_handy < sizeof(int32_t))
271     return FALSE;
272   xdrs->x_handy -= sizeof(int32_t);
273   *(u_int32_t *) xdrs->x_private = htonl ((u_int32_t) * ip);
274   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
275   return TRUE;
276 }
277 
278 static bool_t
xdrmem_getint32_unaligned(XDR * xdrs,int32_t * ip)279 xdrmem_getint32_unaligned (XDR *xdrs,
280 	int32_t *ip)
281 {
282   u_int32_t l;
283 
284   if (xdrs->x_handy < sizeof(int32_t))
285     return FALSE;
286   xdrs->x_handy -= sizeof(int32_t);
287   memmove (&l, xdrs->x_private, sizeof (int32_t));
288   *ip = (int32_t) ntohl (l);
289   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
290   return TRUE;
291 }
292 
293 static bool_t
xdrmem_putint32_unaligned(XDR * xdrs,const int32_t * ip)294 xdrmem_putint32_unaligned (XDR *xdrs,
295 	const int32_t *ip)
296 {
297   u_int32_t l;
298 
299   if (xdrs->x_handy < sizeof(int32_t))
300     return FALSE;
301   xdrs->x_handy -= sizeof(int32_t);
302   l = htonl ((u_int32_t) * ip);
303   memmove (xdrs->x_private, &l, sizeof (int32_t));
304   xdrs->x_private = (char *) xdrs->x_private + sizeof (int32_t);
305   return TRUE;
306 }
307 
308