xref: /minix3/lib/libc/rpc/xdr.c (revision ef01931f760fe8114e6dd99a6864c92b3a85ae12)
1 /*	$NetBSD: xdr.c,v 1.28 2006/05/14 02:15:31 christos Exp $	*/
2 
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user.
10  *
11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14  *
15  * Sun RPC is provided with no support and without any obligation on the
16  * part of Sun Microsystems, Inc. to assist in its use, correction,
17  * modification or enhancement.
18  *
19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21  * OR ANY PART THEREOF.
22  *
23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24  * or profits or other special, indirect and consequential damages, even if
25  * Sun has been advised of the possibility of such damages.
26  *
27  * Sun Microsystems, Inc.
28  * 2550 Garcia Avenue
29  * Mountain View, California  94043
30  */
31 
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 #if 0
35 static char *sccsid = "@(#)xdr.c 1.35 87/08/12";
36 static char *sccsid = "@(#)xdr.c	2.1 88/07/29 4.0 RPCSRC";
37 #else
38 __RCSID("$NetBSD: xdr.c,v 1.28 2006/05/14 02:15:31 christos Exp $");
39 #endif
40 #endif
41 
42 /*
43  * xdr.c, Generic XDR routines implementation.
44  *
45  * Copyright (C) 1986, Sun Microsystems, Inc.
46  *
47  * These are the "generic" xdr routines used to serialize and de-serialize
48  * most common data items.  See xdr.h for more info on the interface to
49  * xdr.
50  */
51 
52 #include "namespace.h"
53 
54 #include <assert.h>
55 #include <err.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 
60 #include <rpc/types.h>
61 #include <rpc/xdr.h>
62 
63 #ifdef __weak_alias
64 __weak_alias(xdr_bool,_xdr_bool)
65 __weak_alias(xdr_bytes,_xdr_bytes)
66 __weak_alias(xdr_char,_xdr_char)
67 __weak_alias(xdr_enum,_xdr_enum)
68 __weak_alias(xdr_free,_xdr_free)
69 __weak_alias(xdr_hyper,_xdr_hyper)
70 __weak_alias(xdr_int,_xdr_int)
71 __weak_alias(xdr_int16_t,_xdr_int16_t)
72 __weak_alias(xdr_int32_t,_xdr_int32_t)
73 __weak_alias(xdr_int64_t,_xdr_int64_t)
74 __weak_alias(xdr_long,_xdr_long)
75 __weak_alias(xdr_longlong_t,_xdr_longlong_t)
76 __weak_alias(xdr_netobj,_xdr_netobj)
77 __weak_alias(xdr_opaque,_xdr_opaque)
78 __weak_alias(xdr_short,_xdr_short)
79 __weak_alias(xdr_string,_xdr_string)
80 __weak_alias(xdr_u_char,_xdr_u_char)
81 __weak_alias(xdr_u_hyper,_xdr_u_hyper)
82 __weak_alias(xdr_u_int,_xdr_u_int)
83 __weak_alias(xdr_u_int16_t,_xdr_u_int16_t)
84 __weak_alias(xdr_u_int32_t,_xdr_u_int32_t)
85 __weak_alias(xdr_u_int64_t,_xdr_u_int64_t)
86 __weak_alias(xdr_u_long,_xdr_u_long)
87 __weak_alias(xdr_u_longlong_t,_xdr_u_longlong_t)
88 __weak_alias(xdr_u_short,_xdr_u_short)
89 __weak_alias(xdr_union,_xdr_union)
90 __weak_alias(xdr_void,_xdr_void)
91 __weak_alias(xdr_wrapstring,_xdr_wrapstring)
92 #endif
93 
94 /*
95  * constants specific to the xdr "protocol"
96  */
97 #define XDR_FALSE	((long) 0)
98 #define XDR_TRUE	((long) 1)
99 #define LASTUNSIGNED	((u_int) 0-1)
100 
101 /*
102  * for unit alignment
103  */
104 static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
105 
106 /*
107  * Free a data structure using XDR
108  * Not a filter, but a convenient utility nonetheless
109  */
110 void
111 xdr_free(proc, objp)
112 	xdrproc_t proc;
113 	char *objp;
114 {
115 	XDR x;
116 
117 	x.x_op = XDR_FREE;
118 	(*proc)(&x, objp);
119 }
120 
121 /*
122  * XDR nothing
123  */
124 bool_t
125 xdr_void(/* xdrs, addr */)
126 	/* XDR *xdrs; */
127 	/* caddr_t addr; */
128 {
129 
130 	return (TRUE);
131 }
132 
133 
134 /*
135  * XDR integers
136  */
137 bool_t
138 xdr_int(xdrs, ip)
139 	XDR *xdrs;
140 	int *ip;
141 {
142 	long l;
143 
144 	_DIAGASSERT(xdrs != NULL);
145 	_DIAGASSERT(ip != NULL);
146 
147 	switch (xdrs->x_op) {
148 
149 	case XDR_ENCODE:
150 		l = (long) *ip;
151 		return (XDR_PUTLONG(xdrs, &l));
152 
153 	case XDR_DECODE:
154 		if (!XDR_GETLONG(xdrs, &l)) {
155 			return (FALSE);
156 		}
157 		*ip = (int) l;
158 		return (TRUE);
159 
160 	case XDR_FREE:
161 		return (TRUE);
162 	}
163 	/* NOTREACHED */
164 	return (FALSE);
165 }
166 
167 /*
168  * XDR unsigned integers
169  */
170 bool_t
171 xdr_u_int(xdrs, up)
172 	XDR *xdrs;
173 	u_int *up;
174 {
175 	u_long l;
176 
177 	_DIAGASSERT(xdrs != NULL);
178 	_DIAGASSERT(up != NULL);
179 
180 	switch (xdrs->x_op) {
181 
182 	case XDR_ENCODE:
183 		l = (u_long) *up;
184 		return (XDR_PUTLONG(xdrs, (long *)&l));
185 
186 	case XDR_DECODE:
187 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
188 			return (FALSE);
189 		}
190 		*up = (u_int) l;
191 		return (TRUE);
192 
193 	case XDR_FREE:
194 		return (TRUE);
195 	}
196 	/* NOTREACHED */
197 	return (FALSE);
198 }
199 
200 
201 /*
202  * XDR long integers
203  * same as xdr_u_long - open coded to save a proc call!
204  */
205 bool_t
206 xdr_long(xdrs, lp)
207 	XDR *xdrs;
208 	long *lp;
209 {
210 
211 	_DIAGASSERT(xdrs != NULL);
212 	_DIAGASSERT(lp != NULL);
213 
214 	switch (xdrs->x_op) {
215 	case XDR_ENCODE:
216 		return (XDR_PUTLONG(xdrs, lp));
217 	case XDR_DECODE:
218 		return (XDR_GETLONG(xdrs, lp));
219 	case XDR_FREE:
220 		return (TRUE);
221 	}
222 	/* NOTREACHED */
223 	return (FALSE);
224 }
225 
226 /*
227  * XDR unsigned long integers
228  * same as xdr_long - open coded to save a proc call!
229  */
230 bool_t
231 xdr_u_long(xdrs, ulp)
232 	XDR *xdrs;
233 	u_long *ulp;
234 {
235 
236 	_DIAGASSERT(xdrs != NULL);
237 	_DIAGASSERT(ulp != NULL);
238 
239 	switch (xdrs->x_op) {
240 	case XDR_ENCODE:
241 		return (XDR_PUTLONG(xdrs, (long *)ulp));
242 	case XDR_DECODE:
243 		return (XDR_GETLONG(xdrs, (long *)ulp));
244 	case XDR_FREE:
245 		return (TRUE);
246 	}
247 	/* NOTREACHED */
248 	return (FALSE);
249 }
250 
251 
252 /*
253  * XDR 32-bit integers
254  * same as xdr_u_int32_t - open coded to save a proc call!
255  */
256 bool_t
257 xdr_int32_t(xdrs, int32_p)
258 	XDR *xdrs;
259 	int32_t *int32_p;
260 {
261 	long l;
262 
263 	_DIAGASSERT(xdrs != NULL);
264 	_DIAGASSERT(int32_p != NULL);
265 
266 	switch (xdrs->x_op) {
267 
268 	case XDR_ENCODE:
269 		l = (long) *int32_p;
270 		return (XDR_PUTLONG(xdrs, &l));
271 
272 	case XDR_DECODE:
273 		if (!XDR_GETLONG(xdrs, &l)) {
274 			return (FALSE);
275 		}
276 		*int32_p = (int32_t) l;
277 		return (TRUE);
278 
279 	case XDR_FREE:
280 		return (TRUE);
281 	}
282 	/* NOTREACHED */
283 	return (FALSE);
284 }
285 
286 /*
287  * XDR unsigned 32-bit integers
288  * same as xdr_int32_t - open coded to save a proc call!
289  */
290 bool_t
291 xdr_u_int32_t(xdrs, u_int32_p)
292 	XDR *xdrs;
293 	u_int32_t *u_int32_p;
294 {
295 	u_long l;
296 
297 	_DIAGASSERT(xdrs != NULL);
298 	_DIAGASSERT(u_int32_p != NULL);
299 
300 	switch (xdrs->x_op) {
301 
302 	case XDR_ENCODE:
303 		l = (u_long) *u_int32_p;
304 		return (XDR_PUTLONG(xdrs, (long *)&l));
305 
306 	case XDR_DECODE:
307 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
308 			return (FALSE);
309 		}
310 		*u_int32_p = (u_int32_t) l;
311 		return (TRUE);
312 
313 	case XDR_FREE:
314 		return (TRUE);
315 	}
316 	/* NOTREACHED */
317 	return (FALSE);
318 }
319 
320 
321 /*
322  * XDR short integers
323  */
324 bool_t
325 xdr_short(xdrs, sp)
326 	XDR *xdrs;
327 	short *sp;
328 {
329 	long l;
330 
331 	_DIAGASSERT(xdrs != NULL);
332 	_DIAGASSERT(sp != NULL);
333 
334 	switch (xdrs->x_op) {
335 
336 	case XDR_ENCODE:
337 		l = (long) *sp;
338 		return (XDR_PUTLONG(xdrs, &l));
339 
340 	case XDR_DECODE:
341 		if (!XDR_GETLONG(xdrs, &l)) {
342 			return (FALSE);
343 		}
344 		*sp = (short) l;
345 		return (TRUE);
346 
347 	case XDR_FREE:
348 		return (TRUE);
349 	}
350 	/* NOTREACHED */
351 	return (FALSE);
352 }
353 
354 /*
355  * XDR unsigned short integers
356  */
357 bool_t
358 xdr_u_short(xdrs, usp)
359 	XDR *xdrs;
360 	u_short *usp;
361 {
362 	u_long l;
363 
364 	_DIAGASSERT(xdrs != NULL);
365 	_DIAGASSERT(usp != NULL);
366 
367 	switch (xdrs->x_op) {
368 
369 	case XDR_ENCODE:
370 		l = (u_long) *usp;
371 		return (XDR_PUTLONG(xdrs, (long *)&l));
372 
373 	case XDR_DECODE:
374 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
375 			return (FALSE);
376 		}
377 		*usp = (u_short) l;
378 		return (TRUE);
379 
380 	case XDR_FREE:
381 		return (TRUE);
382 	}
383 	/* NOTREACHED */
384 	return (FALSE);
385 }
386 
387 
388 /*
389  * XDR 16-bit integers
390  */
391 bool_t
392 xdr_int16_t(xdrs, int16_p)
393 	XDR *xdrs;
394 	int16_t *int16_p;
395 {
396 	long l;
397 
398 	_DIAGASSERT(xdrs != NULL);
399 	_DIAGASSERT(int16_p != NULL);
400 
401 	switch (xdrs->x_op) {
402 
403 	case XDR_ENCODE:
404 		l = (long) *int16_p;
405 		return (XDR_PUTLONG(xdrs, &l));
406 
407 	case XDR_DECODE:
408 		if (!XDR_GETLONG(xdrs, &l)) {
409 			return (FALSE);
410 		}
411 		*int16_p = (int16_t) l;
412 		return (TRUE);
413 
414 	case XDR_FREE:
415 		return (TRUE);
416 	}
417 	/* NOTREACHED */
418 	return (FALSE);
419 }
420 
421 /*
422  * XDR unsigned 16-bit integers
423  */
424 bool_t
425 xdr_u_int16_t(xdrs, u_int16_p)
426 	XDR *xdrs;
427 	u_int16_t *u_int16_p;
428 {
429 	u_long l;
430 
431 	_DIAGASSERT(xdrs != NULL);
432 	_DIAGASSERT(u_int16_p != NULL);
433 
434 	switch (xdrs->x_op) {
435 
436 	case XDR_ENCODE:
437 		l = (u_long) *u_int16_p;
438 		return (XDR_PUTLONG(xdrs, (long *)&l));
439 
440 	case XDR_DECODE:
441 		if (!XDR_GETLONG(xdrs, (long *)&l)) {
442 			return (FALSE);
443 		}
444 		*u_int16_p = (u_int16_t) l;
445 		return (TRUE);
446 
447 	case XDR_FREE:
448 		return (TRUE);
449 	}
450 	/* NOTREACHED */
451 	return (FALSE);
452 }
453 
454 
455 /*
456  * XDR a char
457  */
458 bool_t
459 xdr_char(xdrs, cp)
460 	XDR *xdrs;
461 	char *cp;
462 {
463 	int i;
464 
465 	_DIAGASSERT(xdrs != NULL);
466 	_DIAGASSERT(cp != NULL);
467 
468 	i = (*cp);
469 	if (!xdr_int(xdrs, &i)) {
470 		return (FALSE);
471 	}
472 	*cp = i;
473 	return (TRUE);
474 }
475 
476 /*
477  * XDR an unsigned char
478  */
479 bool_t
480 xdr_u_char(xdrs, cp)
481 	XDR *xdrs;
482 	u_char *cp;
483 {
484 	u_int u;
485 
486 	_DIAGASSERT(xdrs != NULL);
487 	_DIAGASSERT(cp != NULL);
488 
489 	u = (*cp);
490 	if (!xdr_u_int(xdrs, &u)) {
491 		return (FALSE);
492 	}
493 	*cp = u;
494 	return (TRUE);
495 }
496 
497 /*
498  * XDR booleans
499  */
500 bool_t
501 xdr_bool(xdrs, bp)
502 	XDR *xdrs;
503 	bool_t *bp;
504 {
505 	long lb;
506 
507 	_DIAGASSERT(xdrs != NULL);
508 	_DIAGASSERT(bp != NULL);
509 
510 	switch (xdrs->x_op) {
511 
512 	case XDR_ENCODE:
513 		lb = *bp ? XDR_TRUE : XDR_FALSE;
514 		return (XDR_PUTLONG(xdrs, &lb));
515 
516 	case XDR_DECODE:
517 		if (!XDR_GETLONG(xdrs, &lb)) {
518 			return (FALSE);
519 		}
520 		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
521 		return (TRUE);
522 
523 	case XDR_FREE:
524 		return (TRUE);
525 	}
526 	/* NOTREACHED */
527 	return (FALSE);
528 }
529 
530 /*
531  * XDR enumerations
532  */
533 bool_t
534 xdr_enum(xdrs, ep)
535 	XDR *xdrs;
536 	enum_t *ep;
537 {
538 	long l;
539 
540 	_DIAGASSERT(xdrs != NULL);
541 	_DIAGASSERT(ep != NULL);
542 
543 	switch (xdrs->x_op) {
544 
545 	case XDR_ENCODE:
546 		l = (long) *ep;
547 		return (XDR_PUTLONG(xdrs, &l));
548 
549 	case XDR_DECODE:
550 		if (!XDR_GETLONG(xdrs, &l)) {
551 			return (FALSE);
552 		}
553 		*ep = (enum_t) l;
554 		return (TRUE);
555 
556 	case XDR_FREE:
557 		return (TRUE);
558 	}
559 	/* NOTREACHED */
560 	return (FALSE);
561 }
562 
563 /*
564  * XDR opaque data
565  * Allows the specification of a fixed size sequence of opaque bytes.
566  * cp points to the opaque object and cnt gives the byte length.
567  */
568 bool_t
569 xdr_opaque(xdrs, cp, cnt)
570 	XDR *xdrs;
571 	caddr_t cp;
572 	u_int cnt;
573 {
574 	u_int rndup;
575 	static int crud[BYTES_PER_XDR_UNIT];
576 
577 	_DIAGASSERT(xdrs != NULL);
578 		/*
579 		 * if no data we are done
580 		 */
581 	if (cnt == 0)
582 		return (TRUE);
583 	_DIAGASSERT(cp != NULL);
584 
585 	/*
586 	 * round byte count to full xdr units
587 	 */
588 	rndup = cnt % BYTES_PER_XDR_UNIT;
589 	if (rndup > 0)
590 		rndup = BYTES_PER_XDR_UNIT - rndup;
591 
592 	if (xdrs->x_op == XDR_DECODE) {
593 		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
594 			return (FALSE);
595 		}
596 		if (rndup == 0)
597 			return (TRUE);
598 		return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
599 	}
600 
601 	if (xdrs->x_op == XDR_ENCODE) {
602 		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
603 			return (FALSE);
604 		}
605 		if (rndup == 0)
606 			return (TRUE);
607 		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
608 	}
609 
610 	if (xdrs->x_op == XDR_FREE) {
611 		return (TRUE);
612 	}
613 
614 	return (FALSE);
615 }
616 
617 /*
618  * XDR counted bytes
619  * *cpp is a pointer to the bytes, *sizep is the count.
620  * If *cpp is NULL maxsize bytes are allocated
621  */
622 bool_t
623 xdr_bytes(xdrs, cpp, sizep, maxsize)
624 	XDR *xdrs;
625 	char **cpp;
626 	u_int *sizep;
627 	u_int maxsize;
628 {
629 	char *sp;  		/* sp is the actual string pointer */
630 	u_int nodesize;
631 
632 	_DIAGASSERT(xdrs != NULL);
633 	_DIAGASSERT(cpp != NULL);
634 	_DIAGASSERT(sizep != NULL);
635 
636 	sp = *cpp;
637 
638 	/*
639 	 * first deal with the length since xdr bytes are counted
640 	 */
641 	if (! xdr_u_int(xdrs, sizep)) {
642 		return (FALSE);
643 	}
644 	nodesize = *sizep;
645 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
646 		return (FALSE);
647 	}
648 
649 	/*
650 	 * now deal with the actual bytes
651 	 */
652 	switch (xdrs->x_op) {
653 
654 	case XDR_DECODE:
655 		if (nodesize == 0) {
656 			return (TRUE);
657 		}
658 		if (sp == NULL) {
659 			*cpp = sp = mem_alloc(nodesize);
660 		}
661 		if (sp == NULL) {
662 			warnx("xdr_bytes: out of memory");
663 			return (FALSE);
664 		}
665 		/* FALLTHROUGH */
666 
667 	case XDR_ENCODE:
668 		return (xdr_opaque(xdrs, sp, nodesize));
669 
670 	case XDR_FREE:
671 		if (sp != NULL) {
672 			mem_free(sp, nodesize);
673 			*cpp = NULL;
674 		}
675 		return (TRUE);
676 	}
677 	/* NOTREACHED */
678 	return (FALSE);
679 }
680 
681 /*
682  * Implemented here due to commonality of the object.
683  */
684 bool_t
685 xdr_netobj(xdrs, np)
686 	XDR *xdrs;
687 	struct netobj *np;
688 {
689 
690 	_DIAGASSERT(xdrs != NULL);
691 	_DIAGASSERT(np != NULL);
692 
693 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
694 }
695 
696 /*
697  * XDR a descriminated union
698  * Support routine for discriminated unions.
699  * You create an array of xdrdiscrim structures, terminated with
700  * an entry with a null procedure pointer.  The routine gets
701  * the discriminant value and then searches the array of xdrdiscrims
702  * looking for that value.  It calls the procedure given in the xdrdiscrim
703  * to handle the discriminant.  If there is no specific routine a default
704  * routine may be called.
705  * If there is no specific or default routine an error is returned.
706  */
707 bool_t
708 xdr_union(xdrs, dscmp, unp, choices, dfault)
709 	XDR *xdrs;
710 	enum_t *dscmp;		/* enum to decide which arm to work on */
711 	char *unp;		/* the union itself */
712 	const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
713 	xdrproc_t dfault;	/* default xdr routine */
714 {
715 	enum_t dscm;
716 
717 	_DIAGASSERT(xdrs != NULL);
718 	_DIAGASSERT(dscmp != NULL);
719 	_DIAGASSERT(unp != NULL);
720 	_DIAGASSERT(choices != NULL);
721 	/* dfault may be NULL */
722 
723 	/*
724 	 * we deal with the discriminator;  it's an enum
725 	 */
726 	if (! xdr_enum(xdrs, dscmp)) {
727 		return (FALSE);
728 	}
729 	dscm = *dscmp;
730 
731 	/*
732 	 * search choices for a value that matches the discriminator.
733 	 * if we find one, execute the xdr routine for that value.
734 	 */
735 	for (; choices->proc != NULL_xdrproc_t; choices++) {
736 		if (choices->value == dscm)
737 			return ((*(choices->proc))(xdrs, unp));
738 	}
739 
740 	/*
741 	 * no match - execute the default xdr routine if there is one
742 	 */
743 	return ((dfault == NULL_xdrproc_t) ? FALSE :
744 	    (*dfault)(xdrs, unp));
745 }
746 
747 
748 /*
749  * Non-portable xdr primitives.
750  * Care should be taken when moving these routines to new architectures.
751  */
752 
753 
754 /*
755  * XDR null terminated ASCII strings
756  * xdr_string deals with "C strings" - arrays of bytes that are
757  * terminated by a NULL character.  The parameter cpp references a
758  * pointer to storage; If the pointer is null, then the necessary
759  * storage is allocated.  The last parameter is the max allowed length
760  * of the string as specified by a protocol.
761  */
762 bool_t
763 xdr_string(xdrs, cpp, maxsize)
764 	XDR *xdrs;
765 	char **cpp;
766 	u_int maxsize;
767 {
768 	char *sp;  		/* sp is the actual string pointer */
769 	u_int size = 0;		/* XXX: GCC */
770 	u_int nodesize;
771 
772 	_DIAGASSERT(xdrs != NULL);
773 	_DIAGASSERT(cpp != NULL);
774 
775 	sp = *cpp;
776 
777 	/*
778 	 * first deal with the length since xdr strings are counted-strings
779 	 */
780 	switch (xdrs->x_op) {
781 	case XDR_FREE:
782 		if (sp == NULL) {
783 			return(TRUE);	/* already free */
784 		}
785 		/* FALLTHROUGH */
786 	case XDR_ENCODE:
787 		size = strlen(sp);
788 		break;
789 	case XDR_DECODE:
790 		break;
791 	}
792 	if (! xdr_u_int(xdrs, &size)) {
793 		return (FALSE);
794 	}
795 	if (size > maxsize) {
796 		return (FALSE);
797 	}
798 	nodesize = size + 1;
799 
800 	/*
801 	 * now deal with the actual bytes
802 	 */
803 	switch (xdrs->x_op) {
804 
805 	case XDR_DECODE:
806 		if (nodesize == 0) {
807 			return (TRUE);
808 		}
809 		if (sp == NULL)
810 			*cpp = sp = mem_alloc(nodesize);
811 		if (sp == NULL) {
812 			warnx("xdr_string: out of memory");
813 			return (FALSE);
814 		}
815 		sp[size] = 0;
816 		/* FALLTHROUGH */
817 
818 	case XDR_ENCODE:
819 		return (xdr_opaque(xdrs, sp, size));
820 
821 	case XDR_FREE:
822 		mem_free(sp, nodesize);
823 		*cpp = NULL;
824 		return (TRUE);
825 	}
826 	/* NOTREACHED */
827 	return (FALSE);
828 }
829 
830 /*
831  * Wrapper for xdr_string that can be called directly from
832  * routines like clnt_call
833  */
834 bool_t
835 xdr_wrapstring(xdrs, cpp)
836 	XDR *xdrs;
837 	char **cpp;
838 {
839 
840 	_DIAGASSERT(xdrs != NULL);
841 	_DIAGASSERT(cpp != NULL);
842 
843 	return xdr_string(xdrs, cpp, LASTUNSIGNED);
844 }
845 
846 /*
847  * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
848  * are in the "non-portable" section because they require that a `long long'
849  * be a 64-bit type.
850  *
851  *	--thorpej@NetBSD.org, November 30, 1999
852  */
853 
854 /*
855  * XDR 64-bit integers
856  */
857 bool_t
858 xdr_int64_t(xdrs, llp)
859 	XDR *xdrs;
860 	int64_t *llp;
861 {
862 	u_long ul[2];
863 
864 	_DIAGASSERT(xdrs != NULL);
865 	_DIAGASSERT(llp != NULL);
866 
867 	switch (xdrs->x_op) {
868 	case XDR_ENCODE:
869 		ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
870 		ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
871 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
872 			return (FALSE);
873 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
874 	case XDR_DECODE:
875 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
876 			return (FALSE);
877 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
878 			return (FALSE);
879 		*llp = (int64_t)
880 		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
881 		return (TRUE);
882 	case XDR_FREE:
883 		return (TRUE);
884 	}
885 	/* NOTREACHED */
886 	return (FALSE);
887 }
888 
889 
890 /*
891  * XDR unsigned 64-bit integers
892  */
893 bool_t
894 xdr_u_int64_t(xdrs, ullp)
895 	XDR *xdrs;
896 	u_int64_t *ullp;
897 {
898 	u_long ul[2];
899 
900 	_DIAGASSERT(xdrs != NULL);
901 	_DIAGASSERT(ullp != NULL);
902 
903 	switch (xdrs->x_op) {
904 	case XDR_ENCODE:
905 		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
906 		ul[1] = (u_long)(*ullp) & 0xffffffff;
907 		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
908 			return (FALSE);
909 		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
910 	case XDR_DECODE:
911 		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
912 			return (FALSE);
913 		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
914 			return (FALSE);
915 		*ullp = (u_int64_t)
916 		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
917 		return (TRUE);
918 	case XDR_FREE:
919 		return (TRUE);
920 	}
921 	/* NOTREACHED */
922 	return (FALSE);
923 }
924 
925 
926 /*
927  * XDR hypers
928  */
929 bool_t
930 xdr_hyper(xdrs, llp)
931 	XDR *xdrs;
932 	longlong_t *llp;
933 {
934 
935 	_DIAGASSERT(xdrs != NULL);
936 	_DIAGASSERT(llp != NULL);
937 
938 	/*
939 	 * Don't bother open-coding this; it's a fair amount of code.  Just
940 	 * call xdr_int64_t().
941 	 */
942 	return (xdr_int64_t(xdrs, (int64_t *)llp));
943 }
944 
945 
946 /*
947  * XDR unsigned hypers
948  */
949 bool_t
950 xdr_u_hyper(xdrs, ullp)
951 	XDR *xdrs;
952 	u_longlong_t *ullp;
953 {
954 
955 	_DIAGASSERT(xdrs != NULL);
956 	_DIAGASSERT(ullp != NULL);
957 
958 	/*
959 	 * Don't bother open-coding this; it's a fair amount of code.  Just
960 	 * call xdr_u_int64_t().
961 	 */
962 	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
963 }
964 
965 
966 /*
967  * XDR longlong_t's
968  */
969 bool_t
970 xdr_longlong_t(xdrs, llp)
971 	XDR *xdrs;
972 	longlong_t *llp;
973 {
974 
975 	_DIAGASSERT(xdrs != NULL);
976 	_DIAGASSERT(llp != NULL);
977 
978 	/*
979 	 * Don't bother open-coding this; it's a fair amount of code.  Just
980 	 * call xdr_int64_t().
981 	 */
982 	return (xdr_int64_t(xdrs, (int64_t *)llp));
983 }
984 
985 
986 /*
987  * XDR u_longlong_t's
988  */
989 bool_t
990 xdr_u_longlong_t(xdrs, ullp)
991 	XDR *xdrs;
992 	u_longlong_t *ullp;
993 {
994 
995 	_DIAGASSERT(xdrs != NULL);
996 	_DIAGASSERT(ullp != NULL);
997 
998 	/*
999 	 * Don't bother open-coding this; it's a fair amount of code.  Just
1000 	 * call xdr_u_int64_t().
1001 	 */
1002 	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
1003 }
1004