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