1177633Sdfr/*	$NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $	*/
2177633Sdfr
3261057Smav/*-
4261057Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261057Smav * All rights reserved.
6177633Sdfr *
7261057Smav * Redistribution and use in source and binary forms, with or without
8261057Smav * modification, are permitted provided that the following conditions are met:
9261057Smav * - Redistributions of source code must retain the above copyright notice,
10261057Smav *   this list of conditions and the following disclaimer.
11261057Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261057Smav *   this list of conditions and the following disclaimer in the documentation
13261057Smav *   and/or other materials provided with the distribution.
14261057Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261057Smav *   contributors may be used to endorse or promote products derived
16261057Smav *   from this software without specific prior written permission.
17261057Smav *
18261057Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261057Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261057Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261057Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261057Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261057Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261057Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261057Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261057Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261057Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261057Smav * POSSIBILITY OF SUCH DAMAGE.
29177633Sdfr *
30177633Sdfr *	from: @(#)xdr.h 1.19 87/04/22 SMI
31177633Sdfr *	from: @(#)xdr.h	2.2 88/07/29 4.0 RPCSRC
32177633Sdfr * $FreeBSD$
33177633Sdfr */
34177633Sdfr
35177633Sdfr/*
36177633Sdfr * xdr.h, External Data Representation Serialization Routines.
37177633Sdfr *
38177633Sdfr * Copyright (C) 1984, Sun Microsystems, Inc.
39177633Sdfr */
40177633Sdfr
41177633Sdfr#ifndef _KRPC_XDR_H
42177633Sdfr#define _KRPC_XDR_H
43177633Sdfr#include <sys/cdefs.h>
44177633Sdfr
45177633Sdfr/*
46177633Sdfr * XDR provides a conventional way for converting between C data
47177633Sdfr * types and an external bit-string representation.  Library supplied
48177633Sdfr * routines provide for the conversion on built-in C data types.  These
49177633Sdfr * routines and utility routines defined here are used to help implement
50177633Sdfr * a type encode/decode routine for each user-defined type.
51177633Sdfr *
52177633Sdfr * Each data type provides a single procedure which takes two arguments:
53177633Sdfr *
54177633Sdfr *	bool_t
55177633Sdfr *	xdrproc(xdrs, argresp)
56177633Sdfr *		XDR *xdrs;
57177633Sdfr *		<type> *argresp;
58177633Sdfr *
59177633Sdfr * xdrs is an instance of a XDR handle, to which or from which the data
60177633Sdfr * type is to be converted.  argresp is a pointer to the structure to be
61177633Sdfr * converted.  The XDR handle contains an operation field which indicates
62177633Sdfr * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
63177633Sdfr *
64177633Sdfr * XDR_DECODE may allocate space if the pointer argresp is null.  This
65177633Sdfr * data can be freed with the XDR_FREE operation.
66177633Sdfr *
67177633Sdfr * We write only one procedure per data type to make it easy
68177633Sdfr * to keep the encode and decode procedures for a data type consistent.
69177633Sdfr * In many cases the same code performs all operations on a user defined type,
70177633Sdfr * because all the hard work is done in the component type routines.
71177633Sdfr * decode as a series of calls on the nested data types.
72177633Sdfr */
73177633Sdfr
74177633Sdfr/*
75177633Sdfr * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
76177633Sdfr * stream.  XDR_DECODE causes the type to be extracted from the stream.
77177633Sdfr * XDR_FREE can be used to release the space allocated by an XDR_DECODE
78177633Sdfr * request.
79177633Sdfr */
80177633Sdfrenum xdr_op {
81177633Sdfr	XDR_ENCODE=0,
82177633Sdfr	XDR_DECODE=1,
83177633Sdfr	XDR_FREE=2
84177633Sdfr};
85177633Sdfr
86177633Sdfr/*
87177633Sdfr * This is the number of bytes per unit of external data.
88177633Sdfr */
89177633Sdfr#define BYTES_PER_XDR_UNIT	(4)
90177633Sdfr#define RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
91177633Sdfr		    * BYTES_PER_XDR_UNIT)
92177633Sdfr
93177633Sdfr/*
94177633Sdfr * The XDR handle.
95177633Sdfr * Contains operation which is being applied to the stream,
96177633Sdfr * an operations vector for the particular implementation (e.g. see xdr_mem.c),
97177633Sdfr * and two private fields for the use of the particular implementation.
98177633Sdfr */
99240542Spfgtypedef struct XDR {
100177633Sdfr	enum xdr_op	x_op;		/* operation; fast additional param */
101177633Sdfr	const struct xdr_ops {
102177633Sdfr		/* get a long from underlying stream */
103240542Spfg		bool_t	(*x_getlong)(struct XDR *, long *);
104177633Sdfr		/* put a long to " */
105240542Spfg		bool_t	(*x_putlong)(struct XDR *, const long *);
106177633Sdfr		/* get some bytes from " */
107240542Spfg		bool_t	(*x_getbytes)(struct XDR *, char *, u_int);
108177633Sdfr		/* put some bytes to " */
109240542Spfg		bool_t	(*x_putbytes)(struct XDR *, const char *, u_int);
110177633Sdfr		/* returns bytes off from beginning */
111240542Spfg		u_int	(*x_getpostn)(struct XDR *);
112177633Sdfr		/* lets you reposition the stream */
113240542Spfg		bool_t  (*x_setpostn)(struct XDR *, u_int);
114177633Sdfr		/* buf quick ptr to buffered data */
115240542Spfg		int32_t *(*x_inline)(struct XDR *, u_int);
116177633Sdfr		/* free privates of this xdr_stream */
117240542Spfg		void	(*x_destroy)(struct XDR *);
118240542Spfg		bool_t	(*x_control)(struct XDR *, int, void *);
119177633Sdfr	} *x_ops;
120177633Sdfr	char *	 	x_public;	/* users' data */
121177633Sdfr	void *		x_private;	/* pointer to private data */
122177633Sdfr	char * 		x_base;		/* private used for position info */
123177633Sdfr	u_int		x_handy;	/* extra private word */
124177633Sdfr} XDR;
125177633Sdfr
126177633Sdfr/*
127177633Sdfr * A xdrproc_t exists for each data type which is to be encoded or decoded.
128177633Sdfr *
129177633Sdfr * The second argument to the xdrproc_t is a pointer to an opaque pointer.
130177633Sdfr * The opaque pointer generally points to a structure of the data type
131177633Sdfr * to be decoded.  If this pointer is 0, then the type routines should
132177633Sdfr * allocate dynamic storage of the appropriate size and return it.
133177633Sdfr */
134177633Sdfr#ifdef _KERNEL
135177633Sdfrtypedef	bool_t (*xdrproc_t)(XDR *, void *, ...);
136177633Sdfr#else
137177633Sdfr/*
138177633Sdfr * XXX can't actually prototype it, because some take three args!!!
139177633Sdfr */
140177633Sdfrtypedef	bool_t (*xdrproc_t)(XDR *, ...);
141177633Sdfr#endif
142177633Sdfr
143177633Sdfr/*
144177633Sdfr * Operations defined on a XDR handle
145177633Sdfr *
146177633Sdfr * XDR		*xdrs;
147177633Sdfr * long		*longp;
148177633Sdfr * char *	 addr;
149177633Sdfr * u_int	 len;
150177633Sdfr * u_int	 pos;
151177633Sdfr */
152177633Sdfr#define XDR_GETLONG(xdrs, longp)			\
153177633Sdfr	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
154177633Sdfr#define xdr_getlong(xdrs, longp)			\
155177633Sdfr	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
156177633Sdfr
157177633Sdfr#define XDR_PUTLONG(xdrs, longp)			\
158177633Sdfr	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
159177633Sdfr#define xdr_putlong(xdrs, longp)			\
160177633Sdfr	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
161177633Sdfr
162177633Sdfrstatic __inline int
163177633Sdfrxdr_getint32(XDR *xdrs, int32_t *ip)
164177633Sdfr{
165177633Sdfr	long l;
166177633Sdfr
167177633Sdfr	if (!xdr_getlong(xdrs, &l))
168177633Sdfr		return (FALSE);
169177633Sdfr	*ip = (int32_t)l;
170177633Sdfr	return (TRUE);
171177633Sdfr}
172177633Sdfr
173177633Sdfrstatic __inline int
174177633Sdfrxdr_putint32(XDR *xdrs, int32_t *ip)
175177633Sdfr{
176177633Sdfr	long l;
177177633Sdfr
178177633Sdfr	l = (long)*ip;
179177633Sdfr	return xdr_putlong(xdrs, &l);
180177633Sdfr}
181177633Sdfr
182177633Sdfr#define XDR_GETINT32(xdrs, int32p)	xdr_getint32(xdrs, int32p)
183177633Sdfr#define XDR_PUTINT32(xdrs, int32p)	xdr_putint32(xdrs, int32p)
184177633Sdfr
185177633Sdfr#define XDR_GETBYTES(xdrs, addr, len)			\
186177633Sdfr	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
187177633Sdfr#define xdr_getbytes(xdrs, addr, len)			\
188177633Sdfr	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
189177633Sdfr
190177633Sdfr#define XDR_PUTBYTES(xdrs, addr, len)			\
191177633Sdfr	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
192177633Sdfr#define xdr_putbytes(xdrs, addr, len)			\
193177633Sdfr	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
194177633Sdfr
195177633Sdfr#define XDR_GETPOS(xdrs)				\
196177633Sdfr	(*(xdrs)->x_ops->x_getpostn)(xdrs)
197177633Sdfr#define xdr_getpos(xdrs)				\
198177633Sdfr	(*(xdrs)->x_ops->x_getpostn)(xdrs)
199177633Sdfr
200177633Sdfr#define XDR_SETPOS(xdrs, pos)				\
201177633Sdfr	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
202177633Sdfr#define xdr_setpos(xdrs, pos)				\
203177633Sdfr	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
204177633Sdfr
205177633Sdfr#define	XDR_INLINE(xdrs, len)				\
206177633Sdfr	(*(xdrs)->x_ops->x_inline)(xdrs, len)
207177633Sdfr#define	xdr_inline(xdrs, len)				\
208177633Sdfr	(*(xdrs)->x_ops->x_inline)(xdrs, len)
209177633Sdfr
210177633Sdfr#define	XDR_DESTROY(xdrs)				\
211177633Sdfr	if ((xdrs)->x_ops->x_destroy) 			\
212177633Sdfr		(*(xdrs)->x_ops->x_destroy)(xdrs)
213177633Sdfr#define	xdr_destroy(xdrs)				\
214177633Sdfr	if ((xdrs)->x_ops->x_destroy) 			\
215177633Sdfr		(*(xdrs)->x_ops->x_destroy)(xdrs)
216177633Sdfr
217177633Sdfr#define XDR_CONTROL(xdrs, req, op)			\
218193128Skmacy	(((xdrs)->x_ops->x_control == NULL) ? (FALSE) :	\
219193128Skmacy		(*(xdrs)->x_ops->x_control)(xdrs, req, op))
220177633Sdfr#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op)
221177633Sdfr
222177633Sdfr/*
223177633Sdfr * Solaris strips the '_t' from these types -- not sure why.
224177633Sdfr * But, let's be compatible.
225177633Sdfr */
226177633Sdfr#define xdr_rpcvers(xdrs, versp) xdr_uint32_t(xdrs, versp)
227177633Sdfr#define xdr_rpcprog(xdrs, progp) xdr_uint32_t(xdrs, progp)
228177633Sdfr#define xdr_rpcproc(xdrs, procp) xdr_uint32_t(xdrs, procp)
229177633Sdfr#define xdr_rpcprot(xdrs, protp) xdr_uint32_t(xdrs, protp)
230177633Sdfr#define xdr_rpcport(xdrs, portp) xdr_uint32_t(xdrs, portp)
231177633Sdfr
232177633Sdfr/*
233177633Sdfr * Support struct for discriminated unions.
234177633Sdfr * You create an array of xdrdiscrim structures, terminated with
235177633Sdfr * an entry with a null procedure pointer.  The xdr_union routine gets
236177633Sdfr * the discriminant value and then searches the array of structures
237177633Sdfr * for a matching value.  If a match is found the associated xdr routine
238177633Sdfr * is called to handle that part of the union.  If there is
239177633Sdfr * no match, then a default routine may be called.
240177633Sdfr * If there is no match and no default routine it is an error.
241177633Sdfr */
242177633Sdfr#define NULL_xdrproc_t ((xdrproc_t)0)
243177633Sdfrstruct xdr_discrim {
244177633Sdfr	int	value;
245177633Sdfr	xdrproc_t proc;
246177633Sdfr};
247177633Sdfr
248177633Sdfr/*
249177633Sdfr * In-line routines for fast encode/decode of primitive data types.
250177633Sdfr * Caveat emptor: these use single memory cycles to get the
251177633Sdfr * data from the underlying buffer, and will fail to operate
252177633Sdfr * properly if the data is not aligned.  The standard way to use these
253177633Sdfr * is to say:
254177633Sdfr *	if ((buf = XDR_INLINE(xdrs, count)) == NULL)
255177633Sdfr *		return (FALSE);
256177633Sdfr *	<<< macro calls >>>
257177633Sdfr * where ``count'' is the number of bytes of data occupied
258177633Sdfr * by the primitive data types.
259177633Sdfr *
260177633Sdfr * N.B. and frozen for all time: each data type here uses 4 bytes
261177633Sdfr * of external representation.
262177633Sdfr */
263177633Sdfr#define IXDR_GET_INT32(buf)		((int32_t)__ntohl((uint32_t)*(buf)++))
264177633Sdfr#define IXDR_PUT_INT32(buf, v)		(*(buf)++ =(int32_t)__htonl((uint32_t)v))
265177633Sdfr#define IXDR_GET_U_INT32(buf)		((uint32_t)IXDR_GET_INT32(buf))
266177633Sdfr#define IXDR_PUT_U_INT32(buf, v)	IXDR_PUT_INT32((buf), ((int32_t)(v)))
267177633Sdfr
268177633Sdfr#define IXDR_GET_UINT32(buf)		((uint32_t)IXDR_GET_INT32(buf))
269177633Sdfr#define IXDR_PUT_UINT32(buf, v)		IXDR_PUT_INT32((buf), ((int32_t)(v)))
270177633Sdfr
271177633Sdfr#define IXDR_GET_LONG(buf)		((long)__ntohl((uint32_t)*(buf)++))
272177633Sdfr#define IXDR_PUT_LONG(buf, v)		(*(buf)++ =(int32_t)__htonl((uint32_t)v))
273177633Sdfr
274177633Sdfr#define IXDR_GET_BOOL(buf)		((bool_t)IXDR_GET_LONG(buf))
275177633Sdfr#define IXDR_GET_ENUM(buf, t)		((t)IXDR_GET_LONG(buf))
276177633Sdfr#define IXDR_GET_U_LONG(buf)		((u_long)IXDR_GET_LONG(buf))
277177633Sdfr#define IXDR_GET_SHORT(buf)		((short)IXDR_GET_LONG(buf))
278177633Sdfr#define IXDR_GET_U_SHORT(buf)		((u_short)IXDR_GET_LONG(buf))
279177633Sdfr
280177633Sdfr#define IXDR_PUT_BOOL(buf, v)		IXDR_PUT_LONG((buf), (v))
281177633Sdfr#define IXDR_PUT_ENUM(buf, v)		IXDR_PUT_LONG((buf), (v))
282177633Sdfr#define IXDR_PUT_U_LONG(buf, v)		IXDR_PUT_LONG((buf), (v))
283177633Sdfr#define IXDR_PUT_SHORT(buf, v)		IXDR_PUT_LONG((buf), (v))
284177633Sdfr#define IXDR_PUT_U_SHORT(buf, v)	IXDR_PUT_LONG((buf), (v))
285177633Sdfr
286177633Sdfr/*
287177633Sdfr * These are the "generic" xdr routines.
288177633Sdfr */
289177633Sdfr__BEGIN_DECLS
290177633Sdfrextern bool_t	xdr_void(void);
291177633Sdfrextern bool_t	xdr_int(XDR *, int *);
292177633Sdfrextern bool_t	xdr_u_int(XDR *, u_int *);
293177633Sdfrextern bool_t	xdr_long(XDR *, long *);
294177633Sdfrextern bool_t	xdr_u_long(XDR *, u_long *);
295177633Sdfrextern bool_t	xdr_short(XDR *, short *);
296177633Sdfrextern bool_t	xdr_u_short(XDR *, u_short *);
297177633Sdfrextern bool_t	xdr_int16_t(XDR *, int16_t *);
298177633Sdfrextern bool_t	xdr_uint16_t(XDR *, uint16_t *);
299177633Sdfrextern bool_t	xdr_int32_t(XDR *, int32_t *);
300177633Sdfrextern bool_t	xdr_uint32_t(XDR *, uint32_t *);
301177633Sdfrextern bool_t	xdr_int64_t(XDR *, int64_t *);
302177633Sdfrextern bool_t	xdr_uint64_t(XDR *, uint64_t *);
303177633Sdfrextern bool_t	xdr_bool(XDR *, bool_t *);
304177633Sdfrextern bool_t	xdr_enum(XDR *, enum_t *);
305177633Sdfrextern bool_t	xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t);
306177633Sdfrextern bool_t	xdr_bytes(XDR *, char **, u_int *, u_int);
307177633Sdfrextern bool_t	xdr_opaque(XDR *, char *, u_int);
308177633Sdfrextern bool_t	xdr_string(XDR *, char **, u_int);
309177633Sdfrextern bool_t	xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t);
310177633Sdfrextern bool_t	xdr_char(XDR *, char *);
311177633Sdfrextern bool_t	xdr_u_char(XDR *, u_char *);
312177633Sdfrextern bool_t	xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);
313177633Sdfrextern bool_t	xdr_float(XDR *, float *);
314177633Sdfrextern bool_t	xdr_double(XDR *, double *);
315177633Sdfrextern bool_t	xdr_quadruple(XDR *, long double *);
316177633Sdfrextern bool_t	xdr_reference(XDR *, char **, u_int, xdrproc_t);
317177633Sdfrextern bool_t	xdr_pointer(XDR *, char **, u_int, xdrproc_t);
318177633Sdfrextern bool_t	xdr_wrapstring(XDR *, char **);
319177633Sdfrextern void	xdr_free(xdrproc_t, void *);
320177633Sdfrextern bool_t	xdr_hyper(XDR *, quad_t *);
321177633Sdfrextern bool_t	xdr_u_hyper(XDR *, u_quad_t *);
322177633Sdfrextern bool_t	xdr_longlong_t(XDR *, quad_t *);
323177633Sdfrextern bool_t	xdr_u_longlong_t(XDR *, u_quad_t *);
324177633Sdfrextern unsigned long xdr_sizeof(xdrproc_t func, void *data);
325177633Sdfr__END_DECLS
326177633Sdfr
327177633Sdfr/*
328177633Sdfr * Common opaque bytes objects used by many rpc protocols;
329177633Sdfr * declared here due to commonality.
330177633Sdfr */
331177633Sdfr#define MAX_NETOBJ_SZ 1024
332177633Sdfrstruct netobj {
333177633Sdfr	u_int	n_len;
334177633Sdfr	char	*n_bytes;
335177633Sdfr};
336177633Sdfrtypedef struct netobj netobj;
337177633Sdfrextern bool_t   xdr_netobj(XDR *, struct netobj *);
338177633Sdfr
339177633Sdfr/*
340192971Skmacy * These are XDR control operators
341192971Skmacy */
342192971Skmacy
343192971Skmacy#define	XDR_GET_BYTES_AVAIL 	1
344192971Skmacy#define	XDR_PEEK		2
345192971Skmacy#define	XDR_SKIPBYTES		3
346192971Skmacy
347192971Skmacystruct xdr_bytesrec {
348192971Skmacy	bool_t xc_is_last_record;
349192971Skmacy	size_t xc_num_avail;
350192971Skmacy};
351192971Skmacy
352192971Skmacytypedef struct xdr_bytesrec xdr_bytesrec;
353192971Skmacy
354192971Skmacy
355192971Skmacy/*
356177633Sdfr * These are the public routines for the various implementations of
357177633Sdfr * xdr streams.
358177633Sdfr */
359177633Sdfr__BEGIN_DECLS
360177633Sdfr/* XDR using memory buffers */
361177633Sdfrextern void   xdrmem_create(XDR *, char *, u_int, enum xdr_op);
362177633Sdfr
363177633Sdfr/* XDR using mbufs */
364177633Sdfrstruct mbuf;
365177633Sdfrextern void   xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op);
366184588Sdfrextern void   xdrmbuf_append(XDR *, struct mbuf *);
367184588Sdfrextern struct mbuf * xdrmbuf_getall(XDR *);
368177633Sdfr
369177633Sdfr/* XDR pseudo records for tcp */
370177633Sdfrextern void   xdrrec_create(XDR *, u_int, u_int, void *,
371177633Sdfr			    int (*)(void *, void *, int),
372177633Sdfr			    int (*)(void *, void *, int));
373177633Sdfr
374177633Sdfr/* make end of xdr record */
375177633Sdfrextern bool_t xdrrec_endofrecord(XDR *, int);
376177633Sdfr
377177633Sdfr/* move to beginning of next record */
378177633Sdfrextern bool_t xdrrec_skiprecord(XDR *);
379177633Sdfr
380177633Sdfr/* true if no more input */
381177633Sdfrextern bool_t xdrrec_eof(XDR *);
382177633Sdfrextern u_int xdrrec_readbytes(XDR *, caddr_t, u_int);
383177633Sdfr__END_DECLS
384177633Sdfr
385177633Sdfr#endif /* !_KRPC_XDR_H */
386