/* $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*/135typedef bool_t (*xdrproc_t)(XDR *, void *);136137/*138* Operations defined on a XDR handle139*140* XDR *xdrs;141* long *longp;142* char * addr;143* u_int len;144* u_int pos;145*/146#define XDR_GETLONG(xdrs, longp) \147(*(xdrs)->x_ops->x_getlong)(xdrs, longp)148#define xdr_getlong(xdrs, longp) \149(*(xdrs)->x_ops->x_getlong)(xdrs, longp)150151#define XDR_PUTLONG(xdrs, longp) \152(*(xdrs)->x_ops->x_putlong)(xdrs, longp)153#define xdr_putlong(xdrs, longp) \154(*(xdrs)->x_ops->x_putlong)(xdrs, longp)155156static __inline int157xdr_getint32(XDR *xdrs, int32_t *ip)158{159long l;160161if (!xdr_getlong(xdrs, &l))162return (FALSE);163*ip = (int32_t)l;164return (TRUE);165}166167static __inline int168xdr_putint32(XDR *xdrs, int32_t *ip)169{170long l;171172l = (long)*ip;173return xdr_putlong(xdrs, &l);174}175176#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p)177#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p)178179#define XDR_GETBYTES(xdrs, addr, len) \180(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)181#define xdr_getbytes(xdrs, addr, len) \182(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)183184#define XDR_PUTBYTES(xdrs, addr, len) \185(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)186#define xdr_putbytes(xdrs, addr, len) \187(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)188189#define XDR_PUTMBUF(xdrs, mbuf) \190(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)191#define xdr_putmbuf(xdrs, mbuf) \192(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)193194#define XDR_GETPOS(xdrs) \195(*(xdrs)->x_ops->x_getpostn)(xdrs)196#define xdr_getpos(xdrs) \197(*(xdrs)->x_ops->x_getpostn)(xdrs)198199#define XDR_SETPOS(xdrs, pos) \200(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)201#define xdr_setpos(xdrs, pos) \202(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)203204#define XDR_INLINE(xdrs, len) \205(*(xdrs)->x_ops->x_inline)(xdrs, len)206#define xdr_inline(xdrs, len) \207(*(xdrs)->x_ops->x_inline)(xdrs, len)208209#define XDR_DESTROY(xdrs) \210if ((xdrs)->x_ops->x_destroy) \211(*(xdrs)->x_ops->x_destroy)(xdrs)212#define xdr_destroy(xdrs) \213if ((xdrs)->x_ops->x_destroy) \214(*(xdrs)->x_ops->x_destroy)(xdrs)215216#define XDR_CONTROL(xdrs, req, op) \217(((xdrs)->x_ops->x_control == NULL) ? (FALSE) : \218(*(xdrs)->x_ops->x_control)(xdrs, req, op))219#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op)220221/*222* Solaris strips the '_t' from these types -- not sure why.223* But, let's be compatible.224*/225#define xdr_rpcvers(xdrs, versp) xdr_uint32_t(xdrs, versp)226#define xdr_rpcprog(xdrs, progp) xdr_uint32_t(xdrs, progp)227#define xdr_rpcproc(xdrs, procp) xdr_uint32_t(xdrs, procp)228#define xdr_rpcprot(xdrs, protp) xdr_uint32_t(xdrs, protp)229#define xdr_rpcport(xdrs, portp) xdr_uint32_t(xdrs, portp)230231/*232* Support struct for discriminated unions.233* You create an array of xdrdiscrim structures, terminated with234* an entry with a null procedure pointer. The xdr_union routine gets235* the discriminant value and then searches the array of structures236* for a matching value. If a match is found the associated xdr routine237* is called to handle that part of the union. If there is238* no match, then a default routine may be called.239* If there is no match and no default routine it is an error.240*/241#define NULL_xdrproc_t ((xdrproc_t)0)242struct xdr_discrim {243int value;244xdrproc_t proc;245};246247/*248* In-line routines for fast encode/decode of primitive data types.249* Caveat emptor: these use single memory cycles to get the250* data from the underlying buffer, and will fail to operate251* properly if the data is not aligned. The standard way to use these252* is to say:253* if ((buf = XDR_INLINE(xdrs, count)) == NULL)254* return (FALSE);255* <<< macro calls >>>256* where ``count'' is the number of bytes of data occupied257* by the primitive data types.258*259* N.B. and frozen for all time: each data type here uses 4 bytes260* of external representation.261*/262#define IXDR_GET_INT32(buf) ((int32_t)__ntohl((uint32_t)*(buf)++))263#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v))264#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf))265#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))266267#define IXDR_GET_UINT32(buf) ((uint32_t)IXDR_GET_INT32(buf))268#define IXDR_PUT_UINT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))269270#define IXDR_GET_LONG(buf) ((long)__ntohl((uint32_t)*(buf)++))271#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v))272273#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))274#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))275#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))276#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))277#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))278279#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v))280#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v))281#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v))282#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))283#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))284285/*286* These are the "generic" xdr routines.287*/288__BEGIN_DECLS289extern bool_t xdr_void(XDR *, void *);290extern bool_t xdr_int(XDR *, int *);291extern bool_t xdr_u_int(XDR *, u_int *);292extern bool_t xdr_long(XDR *, long *);293extern bool_t xdr_u_long(XDR *, u_long *);294extern bool_t xdr_short(XDR *, short *);295extern bool_t xdr_u_short(XDR *, u_short *);296extern bool_t xdr_int16_t(XDR *, int16_t *);297extern bool_t xdr_uint16_t(XDR *, uint16_t *);298extern bool_t xdr_int32_t(XDR *, int32_t *);299extern bool_t xdr_uint32_t(XDR *, uint32_t *);300extern bool_t xdr_int64_t(XDR *, int64_t *);301extern bool_t xdr_uint64_t(XDR *, uint64_t *);302extern bool_t xdr_bool(XDR *, bool_t *);303extern bool_t xdr_enum(XDR *, enum_t *);304extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t);305extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int);306extern bool_t xdr_opaque(XDR *, char *, u_int);307extern bool_t xdr_string(XDR *, char **, u_int);308extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t);309extern bool_t xdr_char(XDR *, char *);310extern bool_t xdr_u_char(XDR *, u_char *);311extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);312extern bool_t xdr_float(XDR *, float *);313extern bool_t xdr_double(XDR *, double *);314extern bool_t xdr_quadruple(XDR *, long double *);315extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t);316extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t);317extern bool_t xdr_wrapstring(XDR *, char **);318extern void xdr_free(xdrproc_t, void *);319extern bool_t xdr_hyper(XDR *, quad_t *);320extern bool_t xdr_u_hyper(XDR *, u_quad_t *);321extern bool_t xdr_longlong_t(XDR *, quad_t *);322extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *);323extern unsigned long xdr_sizeof(xdrproc_t func, void *data);324__END_DECLS325326/*327* Common opaque bytes objects used by many rpc protocols;328* declared here due to commonality.329*/330#define MAX_NETOBJ_SZ 1024331struct netobj {332u_int n_len;333char *n_bytes;334};335typedef struct netobj netobj;336extern bool_t xdr_netobj(XDR *, struct netobj *);337338/*339* These are XDR control operators340*/341342#define XDR_GET_BYTES_AVAIL 1343#define XDR_PEEK 2344#define XDR_SKIPBYTES 3345346struct xdr_bytesrec {347bool_t xc_is_last_record;348size_t xc_num_avail;349};350351typedef struct xdr_bytesrec xdr_bytesrec;352353354/*355* These are the public routines for the various implementations of356* xdr streams.357*/358__BEGIN_DECLS359/* XDR using memory buffers */360extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op);361362/* XDR using mbufs */363extern void xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op);364extern struct mbuf * xdrmbuf_getall(XDR *);365366/* XDR pseudo records for tcp */367extern void xdrrec_create(XDR *, u_int, u_int, void *,368int (*)(void *, void *, int),369int (*)(void *, void *, int));370371/* make end of xdr record */372extern bool_t xdrrec_endofrecord(XDR *, int);373374/* move to beginning of next record */375extern bool_t xdrrec_skiprecord(XDR *);376377/* true if no more input */378extern bool_t xdrrec_eof(XDR *);379extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int);380__END_DECLS381382#endif /* !_KRPC_XDR_H */383384385