xdr.c revision 184588
11590Srgrimes/*	$NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $	*/
21590Srgrimes
31590Srgrimes/*
41590Srgrimes * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
51590Srgrimes * unrestricted use provided that this legend is included on all tape
61590Srgrimes * media and as a part of the software program in whole or part.  Users
71590Srgrimes * may copy or modify Sun RPC without charge, but are not authorized
81590Srgrimes * to license or distribute it to anyone else except as part of a product or
91590Srgrimes * program developed by the user.
101590Srgrimes *
111590Srgrimes * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
121590Srgrimes * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
131590Srgrimes * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
141590Srgrimes *
151590Srgrimes * Sun RPC is provided with no support and without any obligation on the
161590Srgrimes * part of Sun Microsystems, Inc. to assist in its use, correction,
171590Srgrimes * modification or enhancement.
181590Srgrimes *
191590Srgrimes * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
201590Srgrimes * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
211590Srgrimes * OR ANY PART THEREOF.
221590Srgrimes *
231590Srgrimes * In no event will Sun Microsystems, Inc. be liable for any lost revenue
241590Srgrimes * or profits or other special, indirect and consequential damages, even if
251590Srgrimes * Sun has been advised of the possibility of such damages.
261590Srgrimes *
271590Srgrimes * Sun Microsystems, Inc.
281590Srgrimes * 2550 Garcia Avenue
291590Srgrimes * Mountain View, California  94043
301590Srgrimes */
311590Srgrimes
321590Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
331590Srgrimesstatic char *sccsid2 = "@(#)xdr.c 1.35 87/08/12";
341590Srgrimesstatic char *sccsid = "@(#)xdr.c	2.1 88/07/29 4.0 RPCSRC";
351590Srgrimes#endif
361590Srgrimes#include <sys/cdefs.h>
371590Srgrimes__FBSDID("$FreeBSD: head/lib/libc/xdr/xdr.c 184588 2008-11-03 10:38:00Z dfr $");
381590Srgrimes
391590Srgrimes/*
401590Srgrimes * xdr.c, Generic XDR routines implementation.
411590Srgrimes *
421590Srgrimes * Copyright (C) 1986, Sun Microsystems, Inc.
431590Srgrimes *
441590Srgrimes * These are the "generic" xdr routines used to serialize and de-serialize
451590Srgrimes * most common data items.  See xdr.h for more info on the interface to
461590Srgrimes * xdr.
471590Srgrimes */
481590Srgrimes
491590Srgrimes#include "namespace.h"
501590Srgrimes#include <err.h>
511590Srgrimes#include <stdio.h>
521590Srgrimes#include <stdlib.h>
531590Srgrimes#include <string.h>
541590Srgrimes
551590Srgrimes#include <rpc/types.h>
561590Srgrimes#include <rpc/xdr.h>
571590Srgrimes#include "un-namespace.h"
581590Srgrimes
591590Srgrimestypedef quad_t          longlong_t;     /* ANSI long long type */
601590Srgrimestypedef u_quad_t        u_longlong_t;   /* ANSI unsigned long long type */
611590Srgrimes
621590Srgrimes/*
631590Srgrimes * constants specific to the xdr "protocol"
641590Srgrimes */
651590Srgrimes#define XDR_FALSE	((long) 0)
661590Srgrimes#define XDR_TRUE	((long) 1)
671590Srgrimes#define LASTUNSIGNED	((u_int) 0-1)
681590Srgrimes
691590Srgrimes/*
701590Srgrimes * for unit alignment
711590Srgrimes */
721590Srgrimesstatic const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
731590Srgrimes
741590Srgrimes/*
751590Srgrimes * Free a data structure using XDR
761590Srgrimes * Not a filter, but a convenient utility nonetheless
771590Srgrimes */
781590Srgrimesvoid
791590Srgrimesxdr_free(proc, objp)
801590Srgrimes	xdrproc_t proc;
811590Srgrimes	void *objp;
821590Srgrimes{
831590Srgrimes	XDR x;
841590Srgrimes
851590Srgrimes	x.x_op = XDR_FREE;
861590Srgrimes	(*proc)(&x, objp);
871590Srgrimes}
881590Srgrimes
891590Srgrimes/*
901590Srgrimes * XDR nothing
911590Srgrimes */
921590Srgrimesbool_t
931590Srgrimesxdr_void(void)
941590Srgrimes{
951590Srgrimes
961590Srgrimes	return (TRUE);
971590Srgrimes}
981590Srgrimes
991590Srgrimes
1001590Srgrimes/*
1011590Srgrimes * XDR integers
1021590Srgrimes */
1031590Srgrimesbool_t
1041590Srgrimesxdr_int(xdrs, ip)
1051590Srgrimes	XDR *xdrs;
1061590Srgrimes	int *ip;
1071590Srgrimes{
1081590Srgrimes	long l;
1091590Srgrimes
1101590Srgrimes	switch (xdrs->x_op) {
1111590Srgrimes
1121590Srgrimes	case XDR_ENCODE:
1131590Srgrimes		l = (long) *ip;
1141590Srgrimes		return (XDR_PUTLONG(xdrs, &l));
1151590Srgrimes
1161590Srgrimes	case XDR_DECODE:
1171590Srgrimes		if (!XDR_GETLONG(xdrs, &l)) {
1181590Srgrimes			return (FALSE);
1191590Srgrimes		}
1201590Srgrimes		*ip = (int) l;
1211590Srgrimes		return (TRUE);
1221590Srgrimes
1231590Srgrimes	case XDR_FREE:
1241590Srgrimes		return (TRUE);
1251590Srgrimes	}
1261590Srgrimes	/* NOTREACHED */
1271590Srgrimes	return (FALSE);
1281590Srgrimes}
1291590Srgrimes
1301590Srgrimes/*
1311590Srgrimes * XDR unsigned integers
1321590Srgrimes */
1331590Srgrimesbool_t
1341590Srgrimesxdr_u_int(xdrs, up)
1351590Srgrimes	XDR *xdrs;
1361590Srgrimes	u_int *up;
1371590Srgrimes{
1381590Srgrimes	u_long l;
1391590Srgrimes
1401590Srgrimes	switch (xdrs->x_op) {
1411590Srgrimes
1421590Srgrimes	case XDR_ENCODE:
1431590Srgrimes		l = (u_long) *up;
1441590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
1451590Srgrimes
1461590Srgrimes	case XDR_DECODE:
1471590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
1481590Srgrimes			return (FALSE);
1491590Srgrimes		}
1501590Srgrimes		*up = (u_int) l;
1511590Srgrimes		return (TRUE);
1521590Srgrimes
1531590Srgrimes	case XDR_FREE:
1541590Srgrimes		return (TRUE);
1551590Srgrimes	}
1561590Srgrimes	/* NOTREACHED */
1571590Srgrimes	return (FALSE);
1581590Srgrimes}
1591590Srgrimes
1601590Srgrimes
1611590Srgrimes/*
1621590Srgrimes * XDR long integers
1631590Srgrimes * same as xdr_u_long - open coded to save a proc call!
1641590Srgrimes */
1651590Srgrimesbool_t
1661590Srgrimesxdr_long(xdrs, lp)
1671590Srgrimes	XDR *xdrs;
1681590Srgrimes	long *lp;
1691590Srgrimes{
1701590Srgrimes	switch (xdrs->x_op) {
1711590Srgrimes	case XDR_ENCODE:
1721590Srgrimes		return (XDR_PUTLONG(xdrs, lp));
1731590Srgrimes	case XDR_DECODE:
1741590Srgrimes		return (XDR_GETLONG(xdrs, lp));
1751590Srgrimes	case XDR_FREE:
1761590Srgrimes		return (TRUE);
1771590Srgrimes	}
1781590Srgrimes	/* NOTREACHED */
1791590Srgrimes	return (FALSE);
1801590Srgrimes}
1811590Srgrimes
1821590Srgrimes/*
1831590Srgrimes * XDR unsigned long integers
1841590Srgrimes * same as xdr_long - open coded to save a proc call!
1851590Srgrimes */
1861590Srgrimesbool_t
1871590Srgrimesxdr_u_long(xdrs, ulp)
1881590Srgrimes	XDR *xdrs;
1891590Srgrimes	u_long *ulp;
1901590Srgrimes{
1911590Srgrimes	switch (xdrs->x_op) {
1921590Srgrimes	case XDR_ENCODE:
1931590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)ulp));
1941590Srgrimes	case XDR_DECODE:
1951590Srgrimes		return (XDR_GETLONG(xdrs, (long *)ulp));
1961590Srgrimes	case XDR_FREE:
1971590Srgrimes		return (TRUE);
1981590Srgrimes	}
1991590Srgrimes	/* NOTREACHED */
2001590Srgrimes	return (FALSE);
2011590Srgrimes}
2021590Srgrimes
2031590Srgrimes
2041590Srgrimes/*
2051590Srgrimes * XDR 32-bit integers
2061590Srgrimes * same as xdr_u_int32_t - open coded to save a proc call!
2071590Srgrimes */
2081590Srgrimesbool_t
2091590Srgrimesxdr_int32_t(xdrs, int32_p)
2101590Srgrimes	XDR *xdrs;
2111590Srgrimes	int32_t *int32_p;
2121590Srgrimes{
2131590Srgrimes	long l;
2141590Srgrimes
2151590Srgrimes	switch (xdrs->x_op) {
2161590Srgrimes
2171590Srgrimes	case XDR_ENCODE:
2181590Srgrimes		l = (long) *int32_p;
2191590Srgrimes		return (XDR_PUTLONG(xdrs, &l));
2201590Srgrimes
2211590Srgrimes	case XDR_DECODE:
2221590Srgrimes		if (!XDR_GETLONG(xdrs, &l)) {
2231590Srgrimes			return (FALSE);
2241590Srgrimes		}
2251590Srgrimes		*int32_p = (int32_t) l;
2261590Srgrimes		return (TRUE);
2271590Srgrimes
2281590Srgrimes	case XDR_FREE:
2291590Srgrimes		return (TRUE);
2301590Srgrimes	}
2311590Srgrimes	/* NOTREACHED */
2321590Srgrimes	return (FALSE);
2331590Srgrimes}
2341590Srgrimes
2351590Srgrimes/*
2361590Srgrimes * XDR unsigned 32-bit integers
2371590Srgrimes * same as xdr_int32_t - open coded to save a proc call!
2381590Srgrimes */
2391590Srgrimesbool_t
2401590Srgrimesxdr_u_int32_t(xdrs, u_int32_p)
2411590Srgrimes	XDR *xdrs;
2421590Srgrimes	u_int32_t *u_int32_p;
2431590Srgrimes{
2441590Srgrimes	u_long l;
2451590Srgrimes
2461590Srgrimes	switch (xdrs->x_op) {
2471590Srgrimes
2481590Srgrimes	case XDR_ENCODE:
2491590Srgrimes		l = (u_long) *u_int32_p;
2501590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
2511590Srgrimes
2521590Srgrimes	case XDR_DECODE:
2531590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
2541590Srgrimes			return (FALSE);
2551590Srgrimes		}
2561590Srgrimes		*u_int32_p = (u_int32_t) l;
2571590Srgrimes		return (TRUE);
2581590Srgrimes
2591590Srgrimes	case XDR_FREE:
2601590Srgrimes		return (TRUE);
2611590Srgrimes	}
2621590Srgrimes	/* NOTREACHED */
2631590Srgrimes	return (FALSE);
2641590Srgrimes}
2651590Srgrimes
2661590Srgrimes/*
2671590Srgrimes * XDR unsigned 32-bit integers
2681590Srgrimes * same as xdr_int32_t - open coded to save a proc call!
2691590Srgrimes */
2701590Srgrimesbool_t
2711590Srgrimesxdr_uint32_t(xdrs, u_int32_p)
2721590Srgrimes	XDR *xdrs;
2731590Srgrimes	uint32_t *u_int32_p;
2741590Srgrimes{
2751590Srgrimes	u_long l;
2761590Srgrimes
2771590Srgrimes	switch (xdrs->x_op) {
2781590Srgrimes
2791590Srgrimes	case XDR_ENCODE:
2801590Srgrimes		l = (u_long) *u_int32_p;
2811590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
2821590Srgrimes
2831590Srgrimes	case XDR_DECODE:
2841590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
2851590Srgrimes			return (FALSE);
2861590Srgrimes		}
2871590Srgrimes		*u_int32_p = (u_int32_t) l;
2881590Srgrimes		return (TRUE);
2891590Srgrimes
2901590Srgrimes	case XDR_FREE:
2911590Srgrimes		return (TRUE);
2921590Srgrimes	}
2931590Srgrimes	/* NOTREACHED */
2941590Srgrimes	return (FALSE);
2951590Srgrimes}
2961590Srgrimes
2971590Srgrimes/*
2981590Srgrimes * XDR short integers
2991590Srgrimes */
3001590Srgrimesbool_t
3011590Srgrimesxdr_short(xdrs, sp)
3021590Srgrimes	XDR *xdrs;
3031590Srgrimes	short *sp;
3041590Srgrimes{
3051590Srgrimes	long l;
3061590Srgrimes
3071590Srgrimes	switch (xdrs->x_op) {
3081590Srgrimes
3091590Srgrimes	case XDR_ENCODE:
3101590Srgrimes		l = (long) *sp;
3111590Srgrimes		return (XDR_PUTLONG(xdrs, &l));
3121590Srgrimes
3131590Srgrimes	case XDR_DECODE:
3141590Srgrimes		if (!XDR_GETLONG(xdrs, &l)) {
3151590Srgrimes			return (FALSE);
3161590Srgrimes		}
3171590Srgrimes		*sp = (short) l;
3181590Srgrimes		return (TRUE);
3191590Srgrimes
3201590Srgrimes	case XDR_FREE:
3211590Srgrimes		return (TRUE);
3221590Srgrimes	}
3231590Srgrimes	/* NOTREACHED */
3241590Srgrimes	return (FALSE);
3251590Srgrimes}
3261590Srgrimes
3271590Srgrimes/*
3281590Srgrimes * XDR unsigned short integers
3291590Srgrimes */
3301590Srgrimesbool_t
3311590Srgrimesxdr_u_short(xdrs, usp)
3321590Srgrimes	XDR *xdrs;
3331590Srgrimes	u_short *usp;
3341590Srgrimes{
3351590Srgrimes	u_long l;
3361590Srgrimes
3371590Srgrimes	switch (xdrs->x_op) {
3381590Srgrimes
3391590Srgrimes	case XDR_ENCODE:
3401590Srgrimes		l = (u_long) *usp;
3411590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
3421590Srgrimes
3431590Srgrimes	case XDR_DECODE:
3441590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
3451590Srgrimes			return (FALSE);
3461590Srgrimes		}
3471590Srgrimes		*usp = (u_short) l;
3481590Srgrimes		return (TRUE);
3491590Srgrimes
3501590Srgrimes	case XDR_FREE:
3511590Srgrimes		return (TRUE);
3521590Srgrimes	}
3531590Srgrimes	/* NOTREACHED */
3541590Srgrimes	return (FALSE);
3551590Srgrimes}
3561590Srgrimes
3571590Srgrimes
3581590Srgrimes/*
3591590Srgrimes * XDR 16-bit integers
3601590Srgrimes */
3611590Srgrimesbool_t
3621590Srgrimesxdr_int16_t(xdrs, int16_p)
3631590Srgrimes	XDR *xdrs;
3641590Srgrimes	int16_t *int16_p;
3651590Srgrimes{
3661590Srgrimes	long l;
3671590Srgrimes
3681590Srgrimes	switch (xdrs->x_op) {
3691590Srgrimes
3701590Srgrimes	case XDR_ENCODE:
3711590Srgrimes		l = (long) *int16_p;
3721590Srgrimes		return (XDR_PUTLONG(xdrs, &l));
3731590Srgrimes
3741590Srgrimes	case XDR_DECODE:
3751590Srgrimes		if (!XDR_GETLONG(xdrs, &l)) {
3761590Srgrimes			return (FALSE);
3771590Srgrimes		}
3781590Srgrimes		*int16_p = (int16_t) l;
3791590Srgrimes		return (TRUE);
3801590Srgrimes
3811590Srgrimes	case XDR_FREE:
3821590Srgrimes		return (TRUE);
3831590Srgrimes	}
3841590Srgrimes	/* NOTREACHED */
3851590Srgrimes	return (FALSE);
3861590Srgrimes}
3871590Srgrimes
3881590Srgrimes/*
3891590Srgrimes * XDR unsigned 16-bit integers
3901590Srgrimes */
3911590Srgrimesbool_t
3921590Srgrimesxdr_u_int16_t(xdrs, u_int16_p)
3931590Srgrimes	XDR *xdrs;
3941590Srgrimes	u_int16_t *u_int16_p;
3951590Srgrimes{
3961590Srgrimes	u_long l;
3971590Srgrimes
3981590Srgrimes	switch (xdrs->x_op) {
3991590Srgrimes
4001590Srgrimes	case XDR_ENCODE:
4011590Srgrimes		l = (u_long) *u_int16_p;
4021590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
4031590Srgrimes
4041590Srgrimes	case XDR_DECODE:
4051590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
4061590Srgrimes			return (FALSE);
4071590Srgrimes		}
4081590Srgrimes		*u_int16_p = (u_int16_t) l;
4091590Srgrimes		return (TRUE);
4101590Srgrimes
4111590Srgrimes	case XDR_FREE:
4121590Srgrimes		return (TRUE);
4131590Srgrimes	}
4141590Srgrimes	/* NOTREACHED */
4151590Srgrimes	return (FALSE);
4161590Srgrimes}
4171590Srgrimes
4181590Srgrimes/*
4191590Srgrimes * XDR unsigned 16-bit integers
4201590Srgrimes */
4211590Srgrimesbool_t
4221590Srgrimesxdr_uint16_t(xdrs, u_int16_p)
4231590Srgrimes	XDR *xdrs;
4241590Srgrimes	uint16_t *u_int16_p;
4251590Srgrimes{
4261590Srgrimes	u_long l;
4271590Srgrimes
4281590Srgrimes	switch (xdrs->x_op) {
4291590Srgrimes
4301590Srgrimes	case XDR_ENCODE:
4311590Srgrimes		l = (u_long) *u_int16_p;
4321590Srgrimes		return (XDR_PUTLONG(xdrs, (long *)&l));
4331590Srgrimes
4341590Srgrimes	case XDR_DECODE:
4351590Srgrimes		if (!XDR_GETLONG(xdrs, (long *)&l)) {
4361590Srgrimes			return (FALSE);
4371590Srgrimes		}
4381590Srgrimes		*u_int16_p = (u_int16_t) l;
4391590Srgrimes		return (TRUE);
4401590Srgrimes
4411590Srgrimes	case XDR_FREE:
4421590Srgrimes		return (TRUE);
4431590Srgrimes	}
4441590Srgrimes	/* NOTREACHED */
4451590Srgrimes	return (FALSE);
4461590Srgrimes}
4471590Srgrimes
4481590Srgrimes
4491590Srgrimes/*
4501590Srgrimes * XDR a char
4511590Srgrimes */
4521590Srgrimesbool_t
4531590Srgrimesxdr_char(xdrs, cp)
4541590Srgrimes	XDR *xdrs;
4551590Srgrimes	char *cp;
4561590Srgrimes{
4571590Srgrimes	int i;
4581590Srgrimes
4591590Srgrimes	i = (*cp);
4601590Srgrimes	if (!xdr_int(xdrs, &i)) {
4611590Srgrimes		return (FALSE);
4621590Srgrimes	}
4631590Srgrimes	*cp = i;
4641590Srgrimes	return (TRUE);
4651590Srgrimes}
4661590Srgrimes
4671590Srgrimes/*
4681590Srgrimes * XDR an unsigned char
4691590Srgrimes */
4701590Srgrimesbool_t
4711590Srgrimesxdr_u_char(xdrs, cp)
472	XDR *xdrs;
473	u_char *cp;
474{
475	u_int u;
476
477	u = (*cp);
478	if (!xdr_u_int(xdrs, &u)) {
479		return (FALSE);
480	}
481	*cp = u;
482	return (TRUE);
483}
484
485/*
486 * XDR booleans
487 */
488bool_t
489xdr_bool(xdrs, bp)
490	XDR *xdrs;
491	bool_t *bp;
492{
493	long lb;
494
495	switch (xdrs->x_op) {
496
497	case XDR_ENCODE:
498		lb = *bp ? XDR_TRUE : XDR_FALSE;
499		return (XDR_PUTLONG(xdrs, &lb));
500
501	case XDR_DECODE:
502		if (!XDR_GETLONG(xdrs, &lb)) {
503			return (FALSE);
504		}
505		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
506		return (TRUE);
507
508	case XDR_FREE:
509		return (TRUE);
510	}
511	/* NOTREACHED */
512	return (FALSE);
513}
514
515/*
516 * XDR enumerations
517 */
518bool_t
519xdr_enum(xdrs, ep)
520	XDR *xdrs;
521	enum_t *ep;
522{
523	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
524
525	/*
526	 * enums are treated as ints
527	 */
528	/* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
529		return (xdr_long(xdrs, (long *)(void *)ep));
530	} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
531		return (xdr_int(xdrs, (int *)(void *)ep));
532	} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
533		return (xdr_short(xdrs, (short *)(void *)ep));
534	} else {
535		return (FALSE);
536	}
537}
538
539/*
540 * XDR opaque data
541 * Allows the specification of a fixed size sequence of opaque bytes.
542 * cp points to the opaque object and cnt gives the byte length.
543 */
544bool_t
545xdr_opaque(xdrs, cp, cnt)
546	XDR *xdrs;
547	caddr_t cp;
548	u_int cnt;
549{
550	u_int rndup;
551	static int crud[BYTES_PER_XDR_UNIT];
552
553	/*
554	 * if no data we are done
555	 */
556	if (cnt == 0)
557		return (TRUE);
558
559	/*
560	 * round byte count to full xdr units
561	 */
562	rndup = cnt % BYTES_PER_XDR_UNIT;
563	if (rndup > 0)
564		rndup = BYTES_PER_XDR_UNIT - rndup;
565
566	if (xdrs->x_op == XDR_DECODE) {
567		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
568			return (FALSE);
569		}
570		if (rndup == 0)
571			return (TRUE);
572		return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
573	}
574
575	if (xdrs->x_op == XDR_ENCODE) {
576		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
577			return (FALSE);
578		}
579		if (rndup == 0)
580			return (TRUE);
581		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
582	}
583
584	if (xdrs->x_op == XDR_FREE) {
585		return (TRUE);
586	}
587
588	return (FALSE);
589}
590
591/*
592 * XDR counted bytes
593 * *cpp is a pointer to the bytes, *sizep is the count.
594 * If *cpp is NULL maxsize bytes are allocated
595 */
596bool_t
597xdr_bytes(xdrs, cpp, sizep, maxsize)
598	XDR *xdrs;
599	char **cpp;
600	u_int *sizep;
601	u_int maxsize;
602{
603	char *sp = *cpp;  /* sp is the actual string pointer */
604	u_int nodesize;
605
606	/*
607	 * first deal with the length since xdr bytes are counted
608	 */
609	if (! xdr_u_int(xdrs, sizep)) {
610		return (FALSE);
611	}
612	nodesize = *sizep;
613	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
614		return (FALSE);
615	}
616
617	/*
618	 * now deal with the actual bytes
619	 */
620	switch (xdrs->x_op) {
621
622	case XDR_DECODE:
623		if (nodesize == 0) {
624			return (TRUE);
625		}
626		if (sp == NULL) {
627			*cpp = sp = mem_alloc(nodesize);
628		}
629		if (sp == NULL) {
630			warnx("xdr_bytes: out of memory");
631			return (FALSE);
632		}
633		/* FALLTHROUGH */
634
635	case XDR_ENCODE:
636		return (xdr_opaque(xdrs, sp, nodesize));
637
638	case XDR_FREE:
639		if (sp != NULL) {
640			mem_free(sp, nodesize);
641			*cpp = NULL;
642		}
643		return (TRUE);
644	}
645	/* NOTREACHED */
646	return (FALSE);
647}
648
649/*
650 * Implemented here due to commonality of the object.
651 */
652bool_t
653xdr_netobj(xdrs, np)
654	XDR *xdrs;
655	struct netobj *np;
656{
657
658	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
659}
660
661/*
662 * XDR a descriminated union
663 * Support routine for discriminated unions.
664 * You create an array of xdrdiscrim structures, terminated with
665 * an entry with a null procedure pointer.  The routine gets
666 * the discriminant value and then searches the array of xdrdiscrims
667 * looking for that value.  It calls the procedure given in the xdrdiscrim
668 * to handle the discriminant.  If there is no specific routine a default
669 * routine may be called.
670 * If there is no specific or default routine an error is returned.
671 */
672bool_t
673xdr_union(xdrs, dscmp, unp, choices, dfault)
674	XDR *xdrs;
675	enum_t *dscmp;		/* enum to decide which arm to work on */
676	char *unp;		/* the union itself */
677	const struct xdr_discrim *choices;	/* [value, xdr proc] for each arm */
678	xdrproc_t dfault;	/* default xdr routine */
679{
680	enum_t dscm;
681
682	/*
683	 * we deal with the discriminator;  it's an enum
684	 */
685	if (! xdr_enum(xdrs, dscmp)) {
686		return (FALSE);
687	}
688	dscm = *dscmp;
689
690	/*
691	 * search choices for a value that matches the discriminator.
692	 * if we find one, execute the xdr routine for that value.
693	 */
694	for (; choices->proc != NULL_xdrproc_t; choices++) {
695		if (choices->value == dscm)
696			return ((*(choices->proc))(xdrs, unp));
697	}
698
699	/*
700	 * no match - execute the default xdr routine if there is one
701	 */
702	return ((dfault == NULL_xdrproc_t) ? FALSE :
703	    (*dfault)(xdrs, unp));
704}
705
706
707/*
708 * Non-portable xdr primitives.
709 * Care should be taken when moving these routines to new architectures.
710 */
711
712
713/*
714 * XDR null terminated ASCII strings
715 * xdr_string deals with "C strings" - arrays of bytes that are
716 * terminated by a NULL character.  The parameter cpp references a
717 * pointer to storage; If the pointer is null, then the necessary
718 * storage is allocated.  The last parameter is the max allowed length
719 * of the string as specified by a protocol.
720 */
721bool_t
722xdr_string(xdrs, cpp, maxsize)
723	XDR *xdrs;
724	char **cpp;
725	u_int maxsize;
726{
727	char *sp = *cpp;  /* sp is the actual string pointer */
728	u_int size;
729	u_int nodesize;
730
731	/*
732	 * first deal with the length since xdr strings are counted-strings
733	 */
734	switch (xdrs->x_op) {
735	case XDR_FREE:
736		if (sp == NULL) {
737			return(TRUE);	/* already free */
738		}
739		/* FALLTHROUGH */
740	case XDR_ENCODE:
741		size = strlen(sp);
742		break;
743	case XDR_DECODE:
744		break;
745	}
746	if (! xdr_u_int(xdrs, &size)) {
747		return (FALSE);
748	}
749	if (size > maxsize) {
750		return (FALSE);
751	}
752	nodesize = size + 1;
753
754	/*
755	 * now deal with the actual bytes
756	 */
757	switch (xdrs->x_op) {
758
759	case XDR_DECODE:
760		if (nodesize == 0) {
761			return (TRUE);
762		}
763		if (sp == NULL)
764			*cpp = sp = mem_alloc(nodesize);
765		if (sp == NULL) {
766			warnx("xdr_string: out of memory");
767			return (FALSE);
768		}
769		sp[size] = 0;
770		/* FALLTHROUGH */
771
772	case XDR_ENCODE:
773		return (xdr_opaque(xdrs, sp, size));
774
775	case XDR_FREE:
776		mem_free(sp, nodesize);
777		*cpp = NULL;
778		return (TRUE);
779	}
780	/* NOTREACHED */
781	return (FALSE);
782}
783
784/*
785 * Wrapper for xdr_string that can be called directly from
786 * routines like clnt_call
787 */
788bool_t
789xdr_wrapstring(xdrs, cpp)
790	XDR *xdrs;
791	char **cpp;
792{
793	return xdr_string(xdrs, cpp, LASTUNSIGNED);
794}
795
796/*
797 * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
798 * are in the "non-portable" section because they require that a `long long'
799 * be a 64-bit type.
800 *
801 *	--thorpej@netbsd.org, November 30, 1999
802 */
803
804/*
805 * XDR 64-bit integers
806 */
807bool_t
808xdr_int64_t(xdrs, llp)
809	XDR *xdrs;
810	int64_t *llp;
811{
812	u_long ul[2];
813
814	switch (xdrs->x_op) {
815	case XDR_ENCODE:
816		ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
817		ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
818		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
819			return (FALSE);
820		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
821	case XDR_DECODE:
822		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
823			return (FALSE);
824		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
825			return (FALSE);
826		*llp = (int64_t)
827		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
828		return (TRUE);
829	case XDR_FREE:
830		return (TRUE);
831	}
832	/* NOTREACHED */
833	return (FALSE);
834}
835
836
837/*
838 * XDR unsigned 64-bit integers
839 */
840bool_t
841xdr_u_int64_t(xdrs, ullp)
842	XDR *xdrs;
843	u_int64_t *ullp;
844{
845	u_long ul[2];
846
847	switch (xdrs->x_op) {
848	case XDR_ENCODE:
849		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
850		ul[1] = (u_long)(*ullp) & 0xffffffff;
851		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
852			return (FALSE);
853		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
854	case XDR_DECODE:
855		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
856			return (FALSE);
857		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
858			return (FALSE);
859		*ullp = (u_int64_t)
860		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
861		return (TRUE);
862	case XDR_FREE:
863		return (TRUE);
864	}
865	/* NOTREACHED */
866	return (FALSE);
867}
868
869/*
870 * XDR unsigned 64-bit integers
871 */
872bool_t
873xdr_uint64_t(xdrs, ullp)
874	XDR *xdrs;
875	uint64_t *ullp;
876{
877	u_long ul[2];
878
879	switch (xdrs->x_op) {
880	case XDR_ENCODE:
881		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
882		ul[1] = (u_long)(*ullp) & 0xffffffff;
883		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
884			return (FALSE);
885		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
886	case XDR_DECODE:
887		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
888			return (FALSE);
889		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
890			return (FALSE);
891		*ullp = (u_int64_t)
892		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
893		return (TRUE);
894	case XDR_FREE:
895		return (TRUE);
896	}
897	/* NOTREACHED */
898	return (FALSE);
899}
900
901
902/*
903 * XDR hypers
904 */
905bool_t
906xdr_hyper(xdrs, llp)
907	XDR *xdrs;
908	longlong_t *llp;
909{
910
911	/*
912	 * Don't bother open-coding this; it's a fair amount of code.  Just
913	 * call xdr_int64_t().
914	 */
915	return (xdr_int64_t(xdrs, (int64_t *)llp));
916}
917
918
919/*
920 * XDR unsigned hypers
921 */
922bool_t
923xdr_u_hyper(xdrs, ullp)
924	XDR *xdrs;
925	u_longlong_t *ullp;
926{
927
928	/*
929	 * Don't bother open-coding this; it's a fair amount of code.  Just
930	 * call xdr_u_int64_t().
931	 */
932	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
933}
934
935
936/*
937 * XDR longlong_t's
938 */
939bool_t
940xdr_longlong_t(xdrs, llp)
941	XDR *xdrs;
942	longlong_t *llp;
943{
944
945	/*
946	 * Don't bother open-coding this; it's a fair amount of code.  Just
947	 * call xdr_int64_t().
948	 */
949	return (xdr_int64_t(xdrs, (int64_t *)llp));
950}
951
952
953/*
954 * XDR u_longlong_t's
955 */
956bool_t
957xdr_u_longlong_t(xdrs, ullp)
958	XDR *xdrs;
959	u_longlong_t *ullp;
960{
961
962	/*
963	 * Don't bother open-coding this; it's a fair amount of code.  Just
964	 * call xdr_u_int64_t().
965	 */
966	return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
967}
968