xdr_mem.c revision 256281
155682Smarkm/*	$NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $	*/
2233294Sstas
3233294Sstas/*
4233294Sstas * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
555682Smarkm * unrestricted use provided that this legend is included on all tape
6233294Sstas * media and as a part of the software program in whole or part.  Users
7233294Sstas * may copy or modify Sun RPC without charge, but are not authorized
8233294Sstas * to license or distribute it to anyone else except as part of a product or
955682Smarkm * program developed by the user.
10233294Sstas *
11233294Sstas * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1255682Smarkm * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13233294Sstas * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14233294Sstas *
15233294Sstas * Sun RPC is provided with no support and without any obligation on the
1655682Smarkm * part of Sun Microsystems, Inc. to assist in its use, correction,
17233294Sstas * modification or enhancement.
18233294Sstas *
19233294Sstas * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2055682Smarkm * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21233294Sstas * OR ANY PART THEREOF.
22233294Sstas *
23233294Sstas * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24233294Sstas * or profits or other special, indirect and consequential damages, even if
25233294Sstas * Sun has been advised of the possibility of such damages.
26233294Sstas *
27233294Sstas * Sun Microsystems, Inc.
28233294Sstas * 2550 Garcia Avenue
29233294Sstas * Mountain View, California  94043
30233294Sstas */
31233294Sstas
3255682Smarkm#if defined(LIBC_SCCS) && !defined(lint)
3355682Smarkmstatic char *sccsid2 = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
3455682Smarkmstatic char *sccsid = "@(#)xdr_mem.c	2.1 88/07/29 4.0 RPCSRC";
3555682Smarkm#endif
36233294Sstas#include <sys/cdefs.h>
3755682Smarkm__FBSDID("$FreeBSD: stable/10/sys/xdr/xdr_mem.c 192971 2009-05-28 08:18:12Z kmacy $");
3855682Smarkm
3955682Smarkm/*
4055682Smarkm * xdr_mem.h, XDR implementation using memory buffers.
4155682Smarkm *
42178825Sdfr * Copyright (C) 1984, Sun Microsystems, Inc.
43178825Sdfr *
4455682Smarkm * If you have some data to be interpreted as external data representation
4555682Smarkm * or to be converted to external data representation in a memory buffer,
4655682Smarkm * then this is the package for you.
4755682Smarkm *
48178825Sdfr */
49178825Sdfr
5055682Smarkm#include <sys/param.h>
51178825Sdfr#include <sys/systm.h>
52178825Sdfr#include <sys/malloc.h>
53178825Sdfr
54178825Sdfr#include <rpc/types.h>
55178825Sdfr#include <rpc/xdr.h>
56178825Sdfr
57178825Sdfrstatic void xdrmem_destroy(XDR *);
58178825Sdfrstatic bool_t xdrmem_getlong_aligned(XDR *, long *);
59178825Sdfrstatic bool_t xdrmem_putlong_aligned(XDR *, const long *);
60178825Sdfrstatic bool_t xdrmem_getlong_unaligned(XDR *, long *);
61178825Sdfrstatic bool_t xdrmem_putlong_unaligned(XDR *, const long *);
62178825Sdfrstatic bool_t xdrmem_getbytes(XDR *, char *, u_int);
63233294Sstasstatic bool_t xdrmem_putbytes(XDR *, const char *, u_int);
64178825Sdfr/* XXX: w/64-bit pointers, u_int not enough! */
65178825Sdfrstatic u_int xdrmem_getpos(XDR *);
66178825Sdfrstatic bool_t xdrmem_setpos(XDR *, u_int);
67178825Sdfrstatic int32_t *xdrmem_inline_aligned(XDR *, u_int);
68178825Sdfrstatic int32_t *xdrmem_inline_unaligned(XDR *, u_int);
69178825Sdfrstatic bool_t xdrmem_control(XDR *xdrs, int request, void *info);
70178825Sdfr
71178825Sdfrstatic const struct	xdr_ops xdrmem_ops_aligned = {
72178825Sdfr	xdrmem_getlong_aligned,
73178825Sdfr	xdrmem_putlong_aligned,
74178825Sdfr	xdrmem_getbytes,
75178825Sdfr	xdrmem_putbytes,
76178825Sdfr	xdrmem_getpos,
77178825Sdfr	xdrmem_setpos,
78178825Sdfr	xdrmem_inline_aligned,
79178825Sdfr	xdrmem_destroy,
80178825Sdfr	xdrmem_control
81178825Sdfr};
82178825Sdfr
83178825Sdfrstatic const struct	xdr_ops xdrmem_ops_unaligned = {
84178825Sdfr	xdrmem_getlong_unaligned,
85178825Sdfr	xdrmem_putlong_unaligned,
86178825Sdfr	xdrmem_getbytes,
87178825Sdfr	xdrmem_putbytes,
88178825Sdfr	xdrmem_getpos,
89178825Sdfr	xdrmem_setpos,
90178825Sdfr	xdrmem_inline_unaligned,
91178825Sdfr	xdrmem_destroy,
92178825Sdfr	xdrmem_control
93178825Sdfr};
94178825Sdfr
95178825Sdfr/*
96178825Sdfr * The procedure xdrmem_create initializes a stream descriptor for a
97178825Sdfr * memory buffer.
98178825Sdfr */
99178825Sdfrvoid
100178825Sdfrxdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
101178825Sdfr{
102178825Sdfr
103178825Sdfr	xdrs->x_op = op;
104178825Sdfr	xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1))
105178825Sdfr	    ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
106178825Sdfr	xdrs->x_private = xdrs->x_base = addr;
107178825Sdfr	xdrs->x_handy = size;
108178825Sdfr}
109178825Sdfr
110178825Sdfr/*ARGSUSED*/
111178825Sdfrstatic void
11272445Sassarxdrmem_destroy(XDR *xdrs)
11372445Sassar{
11455682Smarkm
11572445Sassar}
11655682Smarkm
11772445Sassarstatic bool_t
11872445Sassarxdrmem_getlong_aligned(XDR *xdrs, long *lp)
119178825Sdfr{
12072445Sassar
12172445Sassar	if (xdrs->x_handy < sizeof(int32_t))
12272445Sassar		return (FALSE);
123178825Sdfr	xdrs->x_handy -= sizeof(int32_t);
124178825Sdfr	*lp = ntohl(*(u_int32_t *)xdrs->x_private);
125178825Sdfr	xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
126178825Sdfr	return (TRUE);
127178825Sdfr}
128178825Sdfr
129178825Sdfrstatic bool_t
130178825Sdfrxdrmem_putlong_aligned(XDR *xdrs, const long *lp)
131178825Sdfr{
132178825Sdfr
13372445Sassar	if (xdrs->x_handy < sizeof(int32_t))
134178825Sdfr		return (FALSE);
135178825Sdfr	xdrs->x_handy -= sizeof(int32_t);
136178825Sdfr	*(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp);
137178825Sdfr	xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
138178825Sdfr	return (TRUE);
139233294Sstas}
140178825Sdfr
141178825Sdfrstatic bool_t
14272445Sassarxdrmem_getlong_unaligned(XDR *xdrs, long *lp)
143178825Sdfr{
144178825Sdfr	u_int32_t l;
145178825Sdfr
14672445Sassar	if (xdrs->x_handy < sizeof(int32_t))
14772445Sassar		return (FALSE);
14872445Sassar	xdrs->x_handy -= sizeof(int32_t);
149178825Sdfr	memmove(&l, xdrs->x_private, sizeof(int32_t));
15072445Sassar	*lp = ntohl(l);
15172445Sassar	xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
15272445Sassar	return (TRUE);
15372445Sassar}
15455682Smarkm
155178825Sdfrstatic bool_t
156178825Sdfrxdrmem_putlong_unaligned(XDR *xdrs, const long *lp)
157178825Sdfr{
15872445Sassar	u_int32_t l;
159178825Sdfr
16055682Smarkm	if (xdrs->x_handy < sizeof(int32_t))
16172445Sassar		return (FALSE);
16272445Sassar	xdrs->x_handy -= sizeof(int32_t);
163178825Sdfr	l = htonl((u_int32_t)*lp);
164178825Sdfr	memmove(xdrs->x_private, &l, sizeof(int32_t));
165178825Sdfr	xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
166178825Sdfr	return (TRUE);
167178825Sdfr}
16872445Sassar
16972445Sassarstatic bool_t
17072445Sassarxdrmem_getbytes(XDR *xdrs, char *addr, u_int len)
17172445Sassar{
172178825Sdfr
17372445Sassar	if (xdrs->x_handy < len)
17472445Sassar		return (FALSE);
17572445Sassar	xdrs->x_handy -= len;
17672445Sassar	memmove(addr, xdrs->x_private, len);
17772445Sassar	xdrs->x_private = (char *)xdrs->x_private + len;
17872445Sassar	return (TRUE);
17972445Sassar}
180178825Sdfr
181178825Sdfrstatic bool_t
182178825Sdfrxdrmem_putbytes(XDR *xdrs, const char *addr, u_int len)
183178825Sdfr{
184178825Sdfr
18555682Smarkm	if (xdrs->x_handy < len)
186178825Sdfr		return (FALSE);
18772445Sassar	xdrs->x_handy -= len;
188178825Sdfr	memmove(xdrs->x_private, addr, len);
189178825Sdfr	xdrs->x_private = (char *)xdrs->x_private + len;
190178825Sdfr	return (TRUE);
19172445Sassar}
192178825Sdfr
193178825Sdfrstatic u_int
194178825Sdfrxdrmem_getpos(XDR *xdrs)
195178825Sdfr{
196178825Sdfr
197178825Sdfr	/* XXX w/64-bit pointers, u_int not enough! */
198178825Sdfr	return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base);
199178825Sdfr}
200178825Sdfr
201178825Sdfrstatic bool_t
202178825Sdfrxdrmem_setpos(XDR *xdrs, u_int pos)
203178825Sdfr{
204178825Sdfr	char *newaddr = xdrs->x_base + pos;
205178825Sdfr	char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy;
206178825Sdfr
20772445Sassar	if (newaddr > lastaddr)
20872445Sassar		return (FALSE);
20972445Sassar	xdrs->x_private = newaddr;
21072445Sassar	xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) <? sizeof(ptrdiff_t) */
211178825Sdfr	return (TRUE);
212233294Sstas}
213178825Sdfr
214178825Sdfrstatic int32_t *
215178825Sdfrxdrmem_inline_aligned(XDR *xdrs, u_int len)
21672445Sassar{
21772445Sassar	int32_t *buf = 0;
218178825Sdfr
219178825Sdfr	if (xdrs->x_handy >= len) {
220178825Sdfr		xdrs->x_handy -= len;
221233294Sstas		buf = (int32_t *)xdrs->x_private;
222178825Sdfr		xdrs->x_private = (char *)xdrs->x_private + len;
223178825Sdfr	}
224178825Sdfr	return (buf);
225178825Sdfr}
226178825Sdfr
227178825Sdfr/* ARGSUSED */
228178825Sdfrstatic int32_t *
229178825Sdfrxdrmem_inline_unaligned(XDR *xdrs, u_int len)
230178825Sdfr{
231178825Sdfr
232178825Sdfr	return (0);
233178825Sdfr}
234178825Sdfr
235178825Sdfrstatic bool_t
236178825Sdfrxdrmem_control(XDR *xdrs, int request, void *info)
237178825Sdfr{
238233294Sstas	xdr_bytesrec *xptr;
239178825Sdfr	int32_t *l;
240178825Sdfr	int len;
241178825Sdfr
242178825Sdfr	switch (request) {
243178825Sdfr
244178825Sdfr	case XDR_GET_BYTES_AVAIL:
245178825Sdfr		xptr = (xdr_bytesrec *)info;
24672445Sassar		xptr->xc_is_last_record = TRUE;
24755682Smarkm		xptr->xc_num_avail = xdrs->x_handy;
24890926Snectar		return (TRUE);
24990926Snectar
250178825Sdfr	case XDR_PEEK:
25190926Snectar		/*
25290926Snectar		 * Return the next 4 byte unit in the XDR stream.
253178825Sdfr		 */
254178825Sdfr		if (xdrs->x_handy < sizeof (int32_t))
25572445Sassar			return (FALSE);
25672445Sassar		l = (int32_t *)info;
25755682Smarkm		*l = (int32_t)ntohl((uint32_t)
25872445Sassar		    (*((int32_t *)(xdrs->x_private))));
25972445Sassar		return (TRUE);
260233294Sstas
261178825Sdfr	case XDR_SKIPBYTES:
262233294Sstas		/*
26355682Smarkm		 * Skip the next N bytes in the XDR stream.
264178825Sdfr		 */
265178825Sdfr		l = (int32_t *)info;
266178825Sdfr		len = RNDUP((int)(*l));
267233294Sstas		if (xdrs->x_handy < len)
268178825Sdfr			return (FALSE);
269178825Sdfr		xdrs->x_handy -= len;
27072445Sassar		xdrs->x_private = (char *)xdrs->x_private + len;
27172445Sassar		return (TRUE);
272178825Sdfr
27372445Sassar	}
274178825Sdfr	return (FALSE);
275178825Sdfr}
276178825Sdfr