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