1 /*	$OpenBSD: xdr_mem.c,v 1.12 2005/08/08 08:05:36 espie Exp $ */
2 /*
3  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4  * unrestricted use provided that this legend is included on all tape
5  * media and as a part of the software program in whole or part.  Users
6  * may copy or modify Sun RPC without charge, but are not authorized
7  * to license or distribute it to anyone else except as part of a product or
8  * program developed by the user.
9  *
10  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13  *
14  * Sun RPC is provided with no support and without any obligation on the
15  * part of Sun Microsystems, Inc. to assist in its use, correction,
16  * modification or enhancement.
17  *
18  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20  * OR ANY PART THEREOF.
21  *
22  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23  * or profits or other special, indirect and consequential damages, even if
24  * Sun has been advised of the possibility of such damages.
25  *
26  * Sun Microsystems, Inc.
27  * 2550 Garcia Avenue
28  * Mountain View, California  94043
29  */
30 
31 /*
32  * xdr_mem.h, XDR implementation using memory buffers.
33  *
34  * Copyright (C) 1984, Sun Microsystems, Inc.
35  *
36  * If you have some data to be interpreted as external data representation
37  * or to be converted to external data representation in a memory buffer,
38  * then this is the package for you.
39  *
40  */
41 
42 #include <string.h>
43 
44 #include <rpc/types.h>
45 #include <rpc/xdr.h>
46 #include <netinet/in.h>
47 
48 static bool_t	xdrmem_getlong_aligned(XDR *, long *);
49 static bool_t	xdrmem_putlong_aligned(XDR *, long *);
50 static bool_t	xdrmem_getlong_unaligned(XDR *, long *);
51 static bool_t	xdrmem_putlong_unaligned(XDR *, long *);
52 static bool_t	xdrmem_getbytes(XDR *, caddr_t, u_int);
53 static bool_t	xdrmem_putbytes(XDR *, caddr_t, u_int);
54 static u_int	xdrmem_getpos(XDR *); /* XXX w/64-bit pointers, u_int not enough! */
55 static bool_t	xdrmem_setpos(XDR *, u_int);
56 static int32_t *xdrmem_inline_aligned(XDR *, u_int);
57 static int32_t *xdrmem_inline_unaligned(XDR *, u_int);
58 static void	xdrmem_destroy(XDR *);
59 
60 static struct	xdr_ops xdrmem_ops_aligned = {
61 	xdrmem_getlong_aligned,
62 	xdrmem_putlong_aligned,
63 	xdrmem_getbytes,
64 	xdrmem_putbytes,
65 	xdrmem_getpos,
66 	xdrmem_setpos,
67 	xdrmem_inline_aligned,
68 	xdrmem_destroy
69 };
70 
71 static struct	xdr_ops xdrmem_ops_unaligned = {
72 	xdrmem_getlong_unaligned,
73 	xdrmem_putlong_unaligned,
74 	xdrmem_getbytes,
75 	xdrmem_putbytes,
76 	xdrmem_getpos,
77 	xdrmem_setpos,
78 	xdrmem_inline_unaligned,
79 	xdrmem_destroy
80 };
81 
82 /*
83  * The procedure xdrmem_create initializes a stream descriptor for a
84  * memory buffer.
85  */
86 void
xdrmem_create(XDR * xdrs,caddr_t addr,u_int size,enum xdr_op op)87 xdrmem_create(XDR *xdrs, caddr_t addr, u_int size, enum xdr_op op)
88 {
89 
90 	xdrs->x_op = op;
91 	xdrs->x_ops = ((size_t)addr & (sizeof(int32_t) - 1))
92 	    ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
93 	xdrs->x_private = xdrs->x_base = addr;
94 	xdrs->x_handy = size;
95 }
96 
97 static void
xdrmem_destroy(XDR * xdrs)98 xdrmem_destroy(XDR *xdrs)
99 {
100 }
101 
102 static bool_t
xdrmem_getlong_aligned(XDR * xdrs,long int * lp)103 xdrmem_getlong_aligned(XDR *xdrs, long int *lp)
104 {
105 
106 	if (xdrs->x_handy < sizeof(int32_t))
107 		return (FALSE);
108 	xdrs->x_handy -= sizeof(int32_t);
109 	*lp = ntohl(*(int32_t *)xdrs->x_private);
110 	xdrs->x_private += sizeof(int32_t);
111 	return (TRUE);
112 }
113 
114 static bool_t
xdrmem_putlong_aligned(XDR * xdrs,long int * lp)115 xdrmem_putlong_aligned(XDR *xdrs, long int *lp)
116 {
117 
118 	if (xdrs->x_handy < sizeof(int32_t))
119 		return (FALSE);
120 	xdrs->x_handy -= sizeof(int32_t);
121 	*(int32_t *)xdrs->x_private = htonl((u_int32_t)*lp);
122 	xdrs->x_private += sizeof(int32_t);
123 	return (TRUE);
124 }
125 
126 static bool_t
xdrmem_getlong_unaligned(XDR * xdrs,long int * lp)127 xdrmem_getlong_unaligned(XDR *xdrs, long int *lp)
128 {
129 	int32_t l;
130 
131 	if (xdrs->x_handy < sizeof(int32_t))
132 		return (FALSE);
133 	xdrs->x_handy -= sizeof(int32_t);
134 	memcpy(&l, xdrs->x_private, sizeof(int32_t));
135 	*lp = ntohl(l);
136 	xdrs->x_private += sizeof(int32_t);
137 	return (TRUE);
138 }
139 
140 static bool_t
xdrmem_putlong_unaligned(XDR * xdrs,long int * lp)141 xdrmem_putlong_unaligned(XDR *xdrs, long int *lp)
142 {
143 	int32_t l;
144 
145 	if (xdrs->x_handy < sizeof(int32_t))
146 		return (FALSE);
147 	xdrs->x_handy -= sizeof(int32_t);
148 	l = htonl((u_int32_t)*lp);
149 	memcpy(xdrs->x_private, &l, sizeof(int32_t));
150 	xdrs->x_private += sizeof(int32_t);
151 	return (TRUE);
152 }
153 
154 static bool_t
xdrmem_getbytes(XDR * xdrs,caddr_t addr,u_int len)155 xdrmem_getbytes(XDR *xdrs, caddr_t addr, u_int len)
156 {
157 
158 	if (xdrs->x_handy < len)
159 		return (FALSE);
160 	xdrs->x_handy -= len;
161 	memcpy(addr, xdrs->x_private, len);
162 	xdrs->x_private += len;
163 	return (TRUE);
164 }
165 
166 static bool_t
xdrmem_putbytes(XDR * xdrs,caddr_t addr,u_int len)167 xdrmem_putbytes(XDR *xdrs, caddr_t addr, u_int len)
168 {
169 
170 	if (xdrs->x_handy < len)
171 		return (FALSE);
172 	xdrs->x_handy -= len;
173 	memcpy(xdrs->x_private, addr, len);
174 	xdrs->x_private += len;
175 	return (TRUE);
176 }
177 
178 static u_int
xdrmem_getpos(XDR * xdrs)179 xdrmem_getpos(XDR *xdrs)
180 {
181 
182 	/* XXX w/64-bit pointers, u_int not enough! */
183 	return ((u_long)xdrs->x_private - (u_long)xdrs->x_base);
184 }
185 
186 static bool_t
xdrmem_setpos(XDR * xdrs,u_int pos)187 xdrmem_setpos(XDR *xdrs, u_int pos)
188 {
189 	caddr_t newaddr = xdrs->x_base + pos;
190 	caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
191 
192 	if (newaddr > lastaddr)
193 		return (FALSE);
194 	xdrs->x_private = newaddr;
195 	xdrs->x_handy = (u_int)(lastaddr - newaddr);	/* XXX w/64-bit pointers, u_int not enough! */
196 	return (TRUE);
197 }
198 
199 static int32_t *
xdrmem_inline_aligned(XDR * xdrs,u_int len)200 xdrmem_inline_aligned(XDR *xdrs, u_int len)
201 {
202 	int32_t *buf = 0;
203 
204 	if (xdrs->x_handy >= len) {
205 		xdrs->x_handy -= len;
206 		buf = (int32_t *)xdrs->x_private;
207 		xdrs->x_private += len;
208 	}
209 	return (buf);
210 }
211 
212 /* ARGSUSED */
213 static int32_t *
xdrmem_inline_unaligned(XDR * xdrs,u_int len)214 xdrmem_inline_unaligned(XDR *xdrs, u_int len)
215 {
216 
217 	return (0);
218 }
219