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