1/* $NetBSD: xdr.h,v 1.3 2024/02/05 21:46:04 andvar Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 * 31 * from: @(#)xdr.h 1.19 87/04/22 SMI 32 * @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC 33 */ 34 35/* 36 * xdr.h, External Data Representation Serialization Routines. 37 * 38 * Copyright (C) 1984, Sun Microsystems, Inc. 39 */ 40 41#ifndef _RPC_XDR_H_ 42#define _RPC_XDR_H_ 43#include <sys/cdefs.h> 44 45/* 46 * XDR provides a conventional way for converting between C data 47 * types and an external bit-string representation. Library supplied 48 * routines provide for the conversion on built-in C data types. These 49 * routines and utility routines defined here are used to help implement 50 * a type encode/decode routine for each user-defined type. 51 * 52 * Each data type provides a single procedure which takes two arguments: 53 * 54 * bool_t 55 * xdrproc(xdrs, argresp) 56 * XDR *xdrs; 57 * <type> *argresp; 58 * 59 * xdrs is an instance of a XDR handle, to which or from which the data 60 * type is to be converted. argresp is a pointer to the structure to be 61 * converted. The XDR handle contains an operation field which indicates 62 * which of the operations (ENCODE, DECODE * or FREE) is to be performed. 63 * 64 * XDR_DECODE may allocate space if the pointer argresp is null. This 65 * data can be freed with the XDR_FREE operation. 66 * 67 * We write only one procedure per data type to make it easy 68 * to keep the encode and decode procedures for a data type consistent. 69 * In many cases the same code performs all operations on a user defined type, 70 * because all the hard work is done in the component type routines. 71 * decode as a series of calls on the nested data types. 72 */ 73 74/* 75 * Xdr operations. XDR_ENCODE causes the type to be encoded into the 76 * stream. XDR_DECODE causes the type to be extracted from the stream. 77 * XDR_FREE can be used to release the space allocated by an XDR_DECODE 78 * request. 79 */ 80enum xdr_op { 81 XDR_ENCODE=0, 82 XDR_DECODE=1, 83 XDR_FREE=2 84}; 85 86/* 87 * This is the number of bytes per unit of external data. 88 */ 89#define BYTES_PER_XDR_UNIT (4) 90#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ 91 * BYTES_PER_XDR_UNIT) 92 93/* 94 * The XDR handle. 95 * Contains operation which is being applied to the stream, 96 * an operations vector for the particular implementation (e.g. see xdr_mem.c), 97 * and two private fields for the use of the particular implementation. 98 */ 99typedef struct __rpc_xdr { 100 enum xdr_op x_op; /* operation; fast additional param */ 101 const struct xdr_ops { 102 /* get a long from underlying stream */ 103 bool_t (*x_getlong)(struct __rpc_xdr *, long *); 104 /* put a long to " */ 105 bool_t (*x_putlong)(struct __rpc_xdr *, const long *); 106 /* get some bytes from " */ 107 bool_t (*x_getbytes)(struct __rpc_xdr *, char *, unsigned int); 108 /* put some bytes to " */ 109 bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, 110 unsigned int); 111 /* returns bytes off from beginning */ 112 unsigned (*x_getpostn)(struct __rpc_xdr *); 113 /* lets you reposition the stream */ 114 bool_t (*x_setpostn)(struct __rpc_xdr *, unsigned int); 115 /* buf quick ptr to buffered data */ 116 int32_t *(*x_inline)(struct __rpc_xdr *, unsigned int); 117 /* free privates of this xdr_stream */ 118 void (*x_destroy)(struct __rpc_xdr *); 119 bool_t (*x_control)(struct __rpc_xdr *, int, void *); 120 } *x_ops; 121 char * x_public; /* users' data */ 122 void * x_private; /* pointer to private data */ 123 char * x_base; /* private used for position info */ 124 unsigned int x_handy; /* extra private word */ 125} XDR; 126 127/* 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 type 132 * to be decoded. If this pointer is 0, then the type routines should 133 * allocate dynamic storage of the appropriate size and return it. 134 */ 135typedef bool_t (*xdrproc_t)(XDR *, const void *); 136 137/* 138 * Operations defined on a XDR handle 139 * 140 * XDR *xdrs; 141 * long *longp; 142 * char * addr; 143 * unsigned len; 144 * unsigned 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) 150 151#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) 155 156static __inline int 157xdr_getint32(XDR *xdrs, int32_t *ip) 158{ 159 long l; 160 161 if (!xdr_getlong(xdrs, &l)) 162 return 0; 163 *ip = (int32_t)l; 164 return 1; 165} 166 167static __inline int 168xdr_putint32(XDR *xdrs, int32_t *ip) 169{ 170 long l; 171 172 l = (long)*ip; 173 return xdr_putlong(xdrs, &l); 174} 175 176#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) 177#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) 178 179#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) 183 184#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) 188 189#define XDR_GETPOS(xdrs) \ 190 (*(xdrs)->x_ops->x_getpostn)(xdrs) 191#define xdr_getpos(xdrs) \ 192 (*(xdrs)->x_ops->x_getpostn)(xdrs) 193 194#define XDR_SETPOS(xdrs, pos) \ 195 (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) 196#define xdr_setpos(xdrs, pos) \ 197 (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) 198 199#define XDR_INLINE(xdrs, len) \ 200 (*(xdrs)->x_ops->x_inline)(xdrs, len) 201#define xdr_inline(xdrs, len) \ 202 (*(xdrs)->x_ops->x_inline)(xdrs, len) 203 204#define XDR_DESTROY(xdrs) \ 205 if ((xdrs)->x_ops->x_destroy) \ 206 (*(xdrs)->x_ops->x_destroy)(xdrs) 207#define xdr_destroy(xdrs) \ 208 if ((xdrs)->x_ops->x_destroy) \ 209 (*(xdrs)->x_ops->x_destroy)(xdrs) 210 211#define XDR_CONTROL(xdrs, req, op) \ 212 (((xdrs)->x_ops->x_control == NULL) ? (FALSE) : \ 213 (*(xdrs)->x_ops->x_control)(xdrs, req, op)) 214#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op) 215 216#define xdr_rpcvers(xdrs, versp) xdr_u_int32_t(xdrs, versp) 217#define xdr_rpcprog(xdrs, progp) xdr_u_int32_t(xdrs, progp) 218#define xdr_rpcproc(xdrs, procp) xdr_u_int32_t(xdrs, procp) 219#define xdr_rpcprot(xdrs, protp) xdr_u_int32_t(xdrs, protp) 220#define xdr_rpcport(xdrs, portp) xdr_u_int32_t(xdrs, portp) 221 222/* 223 * Support struct for discriminated unions. 224 * You create an array of xdrdiscrim structures, terminated with 225 * a entry with a null procedure pointer. The xdr_union routine gets 226 * the discriminant value and then searches the array of structures 227 * for a matching value. If a match is found the associated xdr routine 228 * is called to handle that part of the union. If there is 229 * no match, then a default routine may be called. 230 * If there is no match and no default routine it is an error. 231 */ 232#define NULL_xdrproc_t ((xdrproc_t)0) 233struct xdr_discrim { 234 int value; 235 xdrproc_t proc; 236}; 237 238/* 239 * In-line routines for fast encode/decode of primitive data types. 240 * Caveat emptor: these use single memory cycles to get the 241 * data from the underlying buffer, and will fail to operate 242 * properly if the data is not aligned. The standard way to use these 243 * is to say: 244 * if ((buf = XDR_INLINE(xdrs, count)) == NULL) 245 * return (0); 246 * <<< macro calls >>> 247 * where ``count'' is the number of bytes of data occupied 248 * by the primitive data types. 249 * 250 * N.B. and frozen for all time: each data type here uses 4 bytes 251 * of external representation. 252 */ 253#define IXDR_GET_INT32(buf) ((int32_t)ntohl((uint32_t)*(buf)++)) 254#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)htonl((uint32_t)v)) 255#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) 256#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) 257 258#define IXDR_GET_LONG(buf) ((long)ntohl((uint32_t)*(buf)++)) 259#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)htonl((uint32_t)v)) 260 261#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) 262#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) 263#define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf)) 264#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) 265#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf)) 266 267#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v)) 268#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v)) 269#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v)) 270#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) 271#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) 272 273/* 274 * These are the "generic" xdr routines. 275 */ 276__BEGIN_DECLS 277extern bool_t xdr_void(void); 278extern bool_t xdr_int(XDR *, int *); 279extern bool_t xdr_u_int(XDR *, unsigned int *); 280extern bool_t xdr_long(XDR *, long *); 281extern bool_t xdr_u_long(XDR *, unsigned long *); 282extern bool_t xdr_short(XDR *, short *); 283extern bool_t xdr_u_short(XDR *, unsigned short *); 284extern bool_t xdr_int16_t(XDR *, int16_t *); 285extern bool_t xdr_u_int16_t(XDR *, uint16_t *); 286extern bool_t xdr_int32_t(XDR *, int32_t *); 287extern bool_t xdr_u_int32_t(XDR *, uint32_t *); 288extern bool_t xdr_int64_t(XDR *, int64_t *); 289extern bool_t xdr_u_int64_t(XDR *, uint64_t *); 290extern bool_t xdr_bool(XDR *, bool_t *); 291extern bool_t xdr_enum(XDR *, enum_t *); 292extern bool_t xdr_array(XDR *, char **, unsigned int *, unsigned int, 293 unsigned int, xdrproc_t); 294extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int); 295extern bool_t xdr_opaque(XDR *, char *, unsigned int); 296extern bool_t xdr_string(XDR *, char **, unsigned int); 297extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); 298extern bool_t xdr_char(XDR *, char *); 299extern bool_t xdr_u_char(XDR *, unsigned char *); 300extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, 301 xdrproc_t); 302extern bool_t xdr_float(XDR *, float *); 303extern bool_t xdr_double(XDR *, double *); 304extern bool_t xdr_quadruple(XDR *, long double *); 305extern bool_t xdr_reference(XDR *, char **, unsigned int, xdrproc_t); 306extern bool_t xdr_pointer(XDR *, char **, unsigned int, xdrproc_t); 307extern bool_t xdr_wrapstring(XDR *, char **); 308extern void xdr_free(xdrproc_t, char *); 309extern bool_t xdr_hyper(XDR *, longlong_t *); 310extern bool_t xdr_u_hyper(XDR *, u_longlong_t *); 311extern bool_t xdr_longlong_t(XDR *, longlong_t *); 312extern bool_t xdr_u_longlong_t(XDR *, u_longlong_t *); 313extern unsigned long xdr_sizeof(xdrproc_t, void *); 314__END_DECLS 315 316/* 317 * Common opaque bytes objects used by many rpc protocols; 318 * declared here due to commonality. 319 */ 320#define MAX_NETOBJ_SZ 1024 321struct netobj { 322 unsigned int n_len; 323 char *n_bytes; 324}; 325typedef struct netobj netobj; 326extern bool_t xdr_netobj(XDR *, struct netobj *); 327 328/* 329 * These are XDR control operators 330 */ 331 332#define XDR_GET_BYTES_AVAIL 1 333 334struct xdr_bytesrec { 335 bool_t xc_is_last_record; 336 size_t xc_num_avail; 337}; 338 339typedef struct xdr_bytesrec xdr_bytesrec; 340 341/* 342 * These are the public routines for the various implementations of 343 * xdr streams. 344 */ 345__BEGIN_DECLS 346/* XDR using memory buffers */ 347extern void xdrmem_create(XDR *, char *, unsigned int, enum xdr_op); 348 349/* XDR using stdio library */ 350#ifdef _STDIO_H_ 351extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); 352#endif 353 354/* XDR pseudo records for tcp */ 355extern void xdrrec_create(XDR *, unsigned int, unsigned int, char *, 356 int (*)(char *, char *, int), 357 int (*)(char *, char *, int)); 358 359/* make end of xdr record */ 360extern bool_t xdrrec_endofrecord(XDR *, int); 361 362/* move to beginning of next record */ 363extern bool_t xdrrec_skiprecord(XDR *); 364 365/* true if no more input */ 366extern bool_t xdrrec_eof(XDR *); 367extern unsigned xdrrec_readbytes(XDR *, char *, unsigned int); 368__END_DECLS 369 370#endif /* !_RPC_XDR_H_ */ 371