/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 2009, Sun Microsystems, Inc.6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions are met:10* - Redistributions of source code must retain the above copyright notice,11* this list of conditions and the following disclaimer.12* - Redistributions in binary form must reproduce the above copyright notice,13* this list of conditions and the following disclaimer in the documentation14* and/or other materials provided with the distribution.15* - Neither the name of Sun Microsystems, Inc. nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"20* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE23* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR24* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF25* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS26* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN27* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE29* POSSIBILITY OF SUCH DAMAGE.30*/3132/*33* xdr.h, External Data Representation Serialization Routines.34*35* Copyright (C) 1984, Sun Microsystems, Inc.36*/3738#ifndef _KRPC_XDR_H39#define _KRPC_XDR_H40#include <sys/cdefs.h>4142struct mbuf;4344/*45* XDR provides a conventional way for converting between C data46* types and an external bit-string representation. Library supplied47* routines provide for the conversion on built-in C data types. These48* routines and utility routines defined here are used to help implement49* a type encode/decode routine for each user-defined type.50*51* Each data type provides a single procedure which takes two arguments:52*53* bool_t54* xdrproc(xdrs, argresp)55* XDR *xdrs;56* <type> *argresp;57*58* xdrs is an instance of a XDR handle, to which or from which the data59* type is to be converted. argresp is a pointer to the structure to be60* converted. The XDR handle contains an operation field which indicates61* which of the operations (ENCODE, DECODE * or FREE) is to be performed.62*63* XDR_DECODE may allocate space if the pointer argresp is null. This64* data can be freed with the XDR_FREE operation.65*66* We write only one procedure per data type to make it easy67* to keep the encode and decode procedures for a data type consistent.68* In many cases the same code performs all operations on a user defined type,69* because all the hard work is done in the component type routines.70* decode as a series of calls on the nested data types.71*/7273/*74* Xdr operations. XDR_ENCODE causes the type to be encoded into the75* stream. XDR_DECODE causes the type to be extracted from the stream.76* XDR_FREE can be used to release the space allocated by an XDR_DECODE77* request.78*/79enum xdr_op {80XDR_ENCODE=0,81XDR_DECODE=1,82XDR_FREE=283};8485/*86* This is the number of bytes per unit of external data.87*/88#define BYTES_PER_XDR_UNIT (4)89#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \90* BYTES_PER_XDR_UNIT)9192/*93* The XDR handle.94* Contains operation which is being applied to the stream,95* an operations vector for the particular implementation (e.g. see xdr_mem.c),96* and two private fields for the use of the particular implementation.97*/98typedef struct XDR {99enum xdr_op x_op; /* operation; fast additional param */100const struct xdr_ops {101/* get a long from underlying stream */102bool_t (*x_getlong)(struct XDR *, long *);103/* put a long to " */104bool_t (*x_putlong)(struct XDR *, const long *);105/* get some bytes from " */106bool_t (*x_getbytes)(struct XDR *, char *, u_int);107/* put some bytes to " */108bool_t (*x_putbytes)(struct XDR *, const char *, u_int);109/* put mbuf or copy its bytes */110bool_t (*x_putmbuf)(struct XDR *, struct mbuf *);111/* returns bytes off from beginning */112u_int (*x_getpostn)(struct XDR *);113/* lets you reposition the stream */114bool_t (*x_setpostn)(struct XDR *, u_int);115/* buf quick ptr to buffered data */116int32_t *(*x_inline)(struct XDR *, u_int);117/* free privates of this xdr_stream */118void (*x_destroy)(struct XDR *);119bool_t (*x_control)(struct XDR *, int, void *);120} *x_ops;121char * x_public; /* users' data */122void * x_private; /* pointer to private data */123char * x_base; /* private used for position info */124u_int x_handy; /* extra private word */125} XDR;126127/*128* A xdrproc_t exists for each data type which is to be encoded or decoded.129*130* The second argument to the xdrproc_t is a pointer to an opaque pointer.131* The opaque pointer generally points to a structure of the data type132* to be decoded. If this pointer is 0, then the type routines should133* allocate dynamic storage of the appropriate size and return it.134*/135#ifdef _KERNEL136typedef bool_t (*xdrproc_t)(XDR *, void *, ...);137#else138/*139* XXX can't actually prototype it, because some take three args!!!140*/141typedef bool_t (*xdrproc_t)(XDR *, ...);142#endif143144/*145* Operations defined on a XDR handle146*147* XDR *xdrs;148* long *longp;149* char * addr;150* u_int len;151* u_int pos;152*/153#define XDR_GETLONG(xdrs, longp) \154(*(xdrs)->x_ops->x_getlong)(xdrs, longp)155#define xdr_getlong(xdrs, longp) \156(*(xdrs)->x_ops->x_getlong)(xdrs, longp)157158#define XDR_PUTLONG(xdrs, longp) \159(*(xdrs)->x_ops->x_putlong)(xdrs, longp)160#define xdr_putlong(xdrs, longp) \161(*(xdrs)->x_ops->x_putlong)(xdrs, longp)162163static __inline int164xdr_getint32(XDR *xdrs, int32_t *ip)165{166long l;167168if (!xdr_getlong(xdrs, &l))169return (FALSE);170*ip = (int32_t)l;171return (TRUE);172}173174static __inline int175xdr_putint32(XDR *xdrs, int32_t *ip)176{177long l;178179l = (long)*ip;180return xdr_putlong(xdrs, &l);181}182183#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p)184#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p)185186#define XDR_GETBYTES(xdrs, addr, len) \187(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)188#define xdr_getbytes(xdrs, addr, len) \189(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)190191#define XDR_PUTBYTES(xdrs, addr, len) \192(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)193#define xdr_putbytes(xdrs, addr, len) \194(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)195196#define XDR_PUTMBUF(xdrs, mbuf) \197(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)198#define xdr_putmbuf(xdrs, mbuf) \199(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)200201#define XDR_GETPOS(xdrs) \202(*(xdrs)->x_ops->x_getpostn)(xdrs)203#define xdr_getpos(xdrs) \204(*(xdrs)->x_ops->x_getpostn)(xdrs)205206#define XDR_SETPOS(xdrs, pos) \207(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)208#define xdr_setpos(xdrs, pos) \209(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)210211#define XDR_INLINE(xdrs, len) \212(*(xdrs)->x_ops->x_inline)(xdrs, len)213#define xdr_inline(xdrs, len) \214(*(xdrs)->x_ops->x_inline)(xdrs, len)215216#define XDR_DESTROY(xdrs) \217if ((xdrs)->x_ops->x_destroy) \218(*(xdrs)->x_ops->x_destroy)(xdrs)219#define xdr_destroy(xdrs) \220if ((xdrs)->x_ops->x_destroy) \221(*(xdrs)->x_ops->x_destroy)(xdrs)222223#define XDR_CONTROL(xdrs, req, op) \224(((xdrs)->x_ops->x_control == NULL) ? (FALSE) : \225(*(xdrs)->x_ops->x_control)(xdrs, req, op))226#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op)227228/*229* Solaris strips the '_t' from these types -- not sure why.230* But, let's be compatible.231*/232#define xdr_rpcvers(xdrs, versp) xdr_uint32_t(xdrs, versp)233#define xdr_rpcprog(xdrs, progp) xdr_uint32_t(xdrs, progp)234#define xdr_rpcproc(xdrs, procp) xdr_uint32_t(xdrs, procp)235#define xdr_rpcprot(xdrs, protp) xdr_uint32_t(xdrs, protp)236#define xdr_rpcport(xdrs, portp) xdr_uint32_t(xdrs, portp)237238/*239* Support struct for discriminated unions.240* You create an array of xdrdiscrim structures, terminated with241* an entry with a null procedure pointer. The xdr_union routine gets242* the discriminant value and then searches the array of structures243* for a matching value. If a match is found the associated xdr routine244* is called to handle that part of the union. If there is245* no match, then a default routine may be called.246* If there is no match and no default routine it is an error.247*/248#define NULL_xdrproc_t ((xdrproc_t)0)249struct xdr_discrim {250int value;251xdrproc_t proc;252};253254/*255* In-line routines for fast encode/decode of primitive data types.256* Caveat emptor: these use single memory cycles to get the257* data from the underlying buffer, and will fail to operate258* properly if the data is not aligned. The standard way to use these259* is to say:260* if ((buf = XDR_INLINE(xdrs, count)) == NULL)261* return (FALSE);262* <<< macro calls >>>263* where ``count'' is the number of bytes of data occupied264* by the primitive data types.265*266* N.B. and frozen for all time: each data type here uses 4 bytes267* of external representation.268*/269#define IXDR_GET_INT32(buf) ((int32_t)__ntohl((uint32_t)*(buf)++))270#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v))271#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf))272#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))273274#define IXDR_GET_UINT32(buf) ((uint32_t)IXDR_GET_INT32(buf))275#define IXDR_PUT_UINT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))276277#define IXDR_GET_LONG(buf) ((long)__ntohl((uint32_t)*(buf)++))278#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v))279280#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))281#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))282#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))283#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))284#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))285286#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v))287#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v))288#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v))289#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))290#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))291292/*293* These are the "generic" xdr routines.294*/295__BEGIN_DECLS296extern bool_t xdr_void(XDR *, void *);297extern bool_t xdr_int(XDR *, int *);298extern bool_t xdr_u_int(XDR *, u_int *);299extern bool_t xdr_long(XDR *, long *);300extern bool_t xdr_u_long(XDR *, u_long *);301extern bool_t xdr_short(XDR *, short *);302extern bool_t xdr_u_short(XDR *, u_short *);303extern bool_t xdr_int16_t(XDR *, int16_t *);304extern bool_t xdr_uint16_t(XDR *, uint16_t *);305extern bool_t xdr_int32_t(XDR *, int32_t *);306extern bool_t xdr_uint32_t(XDR *, uint32_t *);307extern bool_t xdr_int64_t(XDR *, int64_t *);308extern bool_t xdr_uint64_t(XDR *, uint64_t *);309extern bool_t xdr_bool(XDR *, bool_t *);310extern bool_t xdr_enum(XDR *, enum_t *);311extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t);312extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int);313extern bool_t xdr_opaque(XDR *, char *, u_int);314extern bool_t xdr_string(XDR *, char **, u_int);315extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t);316extern bool_t xdr_char(XDR *, char *);317extern bool_t xdr_u_char(XDR *, u_char *);318extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);319extern bool_t xdr_float(XDR *, float *);320extern bool_t xdr_double(XDR *, double *);321extern bool_t xdr_quadruple(XDR *, long double *);322extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t);323extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t);324extern bool_t xdr_wrapstring(XDR *, char **);325extern void xdr_free(xdrproc_t, void *);326extern bool_t xdr_hyper(XDR *, quad_t *);327extern bool_t xdr_u_hyper(XDR *, u_quad_t *);328extern bool_t xdr_longlong_t(XDR *, quad_t *);329extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *);330extern unsigned long xdr_sizeof(xdrproc_t func, void *data);331__END_DECLS332333/*334* Common opaque bytes objects used by many rpc protocols;335* declared here due to commonality.336*/337#define MAX_NETOBJ_SZ 1024338struct netobj {339u_int n_len;340char *n_bytes;341};342typedef struct netobj netobj;343extern bool_t xdr_netobj(XDR *, struct netobj *);344345/*346* These are XDR control operators347*/348349#define XDR_GET_BYTES_AVAIL 1350#define XDR_PEEK 2351#define XDR_SKIPBYTES 3352353struct xdr_bytesrec {354bool_t xc_is_last_record;355size_t xc_num_avail;356};357358typedef struct xdr_bytesrec xdr_bytesrec;359360361/*362* These are the public routines for the various implementations of363* xdr streams.364*/365__BEGIN_DECLS366/* XDR using memory buffers */367extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op);368369/* XDR using mbufs */370extern void xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op);371extern struct mbuf * xdrmbuf_getall(XDR *);372373/* XDR pseudo records for tcp */374extern void xdrrec_create(XDR *, u_int, u_int, void *,375int (*)(void *, void *, int),376int (*)(void *, void *, int));377378/* make end of xdr record */379extern bool_t xdrrec_endofrecord(XDR *, int);380381/* move to beginning of next record */382extern bool_t xdrrec_skiprecord(XDR *);383384/* true if no more input */385extern bool_t xdrrec_eof(XDR *);386extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int);387__END_DECLS388389#endif /* !_KRPC_XDR_H */390391392