1 /*********************************************************************
2  * RPC for the Windows NT Operating System
3  * 1993 by Martin F. Gergeleit
4  * Users may use, copy or modify Sun RPC for the Windows NT Operating
5  * System according to the Sun copyright below.
6  *
7  * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO
8  * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE
9  * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
10  *********************************************************************/
11 
12 /* @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC */
13 /*
14  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
15  * unrestricted use provided that this legend is included on all tape
16  * media and as a part of the software program in whole or part.  Users
17  * may copy or modify Sun RPC without charge, but are not authorized
18  * to license or distribute it to anyone else except as part of a product or
19  * program developed by the user.
20  *
21  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
22  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
24  *
25  * Sun RPC is provided with no support and without any obligation on the
26  * part of Sun Microsystems, Inc. to assist in its use, correction,
27  * modification or enhancement.
28  *
29  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
30  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
31  * OR ANY PART THEREOF.
32  *
33  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
34  * or profits or other special, indirect and consequential damages, even if
35  * Sun has been advised of the possibility of such damages.
36  *
37  * Sun Microsystems, Inc.
38  * 2550 Garcia Avenue
39  * Mountain View, California  94043
40  */
41 #if !defined(lint) && defined(SCCSIDS)
42 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
43 #endif
44 
45 /*
46  * xdr.c, Generic XDR routines implementation.
47  *
48  * Copyright (C) 1986, Sun Microsystems, Inc.
49  *
50  * These are the "generic" xdr routines used to serialize and de-serialize
51  * most common data items.  See xdr.h for more info on the interface to
52  * xdr.
53  */
54 
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h> /* strlen */
58 #include <stdint.h>
59 
60 #include <rpc/types.h>
61 #include <rpc/xdr.h>
62 
63 /* R-specific */
64 void REprintf(char*, ...);
65 #define fprintf(a, b) REprintf(b)
66 
67 #ifdef UNUSED
68 /*
69  * constants specific to the xdr "protocol"
70  */
71 #define XDR_FALSE	((int32_t) 0)
72 #define XDR_TRUE	((int32_t) 1)
73 #define LASTUNSIGNED	((u_int) 0-1)
74 #endif
75 
76 /*
77  * for unit alignment
78  */
79 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
80 
81 #ifdef UNUSED
82 /*
83  * Free a data structure using XDR
84  * Not a filter, but a convenient utility nonetheless
85  */
86 void
xdr_free(proc,objp)87 xdr_free(proc, objp)
88 	xdrproc_t proc;
89 	char *objp;
90 {
91 	XDR x;
92 
93 	x.x_op = XDR_FREE;
94 	(*proc)(&x, objp);
95 }
96 #endif
97 
98 #ifdef UNUSED
99 /*
100  * XDR nothing
101  */
102 bool_t
xdr_void()103 xdr_void(/* xdrs, addr */)
104 	/* XDR *xdrs; */
105 	/* caddr_t addr; */
106 {
107 
108 	return (TRUE);
109 }
110 #endif
111 
112 /*
113  * XDR integers: always 32-bit in R
114  */
115 bool_t
xdr_int(xdrs,ip)116 xdr_int(xdrs, ip)
117 	XDR *xdrs;
118 	int *ip;
119 {
120 //    return (xdr_long(xdrs, (int32_t *)ip));
121 
122 	if (xdrs->x_op == XDR_DECODE)
123 		return (XDR_GETLONG(xdrs, (int32_t *)ip));
124 	if (xdrs->x_op == XDR_ENCODE)
125 		return (XDR_PUTLONG(xdrs, (int32_t *)ip));
126 	if (xdrs->x_op == XDR_FREE)
127 		return (TRUE);
128 	return (FALSE);
129 }
130 
131 /*
132  * XDR unsigned integers: always 32-bit in R
133  */
134 bool_t
xdr_u_int(xdrs,up)135 xdr_u_int(xdrs, up)
136 	XDR *xdrs;
137 	u_int *up;
138 {
139 //    return (xdr_u_long(xdrs, (uint32_t *)up));
140 
141 	if (xdrs->x_op == XDR_DECODE)
142 		return (XDR_GETLONG(xdrs, (int32_t *)up));
143 	if (xdrs->x_op == XDR_ENCODE)
144 		return (XDR_PUTLONG(xdrs, (int32_t *)up));
145 	if (xdrs->x_op == XDR_FREE)
146 		return (TRUE);
147 	return (FALSE);
148 
149 }
150 
151 #ifdef UNUSED
152 /*
153  * XDR long integers
154  * same as xdr_u_long - open coded to save a proc call!
155  */
156 bool_t
xdr_long(xdrs,lp)157 xdr_long(xdrs, lp)
158 	register XDR *xdrs;
159 	int32_t *lp;
160 {
161 
162 	if (xdrs->x_op == XDR_ENCODE)
163 		return (XDR_PUTLONG(xdrs, lp));
164 
165 	if (xdrs->x_op == XDR_DECODE)
166 		return (XDR_GETLONG(xdrs, lp));
167 
168 	if (xdrs->x_op == XDR_FREE)
169 		return (TRUE);
170 
171 	return (FALSE);
172 }
173 
174 /*
175  * XDR unsigned long integers
176  * same as xdr_long - open coded to save a proc call!
177  */
178 bool_t
xdr_u_long(xdrs,ulp)179 xdr_u_long(xdrs, ulp)
180 	register XDR *xdrs;
181 	uint32_t *ulp;
182 {
183 
184 	if (xdrs->x_op == XDR_DECODE)
185 		return (XDR_GETLONG(xdrs, (int32_t *)ulp));
186 	if (xdrs->x_op == XDR_ENCODE)
187 		return (XDR_PUTLONG(xdrs, (int32_t *)ulp));
188 	if (xdrs->x_op == XDR_FREE)
189 		return (TRUE);
190 	return (FALSE);
191 }
192 
193 /*
194  * XDR short integers
195  */
196 bool_t
xdr_short(xdrs,sp)197 xdr_short(xdrs, sp)
198 	register XDR *xdrs;
199 	short *sp;
200 {
201 	int32_t l;
202 
203 	switch (xdrs->x_op) {
204 
205 	case XDR_ENCODE:
206 		l = (int32_t) *sp;
207 		return (XDR_PUTLONG(xdrs, &l));
208 
209 	case XDR_DECODE:
210 		if (!XDR_GETLONG(xdrs, &l)) {
211 			return (FALSE);
212 		}
213 		*sp = (short) l;
214 		return (TRUE);
215 
216 	case XDR_FREE:
217 		return (TRUE);
218 	}
219 	return (FALSE);
220 }
221 
222 /*
223  * XDR unsigned short integers
224  */
225 bool_t
xdr_u_short(xdrs,usp)226 xdr_u_short(xdrs, usp)
227 	register XDR *xdrs;
228 	u_short *usp;
229 {
230 	uint32_t l;
231 
232 	switch (xdrs->x_op) {
233 
234 	case XDR_ENCODE:
235 		l = (uint32_t) *usp;
236 		return (XDR_PUTLONG(xdrs, &l));
237 
238 	case XDR_DECODE:
239 		if (!XDR_GETLONG(xdrs, &l)) {
240 			return (FALSE);
241 		}
242 		*usp = (u_short) l;
243 		return (TRUE);
244 
245 	case XDR_FREE:
246 		return (TRUE);
247 	}
248 	return (FALSE);
249 }
250 
251 /*
252  * XDR a char
253  */
254 bool_t
xdr_char(xdrs,cp)255 xdr_char(xdrs, cp)
256 	XDR *xdrs;
257 	char *cp;
258 {
259 	int i;
260 
261 	i = (*cp);
262 	if (!xdr_int(xdrs, &i)) {
263 		return (FALSE);
264 	}
265 	*cp = i;
266 	return (TRUE);
267 }
268 
269 /*
270  * XDR an unsigned char
271  */
272 bool_t
xdr_u_char(xdrs,cp)273 xdr_u_char(xdrs, cp)
274 	XDR *xdrs;
275 	char *cp;
276 {
277 	u_int u;
278 
279 	u = (*cp);
280 	if (!xdr_u_int(xdrs, &u)) {
281 		return (FALSE);
282 	}
283 	*cp = u;
284 	return (TRUE);
285 }
286 
287 /*
288  * XDR booleans
289  */
290 bool_t
xdr_bool(xdrs,bp)291 xdr_bool(xdrs, bp)
292 	register XDR *xdrs;
293 	bool_t *bp;
294 {
295 	int32_t lb;
296 
297 	switch (xdrs->x_op) {
298 
299 	case XDR_ENCODE:
300 		lb = *bp ? XDR_TRUE : XDR_FALSE;
301 		return (XDR_PUTLONG(xdrs, &lb));
302 
303 	case XDR_DECODE:
304 		if (!XDR_GETLONG(xdrs, &lb)) {
305 			return (FALSE);
306 		}
307 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
308 		return (TRUE);
309 
310 	case XDR_FREE:
311 		return (TRUE);
312 	}
313 	return (FALSE);
314 }
315 
316 /*
317  * XDR enumerations
318  */
319 bool_t
xdr_enum(xdrs,ep)320 xdr_enum(xdrs, ep)
321 	XDR *xdrs;
322 	enum_t *ep;
323 {
324 #ifndef lint
325 	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
326 
327 	/*
328 	 * enums are treated as ints
329 	 */
330 	if (sizeof (enum sizecheck) == sizeof (int32_t)) {
331 		return (xdr_long(xdrs, (int32_t *)ep));
332 	} else if (sizeof (enum sizecheck) == sizeof (short)) {
333 		return (xdr_short(xdrs, (short *)ep));
334 	} else {
335 		return (FALSE);
336 	}
337 #else
338 	(void) (xdr_short(xdrs, (short *)ep));
339 	return (xdr_long(xdrs, (int32_t *)ep));
340 #endif
341 }
342 #endif
343 
344 /*
345  * XDR opaque data
346  * Allows the specification of a fixed size sequence of opaque bytes.
347  * cp points to the opaque object and cnt gives the byte length.
348  */
349 bool_t
xdr_opaque(xdrs,cp,cnt)350 xdr_opaque(xdrs, cp, cnt)
351 	register XDR *xdrs;
352 	caddr_t cp;
353 	register u_int cnt;
354 {
355 	register u_int rndup;
356 	static int crud[BYTES_PER_XDR_UNIT];
357 
358 	/*
359 	 * if no data we are done
360 	 */
361 	if (cnt == 0)
362 		return (TRUE);
363 
364 	/*
365 	 * round byte count to full xdr units
366 	 */
367 	rndup = cnt % BYTES_PER_XDR_UNIT;
368 	if (rndup > 0)
369 		rndup = BYTES_PER_XDR_UNIT - rndup;
370 
371 	if (xdrs->x_op == XDR_DECODE) {
372 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
373 			return (FALSE);
374 		}
375 		if (rndup == 0)
376 			return (TRUE);
377 		return (XDR_GETBYTES(xdrs, crud, rndup));
378 	}
379 
380 	if (xdrs->x_op == XDR_ENCODE) {
381 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
382 			return (FALSE);
383 		}
384 		if (rndup == 0)
385 			return (TRUE);
386 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
387 	}
388 
389 	if (xdrs->x_op == XDR_FREE) {
390 		return (TRUE);
391 	}
392 
393 	return (FALSE);
394 }
395 
396 /*
397  * XDR counted bytes
398  * *cpp is a pointer to the bytes, *sizep is the count.
399  * If *cpp is NULL maxsize bytes are allocated
400  */
401 bool_t
xdr_bytes(xdrs,cpp,sizep,maxsize)402 xdr_bytes(xdrs, cpp, sizep, maxsize)
403 	register XDR *xdrs;
404 	char **cpp;
405 	register u_int *sizep;
406 	u_int maxsize;
407 {
408 	register char *sp = *cpp;  /* sp is the actual string pointer */
409 	register u_int nodesize;
410 
411 	/*
412 	 * first deal with the length since xdr bytes are counted
413 	 */
414 	if (! xdr_u_int(xdrs, sizep)) {
415 		return (FALSE);
416 	}
417 	nodesize = *sizep;
418 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
419 		return (FALSE);
420 	}
421 
422 	/*
423 	 * now deal with the actual bytes
424 	 */
425 	switch (xdrs->x_op) {
426 
427 	case XDR_DECODE:
428 		if (nodesize == 0) {
429 			return (TRUE);
430 		}
431 		if (sp == NULL) {
432 			*cpp = sp = (char *)mem_alloc(nodesize);
433 		}
434 		if (sp == NULL) {
435 			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
436 			return (FALSE);
437 		}
438 		/* fall into ... */
439 
440 	case XDR_ENCODE:
441 		return (xdr_opaque(xdrs, sp, nodesize));
442 
443 	case XDR_FREE:
444 		if (sp != NULL) {
445 			mem_free(sp, nodesize);
446 			*cpp = NULL;
447 		}
448 		return (TRUE);
449 	}
450 	return (FALSE);
451 }
452 
453 #ifdef UNUSED
454 /*
455  * Implemented here due to commonality of the object.
456  */
457 bool_t
xdr_netobj(xdrs,np)458 xdr_netobj(xdrs, np)
459 	XDR *xdrs;
460 	struct netobj *np;
461 {
462 
463 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
464 }
465 
466 /*
467  * XDR a descriminated union
468  * Support routine for discriminated unions.
469  * You create an array of xdrdiscrim structures, terminated with
470  * an entry with a null procedure pointer.  The routine gets
471  * the discriminant value and then searches the array of xdrdiscrims
472  * looking for that value.  It calls the procedure given in the xdrdiscrim
473  * to handle the discriminant.  If there is no specific routine a default
474  * routine may be called.
475  * If there is no specific or default routine an error is returned.
476  */
477 bool_t
xdr_union(xdrs,dscmp,unp,choices,dfault)478 xdr_union(xdrs, dscmp, unp, choices, dfault)
479 	register XDR *xdrs;
480 	enum_t *dscmp;		/* enum to decide which arm to work on */
481 	char *unp;		/* the union itself */
482 	struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
483 	xdrproc_t dfault;	/* default xdr routine */
484 {
485 	register enum_t dscm;
486 
487 	/*
488 	 * we deal with the discriminator;  it's an enum
489 	 */
490 	if (! xdr_enum(xdrs, dscmp)) {
491 		return (FALSE);
492 	}
493 	dscm = *dscmp;
494 
495 	/*
496 	 * search choices for a value that matches the discriminator.
497 	 * if we find one, execute the xdr routine for that value.
498 	 */
499 	for (; choices->proc != NULL_xdrproc_t; choices++) {
500 		if (choices->value == dscm)
501 			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
502 	}
503 
504 	/*
505 	 * no match - execute the default xdr routine if there is one
506 	 */
507 	return ((dfault == NULL_xdrproc_t) ? FALSE :
508 	    (*dfault)(xdrs, unp, LASTUNSIGNED));
509 }
510 #endif
511 
512 /*
513  * Non-portable xdr primitives.
514  * Care should be taken when moving these routines to new architectures.
515  */
516 
517 
518 /*
519  * XDR null terminated ASCII strings
520  * xdr_string deals with "C strings" - arrays of bytes that are
521  * terminated by a NULL character.  The parameter cpp references a
522  * pointer to storage; If the pointer is null, then the necessary
523  * storage is allocated.  The last parameter is the max allowed length
524  * of the string as specified by a protocol.
525  */
526 bool_t
xdr_string(xdrs,cpp,maxsize)527 xdr_string(xdrs, cpp, maxsize)
528 	register XDR *xdrs;
529 	char **cpp;
530 	u_int maxsize;
531 {
532 	register char *sp = *cpp;  /* sp is the actual string pointer */
533 	u_int size;
534 	u_int nodesize;
535 
536 	/*
537 	 * first deal with the length since xdr strings are counted-strings
538 	 */
539 	switch (xdrs->x_op) {
540 	case XDR_FREE:
541 		if (sp == NULL) {
542 			return(TRUE);	/* already free */
543 		}
544 		/* fall through... */
545 	case XDR_ENCODE:
546 		size = strlen(sp);
547 		break;
548 	case XDR_DECODE:
549 	        /* size not used: just keep compilers happy */
550 	        break;
551 	}
552 	if (! xdr_u_int(xdrs, &size)) {
553 		return (FALSE);
554 	}
555 	if (size > maxsize) {
556 		return (FALSE);
557 	}
558 	nodesize = size + 1;
559 
560 	/*
561 	 * now deal with the actual bytes
562 	 */
563 	switch (xdrs->x_op) {
564 
565 	case XDR_DECODE:
566 		if (nodesize == 0) {
567 			return (TRUE);
568 		}
569 		if (sp == NULL)
570 			*cpp = sp = (char *)mem_alloc(nodesize);
571 		if (sp == NULL) {
572 			(void) fprintf(stderr, "xdr_string: out of memory\n");
573 			return (FALSE);
574 		}
575 		sp[size] = 0;
576 		/* fall into ... */
577 
578 	case XDR_ENCODE:
579 		return (xdr_opaque(xdrs, sp, size));
580 
581 	case XDR_FREE:
582 		mem_free(sp, nodesize);
583 		*cpp = NULL;
584 		return (TRUE);
585 	}
586 	return (FALSE);
587 }
588 
589 #ifdef UNUSED
590 /*
591  * Wrapper for xdr_string that can be called directly from
592  * routines like clnt_call
593  */
594 bool_t
xdr_wrapstring(xdrs,cpp)595 xdr_wrapstring(xdrs, cpp)
596 	XDR *xdrs;
597 	char **cpp;
598 {
599 	if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
600 		return (TRUE);
601 	}
602 	return (FALSE);
603 }
604 #endif
605