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