1 /* Copyright (c) 2010, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /**
24   @file windeps/sunrpc/rpc/xdr.h
25   External Data Representation Serialization Routines.
26 */
27 
28 #ifndef _RPC_XDR_H
29 #define _RPC_XDR_H 1
30 
31 #if !defined(WIN32) && !defined(WIN64)
32 #include <features.h>
33 #endif
34 
35 #include <sys/types.h>
36 #include <rpc/types.h>
37 
38 /* We need FILE.  */
39 #include <stdio.h>
40 
41 
42 __BEGIN_DECLS
43 
44 /*
45  * XDR provides a conventional way for converting between C data
46  * types and an external bit-string representation.  Library supplied
47  * routines provide for the conversion on built-in C data types.  These
48  * routines and utility routines defined here are used to help implement
49  * a type encode/decode routine for each user-defined type.
50  *
51  * Each data type provides a single procedure which takes two arguments:
52  *
53  *      bool_t
54  *      xdrproc(xdrs, argresp)
55  *              XDR *xdrs;
56  *              <type> *argresp;
57  *
58  * xdrs is an instance of a XDR handle, to which or from which the data
59  * type is to be converted.  argresp is a pointer to the structure to be
60  * converted.  The XDR handle contains an operation field which indicates
61  * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
62  *
63  * XDR_DECODE may allocate space if the pointer argresp is null.  This
64  * data can be freed with the XDR_FREE operation.
65  *
66  * We write only one procedure per data type to make it easy
67  * to keep the encode and decode procedures for a data type consistent.
68  * In many cases the same code performs all operations on a user defined type,
69  * because all the hard work is done in the component type routines.
70  * decode as a series of calls on the nested data types.
71  */
72 
73 /*
74  * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
75  * stream.  XDR_DECODE causes the type to be extracted from the stream.
76  * XDR_FREE can be used to release the space allocated by an XDR_DECODE
77  * request.
78  */
79 enum xdr_op {
80   XDR_ENCODE = 0,
81   XDR_DECODE = 1,
82   XDR_FREE = 2
83 };
84 
85 /*
86  * This is the number of bytes per unit of external data.
87  */
88 #define BYTES_PER_XDR_UNIT	(4)
89 /*
90  * This only works if the above is a power of 2.  But it's defined to be
91  * 4 by the appropriate RFCs.  So it will work.  And it's normally quicker
92  * than the old routine.
93  */
94 #if 1
95 #define RNDUP(x)  (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1))
96 #else /* this is the old routine */
97 #define RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
98 		    * BYTES_PER_XDR_UNIT)
99 #endif
100 
101 /*
102  * The XDR handle.
103  * Contains operation which is being applied to the stream,
104  * an operations vector for the particular implementation (e.g. see xdr_mem.c),
105  * and two private fields for the use of the particular implementation.
106  */
107 typedef struct XDR XDR;
108 struct XDR
109   {
110     enum xdr_op x_op;		/* operation; fast additional param */
111     struct xdr_ops
112       {
113 	bool_t (*x_getlong) (XDR *__xdrs, long *__lp);
114 	/* get a long from underlying stream */
115 	bool_t (*x_putlong) (XDR *__xdrs, __const long *__lp);
116 	/* put a long to " */
117 	bool_t (*x_getbytes) (XDR *__xdrs, caddr_t __addr, u_int __len);
118 	/* get some bytes from " */
119 	bool_t (*x_putbytes) (XDR *__xdrs, __const char *__addr, u_int __len);
120 	/* put some bytes to " */
121 	u_int (*x_getpostn) (__const XDR *__xdrs);
122 	/* returns bytes off from beginning */
123 	bool_t (*x_setpostn) (XDR *__xdrs, u_int __pos);
124 	/* lets you reposition the stream */
125 	int32_t *(*x_inline) (XDR *__xdrs, u_int __len);
126 	/* buf quick ptr to buffered data */
127 	void (*x_destroy) (XDR *__xdrs);
128 	/* free privates of this xdr_stream */
129 	bool_t (*x_getint32) (XDR *__xdrs, int32_t *__ip);
130 	/* get a int from underlying stream */
131 	bool_t (*x_putint32) (XDR *__xdrs, __const int32_t *__ip);
132 	/* put a int to " */
133       }
134      *x_ops;
135     caddr_t x_public;		/* users' data */
136     caddr_t x_private;		/* pointer to private data */
137     caddr_t x_base;		/* private used for position info */
138     u_int x_handy;		/* extra private word */
139   };
140 
141 /*
142  * A xdrproc_t exists for each data type which is to be encoded or decoded.
143  *
144  * The second argument to the xdrproc_t is a pointer to an opaque pointer.
145  * The opaque pointer generally points to a structure of the data type
146  * to be decoded.  If this pointer is 0, then the type routines should
147  * allocate dynamic storage of the appropriate size and return it.
148  * bool_t       (*xdrproc_t)(XDR *, caddr_t *);
149  */
150 typedef bool_t (*xdrproc_t) (XDR *, void *,...);
151 
152 
153 /*
154  * Operations defined on a XDR handle
155  *
156  * XDR          *xdrs;
157  * int32_t      *int32p;
158  * long         *longp;
159  * caddr_t       addr;
160  * u_int         len;
161  * u_int         pos;
162  */
163 #define XDR_GETINT32(xdrs, int32p)                      \
164         (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
165 #define xdr_getint32(xdrs, int32p)                      \
166         (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
167 
168 #define XDR_PUTINT32(xdrs, int32p)                      \
169         (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
170 #define xdr_putint32(xdrs, int32p)                      \
171         (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
172 
173 #define XDR_GETLONG(xdrs, longp)			\
174 	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
175 #define xdr_getlong(xdrs, longp)			\
176 	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
177 
178 #define XDR_PUTLONG(xdrs, longp)			\
179 	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
180 #define xdr_putlong(xdrs, longp)			\
181 	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
182 
183 #define XDR_GETBYTES(xdrs, addr, len)			\
184 	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
185 #define xdr_getbytes(xdrs, addr, len)			\
186 	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
187 
188 #define XDR_PUTBYTES(xdrs, addr, len)			\
189 	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
190 #define xdr_putbytes(xdrs, addr, len)			\
191 	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
192 
193 #define XDR_GETPOS(xdrs)				\
194 	(*(xdrs)->x_ops->x_getpostn)(xdrs)
195 #define xdr_getpos(xdrs)				\
196 	(*(xdrs)->x_ops->x_getpostn)(xdrs)
197 
198 #define XDR_SETPOS(xdrs, pos)				\
199 	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
200 #define xdr_setpos(xdrs, pos)				\
201 	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
202 
203 #define	XDR_INLINE(xdrs, len)				\
204 	(*(xdrs)->x_ops->x_inline)(xdrs, len)
205 #define	xdr_inline(xdrs, len)				\
206 	(*(xdrs)->x_ops->x_inline)(xdrs, len)
207 
208 #define	XDR_DESTROY(xdrs)					\
209 	do {							\
210 		if ((xdrs)->x_ops->x_destroy)			\
211 			(*(xdrs)->x_ops->x_destroy)(xdrs);	\
212 	} while (0)
213 #define	xdr_destroy(xdrs)					\
214 	do {							\
215 		if ((xdrs)->x_ops->x_destroy)			\
216 			(*(xdrs)->x_ops->x_destroy)(xdrs);	\
217 	} while (0)
218 
219 /*
220  * Support struct for discriminated unions.
221  * You create an array of xdrdiscrim structures, terminated with
222  * a entry with a null procedure pointer.  The xdr_union routine gets
223  * the discriminant value and then searches the array of structures
224  * for a matching value.  If a match is found the associated xdr routine
225  * is called to handle that part of the union.  If there is
226  * no match, then a default routine may be called.
227  * If there is no match and no default routine it is an error.
228  */
229 #define NULL_xdrproc_t ((xdrproc_t)0)
230 struct xdr_discrim
231 {
232   int value;
233   xdrproc_t proc;
234 };
235 
236 /*
237  * Inline routines for fast encode/decode of primitive data types.
238  * Caveat emptor: these use single memory cycles to get the
239  * data from the underlying buffer, and will fail to operate
240  * properly if the data is not aligned.  The standard way to use these
241  * is to say:
242  *      if ((buf = XDR_INLINE(xdrs, count)) == NULL)
243  *              return (FALSE);
244  *      <<< macro calls >>>
245  * where ``count'' is the number of bytes of data occupied
246  * by the primitive data types.
247  *
248  * N.B. and frozen for all time: each data type here uses 4 bytes
249  * of external representation.
250  */
251 
252 #define IXDR_GET_INT32(buf)           ((int32_t)ntohl((uint32_t)*(buf)++))
253 #define IXDR_PUT_INT32(buf, v)        (*(buf)++ = (int32_t)htonl((uint32_t)(v)))
254 #define IXDR_GET_U_INT32(buf)         ((uint32_t)IXDR_GET_INT32(buf))
255 #define IXDR_PUT_U_INT32(buf, v)      IXDR_PUT_INT32(buf, (int32_t)(v))
256 
257 /* WARNING: The IXDR_*_LONG defines are removed by Sun for new platforms
258  * and shouldn't be used any longer. Code which use this defines or longs
259  * in the RPC code will not work on 64bit Solaris platforms !
260  */
261 #define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf))
262 #define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v)))
263 #define IXDR_GET_U_LONG(buf)	      ((u_long)IXDR_GET_LONG(buf))
264 #define IXDR_PUT_U_LONG(buf, v)	      IXDR_PUT_LONG(buf, (long)(v))
265 
266 
267 #define IXDR_GET_BOOL(buf)            ((bool_t)IXDR_GET_LONG(buf))
268 #define IXDR_GET_ENUM(buf, t)         ((t)IXDR_GET_LONG(buf))
269 #define IXDR_GET_SHORT(buf)           ((short)IXDR_GET_LONG(buf))
270 #define IXDR_GET_U_SHORT(buf)         ((u_short)IXDR_GET_LONG(buf))
271 
272 #define IXDR_PUT_BOOL(buf, v)         IXDR_PUT_LONG(buf, (long)(v))
273 #define IXDR_PUT_ENUM(buf, v)         IXDR_PUT_LONG(buf, (long)(v))
274 #define IXDR_PUT_SHORT(buf, v)        IXDR_PUT_LONG(buf, (long)(v))
275 #define IXDR_PUT_U_SHORT(buf, v)      IXDR_PUT_LONG(buf, (long)(v))
276 
277 /*
278  * These are the "generic" xdr routines.
279  * None of these can have const applied because it's not possible to
280  * know whether the call is a read or a write to the passed parameter
281  * also, the XDR structure is always updated by some of these calls.
282  */
283 extern bool_t xdr_void (void) __THROW;
284 extern bool_t xdr_short (XDR *__xdrs, short *__sp) __THROW;
285 extern bool_t xdr_u_short (XDR *__xdrs, u_short *__usp) __THROW;
286 extern bool_t xdr_int (XDR *__xdrs, int *__ip) __THROW;
287 extern bool_t xdr_u_int (XDR *__xdrs, u_int *__up) __THROW;
288 extern bool_t xdr_long (XDR *__xdrs, long *__lp) __THROW;
289 extern bool_t xdr_u_long (XDR *__xdrs, u_long *__ulp) __THROW;
290 extern bool_t xdr_hyper (XDR *__xdrs, quad_t *__llp) __THROW;
291 extern bool_t xdr_u_hyper (XDR *__xdrs, u_quad_t *__ullp) __THROW;
292 extern bool_t xdr_longlong_t (XDR *__xdrs, quad_t *__llp) __THROW;
293 extern bool_t xdr_u_longlong_t (XDR *__xdrs, u_quad_t *__ullp) __THROW;
294 extern bool_t xdr_int8_t (XDR *__xdrs, int8_t *__ip) __THROW;
295 extern bool_t xdr_uint8_t (XDR *__xdrs, uint8_t *__up) __THROW;
296 extern bool_t xdr_int16_t (XDR *__xdrs, int16_t *__ip) __THROW;
297 extern bool_t xdr_uint16_t (XDR *__xdrs, uint16_t *__up) __THROW;
298 extern bool_t xdr_int32_t (XDR *__xdrs, int32_t *__ip) __THROW;
299 extern bool_t xdr_uint32_t (XDR *__xdrs, uint32_t *__up) __THROW;
300 extern bool_t xdr_int64_t (XDR *__xdrs, int64_t *__ip) __THROW;
301 extern bool_t xdr_uint64_t (XDR *__xdrs, uint64_t *__up) __THROW;
302 extern bool_t xdr_quad_t (XDR *__xdrs, quad_t *__ip) __THROW;
303 extern bool_t xdr_u_quad_t (XDR *__xdrs, u_quad_t *__up) __THROW;
304 extern bool_t xdr_bool (XDR *__xdrs, bool_t *__bp) __THROW;
305 extern bool_t xdr_enum (XDR *__xdrs, enum_t *__ep) __THROW;
306 extern bool_t xdr_array (XDR * _xdrs, caddr_t *__addrp, u_int *__sizep,
307 			 u_int __maxsize, u_int __elsize, xdrproc_t __elproc)
308      __THROW;
309 extern bool_t xdr_bytes (XDR *__xdrs, char **__cpp, u_int *__sizep,
310 			 u_int __maxsize) __THROW;
311 extern bool_t xdr_opaque (XDR *__xdrs, caddr_t __cp, u_int __cnt) __THROW;
312 extern bool_t xdr_string (XDR *__xdrs, char **__cpp, u_int __maxsize) __THROW;
313 extern bool_t xdr_union (XDR *__xdrs, enum_t *__dscmp, char *__unp,
314 			 __const struct xdr_discrim *__choices,
315 			 xdrproc_t __dfault) __THROW;
316 extern bool_t xdr_char (XDR *__xdrs, char *__cp) __THROW;
317 extern bool_t xdr_u_char (XDR *__xdrs, u_char *__cp) __THROW;
318 extern bool_t xdr_vector (XDR *__xdrs, char *__basep, u_int __nelem,
319 			  u_int __elemsize, xdrproc_t __xdr_elem) __THROW;
320 extern bool_t xdr_float (XDR *__xdrs, float *__fp) __THROW;
321 extern bool_t xdr_double (XDR *__xdrs, double *__dp) __THROW;
322 extern bool_t xdr_reference (XDR *__xdrs, caddr_t *__xpp, u_int __size,
323 			     xdrproc_t __proc) __THROW;
324 extern bool_t xdr_pointer (XDR *__xdrs, char **__objpp,
325 			   u_int __obj_size, xdrproc_t __xdr_obj) __THROW;
326 extern bool_t xdr_wrapstring (XDR *__xdrs, char **__cpp) __THROW;
327 extern u_long xdr_sizeof (xdrproc_t, void *) __THROW;
328 
329 /*
330  * Common opaque bytes objects used by many rpc protocols;
331  * declared here due to commonality.
332  */
333 #define MAX_NETOBJ_SZ 1024
334 struct netobj
335 {
336   u_int n_len;
337   char *n_bytes;
338 };
339 typedef struct netobj netobj;
340 extern bool_t xdr_netobj (XDR *__xdrs, struct netobj *__np) __THROW;
341 
342 /*
343  * These are the public routines for the various implementations of
344  * xdr streams.
345  */
346 
347 /* XDR using memory buffers */
348 extern void xdrmem_create (XDR *__xdrs, __const caddr_t __addr,
349 			   u_int __size, enum xdr_op __xop) __THROW;
350 
351 /* XDR using stdio library */
352 extern void xdrstdio_create (XDR *__xdrs, FILE *__file, enum xdr_op __xop)
353      __THROW;
354 
355 /* XDR pseudo records for tcp */
356 extern void xdrrec_create (XDR *__xdrs, u_int __sendsize,
357 			   u_int __recvsize, caddr_t __tcp_handle,
358 			   int (*__readit) (char *, char *, int),
359 			   int (*__writeit) (char *, char *, int)) __THROW;
360 
361 /* make end of xdr record */
362 extern bool_t xdrrec_endofrecord (XDR *__xdrs, bool_t __sendnow) __THROW;
363 
364 /* move to beginning of next record */
365 extern bool_t xdrrec_skiprecord (XDR *__xdrs) __THROW;
366 
367 /* true if no more input */
368 extern bool_t xdrrec_eof (XDR *__xdrs) __THROW;
369 
370 /* free memory buffers for xdr */
371 extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW;
372 
373 __END_DECLS
374 
375 #endif /* rpc/xdr.h */
376