xref: /dragonfly/lib/libc/xdr/xdr.c (revision b40e316c)
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  *
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  *
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  *
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  *
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * @(#)xdr.c 1.35 87/08/12
30  * @(#)xdr.c	2.1 88/07/29 4.0 RPCSRC
31  * $FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9.2.1 2000/05/06 21:16:04 dec Exp $
32  * $DragonFly: src/lib/libc/xdr/xdr.c,v 1.3 2004/10/25 19:38:02 drhodus Exp $
33  */
34 
35 /*
36  * xdr.c, Generic XDR routines implementation.
37  *
38  * Copyright (C) 1986, Sun Microsystems, Inc.
39  *
40  * These are the "generic" xdr routines used to serialize and de-serialize
41  * most common data items.  See xdr.h for more info on the interface to
42  * xdr.
43  */
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51 
52 /*
53  * constants specific to the xdr "protocol"
54  */
55 #define XDR_FALSE	((long) 0)
56 #define XDR_TRUE	((long) 1)
57 #define LASTUNSIGNED	((u_int) 0-1)
58 
59 /*
60  * for unit alignment
61  */
62 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
63 
64 /*
65  * Free a data structure using XDR
66  * Not a filter, but a convenient utility nonetheless
67  */
68 void
69 xdr_free(proc, objp)
70 	xdrproc_t proc;
71 	char *objp;
72 {
73 	XDR x;
74 
75 	x.x_op = XDR_FREE;
76 	(*proc)(&x, objp);
77 }
78 
79 /*
80  * XDR nothing
81  */
82 bool_t
83 xdr_void(/* xdrs, addr */)
84 	/* XDR *xdrs; */
85 	/* caddr_t addr; */
86 {
87 
88 	return (TRUE);
89 }
90 
91 
92 /*
93  * XDR integers
94  */
95 bool_t
96 xdr_int(xdrs, ip)
97 	XDR *xdrs;
98 	int *ip;
99 {
100 	long l;
101 
102 	switch (xdrs->x_op) {
103 
104 	case XDR_ENCODE:
105 		l = (long) *ip;
106 		return (XDR_PUTLONG(xdrs, &l));
107 
108 	case XDR_DECODE:
109 		if (!XDR_GETLONG(xdrs, &l)) {
110 			return (FALSE);
111 		}
112 		*ip = (int) l;
113 		return (TRUE);
114 
115 	case XDR_FREE:
116 		return (TRUE);
117 	}
118 	return (FALSE);
119 }
120 
121 /*
122  * XDR unsigned integers
123  */
124 bool_t
125 xdr_u_int(xdrs, up)
126 	XDR *xdrs;
127 	u_int *up;
128 {
129 	u_long l;
130 
131 	switch (xdrs->x_op) {
132 
133 	case XDR_ENCODE:
134 		l = (u_long) *up;
135 		return (XDR_PUTLONG(xdrs, (long *)&l));
136 
137 	case XDR_DECODE:
138 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
139 			return (FALSE);
140 		}
141 		*up = (u_int) l;
142 		return (TRUE);
143 
144 	case XDR_FREE:
145 		return (TRUE);
146 	}
147 	return (FALSE);
148 }
149 
150 
151 /*
152  * XDR long integers
153  * same as xdr_u_long - open coded to save a proc call!
154  */
155 bool_t
156 xdr_long(xdrs, lp)
157 	XDR *xdrs;
158 	long *lp;
159 {
160 	switch (xdrs->x_op) {
161 	case XDR_ENCODE:
162 		return (XDR_PUTLONG(xdrs, lp));
163 	case XDR_DECODE:
164 		return (XDR_GETLONG(xdrs, lp));
165 	case XDR_FREE:
166 		return (TRUE);
167 	}
168 
169 	return (FALSE);
170 }
171 
172 /*
173  * XDR unsigned long integers
174  * same as xdr_long - open coded to save a proc call!
175  */
176 bool_t
177 xdr_u_long(xdrs, ulp)
178 	XDR *xdrs;
179 	u_long *ulp;
180 {
181 	switch (xdrs->x_op) {
182 	case XDR_ENCODE:
183 		return (XDR_PUTLONG(xdrs, (long *)ulp));
184 	case XDR_DECODE:
185 		return (XDR_GETLONG(xdrs, (long *)ulp));
186 	case XDR_FREE:
187 		return (TRUE);
188 	}
189 	return (FALSE);
190 }
191 
192 
193 /*
194  * XDR 32-bit integers
195  * same as xdr_u_int32_t - open coded to save a proc call!
196  */
197 bool_t
198 xdr_int32_t(xdrs, int32_p)
199 	XDR *xdrs;
200 	int32_t *int32_p;
201 {
202 	long l;
203 
204 	switch (xdrs->x_op) {
205 
206 	case XDR_ENCODE:
207 		l = (long) *int32_p;
208 		return (XDR_PUTLONG(xdrs, &l));
209 
210 	case XDR_DECODE:
211 		if (!XDR_GETLONG(xdrs, &l)) {
212 			return (FALSE);
213 		}
214 		*int32_p = (int32_t) l;
215 		return (TRUE);
216 
217 	case XDR_FREE:
218 		return (TRUE);
219 	}
220 	return (FALSE);
221 }
222 
223 /*
224  * XDR unsigned 32-bit integers
225  * same as xdr_int32_t - open coded to save a proc call!
226  */
227 bool_t
228 xdr_u_int32_t(xdrs, u_int32_p)
229 	XDR *xdrs;
230 	u_int32_t *u_int32_p;
231 {
232 	u_long l;
233 
234 	switch (xdrs->x_op) {
235 
236 	case XDR_ENCODE:
237 		l = (u_long) *u_int32_p;
238 		return (XDR_PUTLONG(xdrs, (long *)&l));
239 
240 	case XDR_DECODE:
241 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
242 			return (FALSE);
243 		}
244 		*u_int32_p = (u_int32_t) l;
245 		return (TRUE);
246 
247 	case XDR_FREE:
248 		return (TRUE);
249 	}
250 	return (FALSE);
251 }
252 
253 /*
254  * XDR 64-bit integers
255  */
256 bool_t
257 xdr_int64_t(xdrs, int64_p)
258 	XDR *xdrs;
259 	int64_t *int64_p;
260 {
261 	u_long ul[2];
262 
263 	switch (xdrs->x_op) {
264 
265 	case XDR_ENCODE:
266 		ul[0] = (u_long)((u_int64_t)*int64_p >> 32) & 0xffffffff;
267 		ul[1] = (u_long)((u_int64_t)*int64_p) & 0xffffffff;
268 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
269 			return (FALSE);
270 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
271 	case XDR_DECODE:
272 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
273 			return (FALSE);
274 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
275 			return (FALSE);
276 		*int64_p = (int64_t)
277 			(((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
278 		return (TRUE);
279 	case XDR_FREE:
280 		return (TRUE);
281 	}
282 	return (FALSE);
283 }
284 
285 /*
286  * XDR unsigned 64-bit integers
287  */
288 bool_t
289 xdr_u_int64_t(xdrs, uint64_p)
290 	XDR *xdrs;
291 	u_int64_t *uint64_p;
292 {
293 	u_long ul[2];
294 
295 	switch (xdrs->x_op) {
296 
297 	case XDR_ENCODE:
298 		ul[0] = (u_long)(*uint64_p >> 32) & 0xffffffff;
299 		ul[1] = (u_long)(*uint64_p) & 0xffffffff;
300 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
301 			return (FALSE);
302 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
303 
304         case XDR_DECODE:
305 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
306 			return (FALSE);
307 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
308 			return (FALSE);
309 		*uint64_p = (u_int64_t)
310 			(((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
311 		return (TRUE);
312 	case XDR_FREE:
313 		return (TRUE);
314 	}
315 	return (FALSE);
316 }
317 
318 
319 /*
320  * XDR short integers
321  */
322 bool_t
323 xdr_short(xdrs, sp)
324 	XDR *xdrs;
325 	short *sp;
326 {
327 	long l;
328 
329 	switch (xdrs->x_op) {
330 
331 	case XDR_ENCODE:
332 		l = (long) *sp;
333 		return (XDR_PUTLONG(xdrs, &l));
334 
335 	case XDR_DECODE:
336 		if (!XDR_GETLONG(xdrs, &l)) {
337 			return (FALSE);
338 		}
339 		*sp = (short) l;
340 		return (TRUE);
341 
342 	case XDR_FREE:
343 		return (TRUE);
344 	}
345 	return (FALSE);
346 }
347 
348 /*
349  * XDR unsigned short integers
350  */
351 bool_t
352 xdr_u_short(xdrs, usp)
353 	XDR *xdrs;
354 	u_short *usp;
355 {
356 	u_long l;
357 
358 	switch (xdrs->x_op) {
359 
360 	case XDR_ENCODE:
361 		l = (u_long) *usp;
362 		return (XDR_PUTLONG(xdrs, (long *)&l));
363 
364 	case XDR_DECODE:
365 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
366 			return (FALSE);
367 		}
368 		*usp = (u_short) l;
369 		return (TRUE);
370 
371 	case XDR_FREE:
372 		return (TRUE);
373 	}
374 	return (FALSE);
375 }
376 
377 
378 /*
379  * XDR 16-bit integers
380  */
381 bool_t
382 xdr_int16_t(xdrs, int16_p)
383 	XDR *xdrs;
384 	int16_t *int16_p;
385 {
386 	long l;
387 
388 	switch (xdrs->x_op) {
389 
390 	case XDR_ENCODE:
391 		l = (long) *int16_p;
392 		return (XDR_PUTLONG(xdrs, &l));
393 
394 	case XDR_DECODE:
395 		if (!XDR_GETLONG(xdrs, &l)) {
396 			return (FALSE);
397 		}
398 		*int16_p = (int16_t) l;
399 		return (TRUE);
400 
401 	case XDR_FREE:
402 		return (TRUE);
403 	}
404 	return (FALSE);
405 }
406 
407 /*
408  * XDR unsigned 16-bit integers
409  */
410 bool_t
411 xdr_u_int16_t(xdrs, u_int16_p)
412 	XDR *xdrs;
413 	u_int16_t *u_int16_p;
414 {
415 	u_long l;
416 
417 	switch (xdrs->x_op) {
418 
419 	case XDR_ENCODE:
420 		l = (u_long) *u_int16_p;
421 		return (XDR_PUTLONG(xdrs, (long *)&l));
422 
423 	case XDR_DECODE:
424 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
425 			return (FALSE);
426 		}
427 		*u_int16_p = (u_int16_t) l;
428 		return (TRUE);
429 
430 	case XDR_FREE:
431 		return (TRUE);
432 	}
433 	return (FALSE);
434 }
435 
436 
437 /*
438  * XDR a char
439  */
440 bool_t
441 xdr_char(xdrs, cp)
442 	XDR *xdrs;
443 	char *cp;
444 {
445 	int i;
446 
447 	i = (*cp);
448 	if (!xdr_int(xdrs, &i)) {
449 		return (FALSE);
450 	}
451 	*cp = i;
452 	return (TRUE);
453 }
454 
455 /*
456  * XDR an unsigned char
457  */
458 bool_t
459 xdr_u_char(xdrs, cp)
460 	XDR *xdrs;
461 	u_char *cp;
462 {
463 	u_int u;
464 
465 	u = (*cp);
466 	if (!xdr_u_int(xdrs, &u)) {
467 		return (FALSE);
468 	}
469 	*cp = u;
470 	return (TRUE);
471 }
472 
473 /*
474  * XDR booleans
475  */
476 bool_t
477 xdr_bool(xdrs, bp)
478 	XDR *xdrs;
479 	bool_t *bp;
480 {
481 	long lb;
482 
483 	switch (xdrs->x_op) {
484 
485 	case XDR_ENCODE:
486 		lb = *bp ? XDR_TRUE : XDR_FALSE;
487 		return (XDR_PUTLONG(xdrs, &lb));
488 
489 	case XDR_DECODE:
490 		if (!XDR_GETLONG(xdrs, &lb)) {
491 			return (FALSE);
492 		}
493 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
494 		return (TRUE);
495 
496 	case XDR_FREE:
497 		return (TRUE);
498 	}
499 	return (FALSE);
500 }
501 
502 /*
503  * XDR enumerations
504  */
505 bool_t
506 xdr_enum(xdrs, ep)
507 	XDR *xdrs;
508 	enum_t *ep;
509 {
510 #ifndef lint
511 	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
512 
513 	/*
514 	 * enums are treated as ints
515 	 */
516 	if (sizeof (enum sizecheck) == sizeof (long)) {
517 		return (xdr_long(xdrs, (long *)ep));
518 	} else if (sizeof (enum sizecheck) == sizeof (int)) {
519 		return (xdr_int(xdrs, (int *)ep));
520 	} else if (sizeof (enum sizecheck) == sizeof (short)) {
521 		return (xdr_short(xdrs, (short *)ep));
522 	} else {
523 		return (FALSE);
524 	}
525 #else
526 	(void) (xdr_short(xdrs, (short *)ep));
527 	(void) (xdr_int(xdrs, (int *)ep));
528 	return (xdr_long(xdrs, (long *)ep));
529 #endif
530 }
531 
532 /*
533  * XDR opaque data
534  * Allows the specification of a fixed size sequence of opaque bytes.
535  * cp points to the opaque object and cnt gives the byte length.
536  */
537 bool_t
538 xdr_opaque(xdrs, cp, cnt)
539 	XDR *xdrs;
540 	caddr_t cp;
541 	u_int cnt;
542 {
543 	u_int rndup;
544 	static crud[BYTES_PER_XDR_UNIT];
545 
546 	/*
547 	 * if no data we are done
548 	 */
549 	if (cnt == 0)
550 		return (TRUE);
551 
552 	/*
553 	 * round byte count to full xdr units
554 	 */
555 	rndup = cnt % BYTES_PER_XDR_UNIT;
556 	if (rndup > 0)
557 		rndup = BYTES_PER_XDR_UNIT - rndup;
558 
559 	if (xdrs->x_op == XDR_DECODE) {
560 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
561 			return (FALSE);
562 		}
563 		if (rndup == 0)
564 			return (TRUE);
565 		return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
566 	}
567 
568 	if (xdrs->x_op == XDR_ENCODE) {
569 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
570 			return (FALSE);
571 		}
572 		if (rndup == 0)
573 			return (TRUE);
574 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
575 	}
576 
577 	if (xdrs->x_op == XDR_FREE) {
578 		return (TRUE);
579 	}
580 
581 	return (FALSE);
582 }
583 
584 /*
585  * XDR counted bytes
586  * *cpp is a pointer to the bytes, *sizep is the count.
587  * If *cpp is NULL maxsize bytes are allocated
588  */
589 bool_t
590 xdr_bytes(xdrs, cpp, sizep, maxsize)
591 	XDR *xdrs;
592 	char **cpp;
593 	u_int *sizep;
594 	u_int maxsize;
595 {
596 	char *sp = *cpp;  /* sp is the actual string pointer */
597 	u_int nodesize;
598 
599 	/*
600 	 * first deal with the length since xdr bytes are counted
601 	 */
602 	if (! xdr_u_int(xdrs, sizep)) {
603 		return (FALSE);
604 	}
605 	nodesize = *sizep;
606 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
607 		return (FALSE);
608 	}
609 
610 	/*
611 	 * now deal with the actual bytes
612 	 */
613 	switch (xdrs->x_op) {
614 
615 	case XDR_DECODE:
616 		if (nodesize == 0) {
617 			return (TRUE);
618 		}
619 		if (sp == NULL) {
620 			*cpp = sp = (char *)mem_alloc(nodesize);
621 		}
622 		if (sp == NULL) {
623 			(void) fprintf(stderr, "xdr_bytes: out of memory\n");
624 			return (FALSE);
625 		}
626 		/* fall into ... */
627 
628 	case XDR_ENCODE:
629 		return (xdr_opaque(xdrs, sp, nodesize));
630 
631 	case XDR_FREE:
632 		if (sp != NULL) {
633 			mem_free(sp, nodesize);
634 			*cpp = NULL;
635 		}
636 		return (TRUE);
637 	}
638 	return (FALSE);
639 }
640 
641 /*
642  * Implemented here due to commonality of the object.
643  */
644 bool_t
645 xdr_netobj(xdrs, np)
646 	XDR *xdrs;
647 	struct netobj *np;
648 {
649 
650 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
651 }
652 
653 /*
654  * XDR a descriminated union
655  * Support routine for discriminated unions.
656  * You create an array of xdrdiscrim structures, terminated with
657  * an entry with a null procedure pointer.  The routine gets
658  * the discriminant value and then searches the array of xdrdiscrims
659  * looking for that value.  It calls the procedure given in the xdrdiscrim
660  * to handle the discriminant.  If there is no specific routine a default
661  * routine may be called.
662  * If there is no specific or default routine an error is returned.
663  */
664 bool_t
665 xdr_union(xdrs, dscmp, unp, choices, dfault)
666 	XDR *xdrs;
667 	enum_t *dscmp;		/* enum to decide which arm to work on */
668 	char *unp;		/* the union itself */
669 	struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
670 	xdrproc_t dfault;	/* default xdr routine */
671 {
672 	enum_t dscm;
673 
674 	/*
675 	 * we deal with the discriminator;  it's an enum
676 	 */
677 	if (! xdr_enum(xdrs, dscmp)) {
678 		return (FALSE);
679 	}
680 	dscm = *dscmp;
681 
682 	/*
683 	 * search choices for a value that matches the discriminator.
684 	 * if we find one, execute the xdr routine for that value.
685 	 */
686 	for (; choices->proc != NULL_xdrproc_t; choices++) {
687 		if (choices->value == dscm)
688 			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
689 	}
690 
691 	/*
692 	 * no match - execute the default xdr routine if there is one
693 	 */
694 	return ((dfault == NULL_xdrproc_t) ? FALSE :
695 	    (*dfault)(xdrs, unp, LASTUNSIGNED));
696 }
697 
698 
699 /*
700  * Non-portable xdr primitives.
701  * Care should be taken when moving these routines to new architectures.
702  */
703 
704 
705 /*
706  * XDR null terminated ASCII strings
707  * xdr_string deals with "C strings" - arrays of bytes that are
708  * terminated by a NULL character.  The parameter cpp references a
709  * pointer to storage; If the pointer is null, then the necessary
710  * storage is allocated.  The last parameter is the max allowed length
711  * of the string as specified by a protocol.
712  */
713 bool_t
714 xdr_string(xdrs, cpp, maxsize)
715 	XDR *xdrs;
716 	char **cpp;
717 	u_int maxsize;
718 {
719 	char *sp = *cpp;  /* sp is the actual string pointer */
720 	u_int size;
721 	u_int nodesize;
722 
723 	/*
724 	 * first deal with the length since xdr strings are counted-strings
725 	 */
726 	switch (xdrs->x_op) {
727 	case XDR_FREE:
728 		if (sp == NULL) {
729 			return(TRUE);	/* already free */
730 		}
731 		/* fall through... */
732 	case XDR_ENCODE:
733 		size = strlen(sp);
734 		break;
735 	}
736 	if (! xdr_u_int(xdrs, &size)) {
737 		return (FALSE);
738 	}
739 	if (size > maxsize) {
740 		return (FALSE);
741 	}
742 	nodesize = size + 1;
743 
744 	/*
745 	 * now deal with the actual bytes
746 	 */
747 	switch (xdrs->x_op) {
748 
749 	case XDR_DECODE:
750 		if (nodesize == 0) {
751 			return (TRUE);
752 		}
753 		if (sp == NULL)
754 			*cpp = sp = (char *)mem_alloc(nodesize);
755 		if (sp == NULL) {
756 			(void) fprintf(stderr, "xdr_string: out of memory\n");
757 			return (FALSE);
758 		}
759 		sp[size] = 0;
760 		/* fall into ... */
761 
762 	case XDR_ENCODE:
763 		return (xdr_opaque(xdrs, sp, size));
764 
765 	case XDR_FREE:
766 		mem_free(sp, nodesize);
767 		*cpp = NULL;
768 		return (TRUE);
769 	}
770 	return (FALSE);
771 }
772 
773 /*
774  * Wrapper for xdr_string that can be called directly from
775  * routines like clnt_call
776  */
777 bool_t
778 xdr_wrapstring(xdrs, cpp)
779 	XDR *xdrs;
780 	char **cpp;
781 {
782 	return xdr_string(xdrs, cpp, LASTUNSIGNED);
783 }
784