1/*	$NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $	*/
2
3/*-
4 * Copyright (c) 2010, Oracle America, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *     * Redistributions of source code must retain the above copyright
11 *       notice, this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above
13 *       copyright notice, this list of conditions and the following
14 *       disclaimer in the documentation and/or other materials
15 *       provided with the distribution.
16 *     * Neither the name of the "Oracle America, Inc." nor the names of its
17 *       contributors may be used to endorse or promote products derived
18 *       from this software without specific prior written permission.
19 *
20 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char *sccsid2 = "@(#)xdr.c 1.35 87/08/12";
36static char *sccsid = "@(#)xdr.c	2.1 88/07/29 4.0 RPCSRC";
37#endif
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: stable/11/lib/libc/xdr/xdr.c 319614 2017-06-06 07:21:33Z delphij $");
40
41/*
42 * xdr.c, Generic XDR routines implementation.
43 *
44 * These are the "generic" xdr routines used to serialize and de-serialize
45 * most common data items.  See xdr.h for more info on the interface to
46 * xdr.
47 */
48
49#include "namespace.h"
50#include <err.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54
55#include <rpc/rpc.h>
56#include <rpc/rpc_com.h>
57#include <rpc/types.h>
58#include <rpc/xdr.h>
59#include "un-namespace.h"
60
61typedef quad_t          longlong_t;     /* ANSI long long type */
62typedef u_quad_t        u_longlong_t;   /* ANSI unsigned long long type */
63
64/*
65 * constants specific to the xdr "protocol"
66 */
67#define XDR_FALSE	((long) 0)
68#define XDR_TRUE	((long) 1)
69
70/*
71 * for unit alignment
72 */
73static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
74
75/*
76 * Free a data structure using XDR
77 * Not a filter, but a convenient utility nonetheless
78 */
79void
80xdr_free(xdrproc_t proc, void *objp)
81{
82	XDR x;
83
84	x.x_op = XDR_FREE;
85	(*proc)(&x, objp);
86}
87
88/*
89 * XDR nothing
90 */
91bool_t
92xdr_void(void)
93{
94
95	return (TRUE);
96}
97
98
99/*
100 * XDR integers
101 */
102bool_t
103xdr_int(XDR *xdrs, int *ip)
104{
105	long l;
106
107	switch (xdrs->x_op) {
108
109	case XDR_ENCODE:
110		l = (long) *ip;
111		return (XDR_PUTLONG(xdrs, &l));
112
113	case XDR_DECODE:
114		if (!XDR_GETLONG(xdrs, &l)) {
115			return (FALSE);
116		}
117		*ip = (int) l;
118		return (TRUE);
119
120	case XDR_FREE:
121		return (TRUE);
122	}
123	/* NOTREACHED */
124	return (FALSE);
125}
126
127/*
128 * XDR unsigned integers
129 */
130bool_t
131xdr_u_int(XDR *xdrs, u_int *up)
132{
133	u_long l;
134
135	switch (xdrs->x_op) {
136
137	case XDR_ENCODE:
138		l = (u_long) *up;
139		return (XDR_PUTLONG(xdrs, (long *)&l));
140
141	case XDR_DECODE:
142		if (!XDR_GETLONG(xdrs, (long *)&l)) {
143			return (FALSE);
144		}
145		*up = (u_int) l;
146		return (TRUE);
147
148	case XDR_FREE:
149		return (TRUE);
150	}
151	/* NOTREACHED */
152	return (FALSE);
153}
154
155
156/*
157 * XDR long integers
158 * same as xdr_u_long - open coded to save a proc call!
159 */
160bool_t
161xdr_long(XDR *xdrs, long *lp)
162{
163	switch (xdrs->x_op) {
164	case XDR_ENCODE:
165		return (XDR_PUTLONG(xdrs, lp));
166	case XDR_DECODE:
167		return (XDR_GETLONG(xdrs, lp));
168	case XDR_FREE:
169		return (TRUE);
170	}
171	/* NOTREACHED */
172	return (FALSE);
173}
174
175/*
176 * XDR unsigned long integers
177 * same as xdr_long - open coded to save a proc call!
178 */
179bool_t
180xdr_u_long(XDR *xdrs, u_long *ulp)
181{
182	switch (xdrs->x_op) {
183	case XDR_ENCODE:
184		return (XDR_PUTLONG(xdrs, (long *)ulp));
185	case XDR_DECODE:
186		return (XDR_GETLONG(xdrs, (long *)ulp));
187	case XDR_FREE:
188		return (TRUE);
189	}
190	/* NOTREACHED */
191	return (FALSE);
192}
193
194
195/*
196 * XDR 32-bit integers
197 * same as xdr_u_int32_t - open coded to save a proc call!
198 */
199bool_t
200xdr_int32_t(XDR *xdrs, 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	/* NOTREACHED */
221	return (FALSE);
222}
223
224/*
225 * XDR unsigned 32-bit integers
226 * same as xdr_int32_t - open coded to save a proc call!
227 */
228bool_t
229xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p)
230{
231	u_long l;
232
233	switch (xdrs->x_op) {
234
235	case XDR_ENCODE:
236		l = (u_long) *u_int32_p;
237		return (XDR_PUTLONG(xdrs, (long *)&l));
238
239	case XDR_DECODE:
240		if (!XDR_GETLONG(xdrs, (long *)&l)) {
241			return (FALSE);
242		}
243		*u_int32_p = (u_int32_t) l;
244		return (TRUE);
245
246	case XDR_FREE:
247		return (TRUE);
248	}
249	/* NOTREACHED */
250	return (FALSE);
251}
252
253/*
254 * XDR unsigned 32-bit integers
255 * same as xdr_int32_t - open coded to save a proc call!
256 */
257bool_t
258xdr_uint32_t(XDR *xdrs, uint32_t *u_int32_p)
259{
260	u_long l;
261
262	switch (xdrs->x_op) {
263
264	case XDR_ENCODE:
265		l = (u_long) *u_int32_p;
266		return (XDR_PUTLONG(xdrs, (long *)&l));
267
268	case XDR_DECODE:
269		if (!XDR_GETLONG(xdrs, (long *)&l)) {
270			return (FALSE);
271		}
272		*u_int32_p = (u_int32_t) l;
273		return (TRUE);
274
275	case XDR_FREE:
276		return (TRUE);
277	}
278	/* NOTREACHED */
279	return (FALSE);
280}
281
282/*
283 * XDR short integers
284 */
285bool_t
286xdr_short(XDR *xdrs, short *sp)
287{
288	long l;
289
290	switch (xdrs->x_op) {
291
292	case XDR_ENCODE:
293		l = (long) *sp;
294		return (XDR_PUTLONG(xdrs, &l));
295
296	case XDR_DECODE:
297		if (!XDR_GETLONG(xdrs, &l)) {
298			return (FALSE);
299		}
300		*sp = (short) l;
301		return (TRUE);
302
303	case XDR_FREE:
304		return (TRUE);
305	}
306	/* NOTREACHED */
307	return (FALSE);
308}
309
310/*
311 * XDR unsigned short integers
312 */
313bool_t
314xdr_u_short(XDR *xdrs, u_short *usp)
315{
316	u_long l;
317
318	switch (xdrs->x_op) {
319
320	case XDR_ENCODE:
321		l = (u_long) *usp;
322		return (XDR_PUTLONG(xdrs, (long *)&l));
323
324	case XDR_DECODE:
325		if (!XDR_GETLONG(xdrs, (long *)&l)) {
326			return (FALSE);
327		}
328		*usp = (u_short) l;
329		return (TRUE);
330
331	case XDR_FREE:
332		return (TRUE);
333	}
334	/* NOTREACHED */
335	return (FALSE);
336}
337
338
339/*
340 * XDR 16-bit integers
341 */
342bool_t
343xdr_int16_t(XDR *xdrs, int16_t *int16_p)
344{
345	long l;
346
347	switch (xdrs->x_op) {
348
349	case XDR_ENCODE:
350		l = (long) *int16_p;
351		return (XDR_PUTLONG(xdrs, &l));
352
353	case XDR_DECODE:
354		if (!XDR_GETLONG(xdrs, &l)) {
355			return (FALSE);
356		}
357		*int16_p = (int16_t) l;
358		return (TRUE);
359
360	case XDR_FREE:
361		return (TRUE);
362	}
363	/* NOTREACHED */
364	return (FALSE);
365}
366
367/*
368 * XDR unsigned 16-bit integers
369 */
370bool_t
371xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p)
372{
373	u_long l;
374
375	switch (xdrs->x_op) {
376
377	case XDR_ENCODE:
378		l = (u_long) *u_int16_p;
379		return (XDR_PUTLONG(xdrs, (long *)&l));
380
381	case XDR_DECODE:
382		if (!XDR_GETLONG(xdrs, (long *)&l)) {
383			return (FALSE);
384		}
385		*u_int16_p = (u_int16_t) l;
386		return (TRUE);
387
388	case XDR_FREE:
389		return (TRUE);
390	}
391	/* NOTREACHED */
392	return (FALSE);
393}
394
395/*
396 * XDR unsigned 16-bit integers
397 */
398bool_t
399xdr_uint16_t(XDR *xdrs, uint16_t *u_int16_p)
400{
401	u_long l;
402
403	switch (xdrs->x_op) {
404
405	case XDR_ENCODE:
406		l = (u_long) *u_int16_p;
407		return (XDR_PUTLONG(xdrs, (long *)&l));
408
409	case XDR_DECODE:
410		if (!XDR_GETLONG(xdrs, (long *)&l)) {
411			return (FALSE);
412		}
413		*u_int16_p = (u_int16_t) l;
414		return (TRUE);
415
416	case XDR_FREE:
417		return (TRUE);
418	}
419	/* NOTREACHED */
420	return (FALSE);
421}
422
423
424/*
425 * XDR a char
426 */
427bool_t
428xdr_char(XDR *xdrs, char *cp)
429{
430	int i;
431
432	i = (*cp);
433	if (!xdr_int(xdrs, &i)) {
434		return (FALSE);
435	}
436	*cp = i;
437	return (TRUE);
438}
439
440/*
441 * XDR an unsigned char
442 */
443bool_t
444xdr_u_char(XDR *xdrs, u_char *cp)
445{
446	u_int u;
447
448	u = (*cp);
449	if (!xdr_u_int(xdrs, &u)) {
450		return (FALSE);
451	}
452	*cp = u;
453	return (TRUE);
454}
455
456/*
457 * XDR booleans
458 */
459bool_t
460xdr_bool(XDR *xdrs, bool_t *bp)
461{
462	long lb;
463
464	switch (xdrs->x_op) {
465
466	case XDR_ENCODE:
467		lb = *bp ? XDR_TRUE : XDR_FALSE;
468		return (XDR_PUTLONG(xdrs, &lb));
469
470	case XDR_DECODE:
471		if (!XDR_GETLONG(xdrs, &lb)) {
472			return (FALSE);
473		}
474		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
475		return (TRUE);
476
477	case XDR_FREE:
478		return (TRUE);
479	}
480	/* NOTREACHED */
481	return (FALSE);
482}
483
484/*
485 * XDR enumerations
486 */
487bool_t
488xdr_enum(XDR *xdrs, enum_t *ep)
489{
490	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
491
492	/*
493	 * enums are treated as ints
494	 */
495	/* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
496		return (xdr_long(xdrs, (long *)(void *)ep));
497	} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
498		return (xdr_int(xdrs, (int *)(void *)ep));
499	} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
500		return (xdr_short(xdrs, (short *)(void *)ep));
501	} else {
502		return (FALSE);
503	}
504}
505
506/*
507 * XDR opaque data
508 * Allows the specification of a fixed size sequence of opaque bytes.
509 * cp points to the opaque object and cnt gives the byte length.
510 */
511bool_t
512xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
513{
514	u_int rndup;
515	static int crud[BYTES_PER_XDR_UNIT];
516
517	/*
518	 * if no data we are done
519	 */
520	if (cnt == 0)
521		return (TRUE);
522
523	/*
524	 * round byte count to full xdr units
525	 */
526	rndup = cnt % BYTES_PER_XDR_UNIT;
527	if (rndup > 0)
528		rndup = BYTES_PER_XDR_UNIT - rndup;
529
530	if (xdrs->x_op == XDR_DECODE) {
531		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
532			return (FALSE);
533		}
534		if (rndup == 0)
535			return (TRUE);
536		return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
537	}
538
539	if (xdrs->x_op == XDR_ENCODE) {
540		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
541			return (FALSE);
542		}
543		if (rndup == 0)
544			return (TRUE);
545		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
546	}
547
548	if (xdrs->x_op == XDR_FREE) {
549		return (TRUE);
550	}
551
552	return (FALSE);
553}
554
555/*
556 * XDR counted bytes
557 * *cpp is a pointer to the bytes, *sizep is the count.
558 * If *cpp is NULL maxsize bytes are allocated
559 */
560bool_t
561xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
562{
563	char *sp = *cpp;  /* sp is the actual string pointer */
564	u_int nodesize;
565	bool_t ret, allocated = FALSE;
566
567	/*
568	 * first deal with the length since xdr bytes are counted
569	 */
570	if (! xdr_u_int(xdrs, sizep)) {
571		return (FALSE);
572	}
573	nodesize = *sizep;
574	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
575		return (FALSE);
576	}
577
578	/*
579	 * now deal with the actual bytes
580	 */
581	switch (xdrs->x_op) {
582
583	case XDR_DECODE:
584		if (nodesize == 0) {
585			return (TRUE);
586		}
587		if (sp == NULL) {
588			*cpp = sp = mem_alloc(nodesize);
589			allocated = TRUE;
590		}
591		if (sp == NULL) {
592			warnx("xdr_bytes: out of memory");
593			return (FALSE);
594		}
595		/* FALLTHROUGH */
596
597	case XDR_ENCODE:
598		ret = xdr_opaque(xdrs, sp, nodesize);
599		if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) {
600			if (allocated == TRUE) {
601				free(sp);
602				*cpp = NULL;
603			}
604		}
605		return (ret);
606
607	case XDR_FREE:
608		if (sp != NULL) {
609			mem_free(sp, nodesize);
610			*cpp = NULL;
611		}
612		return (TRUE);
613	}
614	/* NOTREACHED */
615	return (FALSE);
616}
617
618/*
619 * Implemented here due to commonality of the object.
620 */
621bool_t
622xdr_netobj(XDR *xdrs, struct netobj *np)
623{
624
625	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
626}
627
628/*
629 * XDR a descriminated union
630 * Support routine for discriminated unions.
631 * You create an array of xdrdiscrim structures, terminated with
632 * an entry with a null procedure pointer.  The routine gets
633 * the discriminant value and then searches the array of xdrdiscrims
634 * looking for that value.  It calls the procedure given in the xdrdiscrim
635 * to handle the discriminant.  If there is no specific routine a default
636 * routine may be called.
637 * If there is no specific or default routine an error is returned.
638 */
639bool_t
640xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault)
641/*
642 *	XDR *xdrs;
643 *	enum_t *dscmp;		// enum to decide which arm to work on
644 *	char *unp;		// the union itself
645 *	const struct xdr_discrim *choices;	// [value, xdr proc] for each arm
646 *	xdrproc_t dfault;	// default xdr routine
647 */
648{
649	enum_t dscm;
650
651	/*
652	 * we deal with the discriminator;  it's an enum
653	 */
654	if (! xdr_enum(xdrs, dscmp)) {
655		return (FALSE);
656	}
657	dscm = *dscmp;
658
659	/*
660	 * search choices for a value that matches the discriminator.
661	 * if we find one, execute the xdr routine for that value.
662	 */
663	for (; choices->proc != NULL_xdrproc_t; choices++) {
664		if (choices->value == dscm)
665			return ((*(choices->proc))(xdrs, unp));
666	}
667
668	/*
669	 * no match - execute the default xdr routine if there is one
670	 */
671	return ((dfault == NULL_xdrproc_t) ? FALSE :
672	    (*dfault)(xdrs, unp));
673}
674
675
676/*
677 * Non-portable xdr primitives.
678 * Care should be taken when moving these routines to new architectures.
679 */
680
681
682/*
683 * XDR null terminated ASCII strings
684 * xdr_string deals with "C strings" - arrays of bytes that are
685 * terminated by a NULL character.  The parameter cpp references a
686 * pointer to storage; If the pointer is null, then the necessary
687 * storage is allocated.  The last parameter is the max allowed length
688 * of the string as specified by a protocol.
689 */
690bool_t
691xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
692{
693	char *sp = *cpp;  /* sp is the actual string pointer */
694	u_int size;
695	u_int nodesize;
696	bool_t ret, allocated = FALSE;
697
698	/*
699	 * first deal with the length since xdr strings are counted-strings
700	 */
701	switch (xdrs->x_op) {
702	case XDR_FREE:
703		if (sp == NULL) {
704			return(TRUE);	/* already free */
705		}
706		/* FALLTHROUGH */
707	case XDR_ENCODE:
708		size = strlen(sp);
709		break;
710	case XDR_DECODE:
711		break;
712	}
713	if (! xdr_u_int(xdrs, &size)) {
714		return (FALSE);
715	}
716	if (size > maxsize) {
717		return (FALSE);
718	}
719	nodesize = size + 1;
720
721	/*
722	 * now deal with the actual bytes
723	 */
724	switch (xdrs->x_op) {
725
726	case XDR_DECODE:
727		if (nodesize == 0) {
728			return (TRUE);
729		}
730		if (sp == NULL) {
731			*cpp = sp = mem_alloc(nodesize);
732			allocated = TRUE;
733		}
734		if (sp == NULL) {
735			warnx("xdr_string: out of memory");
736			return (FALSE);
737		}
738		sp[size] = 0;
739		/* FALLTHROUGH */
740
741	case XDR_ENCODE:
742		ret = xdr_opaque(xdrs, sp, size);
743		if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) {
744			if (allocated == TRUE) {
745				free(sp);
746				*cpp = NULL;
747			}
748		}
749		return (ret);
750
751	case XDR_FREE:
752		mem_free(sp, nodesize);
753		*cpp = NULL;
754		return (TRUE);
755	}
756	/* NOTREACHED */
757	return (FALSE);
758}
759
760/*
761 * Wrapper for xdr_string that can be called directly from
762 * routines like clnt_call
763 */
764bool_t
765xdr_wrapstring(XDR *xdrs, char **cpp)
766{
767	return xdr_string(xdrs, cpp, RPC_MAXDATASIZE);
768}
769
770/*
771 * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
772 * are in the "non-portable" section because they require that a `long long'
773 * be a 64-bit type.
774 *
775 *	--thorpej@netbsd.org, November 30, 1999
776 */
777
778/*
779 * XDR 64-bit integers
780 */
781bool_t
782xdr_int64_t(XDR *xdrs, int64_t *llp)
783{
784	u_long ul[2];
785
786	switch (xdrs->x_op) {
787	case XDR_ENCODE:
788		ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
789		ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
790		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
791			return (FALSE);
792		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
793	case XDR_DECODE:
794		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
795			return (FALSE);
796		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
797			return (FALSE);
798		*llp = (int64_t)
799		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
800		return (TRUE);
801	case XDR_FREE:
802		return (TRUE);
803	}
804	/* NOTREACHED */
805	return (FALSE);
806}
807
808
809/*
810 * XDR unsigned 64-bit integers
811 */
812bool_t
813xdr_u_int64_t(XDR *xdrs, u_int64_t *ullp)
814{
815	u_long ul[2];
816
817	switch (xdrs->x_op) {
818	case XDR_ENCODE:
819		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
820		ul[1] = (u_long)(*ullp) & 0xffffffff;
821		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
822			return (FALSE);
823		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
824	case XDR_DECODE:
825		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
826			return (FALSE);
827		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
828			return (FALSE);
829		*ullp = (u_int64_t)
830		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
831		return (TRUE);
832	case XDR_FREE:
833		return (TRUE);
834	}
835	/* NOTREACHED */
836	return (FALSE);
837}
838
839/*
840 * XDR unsigned 64-bit integers
841 */
842bool_t
843xdr_uint64_t(XDR *xdrs, uint64_t *ullp)
844{
845	u_long ul[2];
846
847	switch (xdrs->x_op) {
848	case XDR_ENCODE:
849		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
850		ul[1] = (u_long)(*ullp) & 0xffffffff;
851		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
852			return (FALSE);
853		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
854	case XDR_DECODE:
855		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
856			return (FALSE);
857		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
858			return (FALSE);
859		*ullp = (u_int64_t)
860		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
861		return (TRUE);
862	case XDR_FREE:
863		return (TRUE);
864	}
865	/* NOTREACHED */
866	return (FALSE);
867}
868
869
870/*
871 * XDR hypers
872 */
873bool_t
874xdr_hyper(XDR *xdrs, longlong_t *llp)
875{
876
877	/*
878	 * Don't bother open-coding this; it's a fair amount of code.  Just
879	 * call xdr_int64_t().
880	 */
881	return (xdr_int64_t(xdrs, (int64_t *)llp));
882}
883
884
885/*
886 * XDR unsigned hypers
887 */
888bool_t
889xdr_u_hyper(XDR *xdrs, u_longlong_t *ullp)
890{
891
892	/*
893	 * Don't bother open-coding this; it's a fair amount of code.  Just
894	 * call xdr_u_int64_t().
895	 */
896	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
897}
898
899
900/*
901 * XDR longlong_t's
902 */
903bool_t
904xdr_longlong_t(XDR *xdrs, longlong_t *llp)
905{
906
907	/*
908	 * Don't bother open-coding this; it's a fair amount of code.  Just
909	 * call xdr_int64_t().
910	 */
911	return (xdr_int64_t(xdrs, (int64_t *)llp));
912}
913
914
915/*
916 * XDR u_longlong_t's
917 */
918bool_t
919xdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp)
920{
921
922	/*
923	 * Don't bother open-coding this; it's a fair amount of code.  Just
924	 * call xdr_u_int64_t().
925	 */
926	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
927}
928