xdr.h revision 192971
14974Sache/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */ 24974Sache 3112749Smux/* 44974Sache * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5112749Smux * unrestricted use provided that this legend is included on all tape 64974Sache * media and as a part of the software program in whole or part. Users 7112749Smux * may copy or modify Sun RPC without charge, but are not authorized 84974Sache * to license or distribute it to anyone else except as part of a product or 94974Sache * program developed by the user. 1051358Sgreen * 11112749Smux * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12112749Smux * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 13112749Smux * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1451358Sgreen * 154974Sache * Sun RPC is provided with no support and without any obligation on the 164974Sache * part of Sun Microsystems, Inc. to assist in its use, correction, 1783928Sru * modification or enhancement. 18210809Suqs * 194974Sache * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 204974Sache * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21210809Suqs * OR ANY PART THEREOF. 224974Sache * 234974Sache * In no event will Sun Microsystems, Inc. be liable for any lost revenue 244974Sache * or profits or other special, indirect and consequential damages, even if 254974Sache * Sun has been advised of the possibility of such damages. 264974Sache * 274974Sache * Sun Microsystems, Inc. 284974Sache * 2550 Garcia Avenue 29227101Sed * Mountain View, California 94043 30227101Sed * 314974Sache * from: @(#)xdr.h 1.19 87/04/22 SMI 32227101Sed * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC 334974Sache * $FreeBSD: head/sys/rpc/xdr.h 192971 2009-05-28 08:18:12Z kmacy $ 344974Sache */ 354974Sache 36227101Sed/* 374974Sache * xdr.h, External Data Representation Serialization Routines. 38227101Sed * 394974Sache * Copyright (C) 1984, Sun Microsystems, Inc. 40227101Sed */ 414974Sache 42227101Sed#ifndef _KRPC_XDR_H 43227101Sed#define _KRPC_XDR_H 44227101Sed#include <sys/cdefs.h> 45227101Sed 46227101Sed/* 474974Sache * XDR provides a conventional way for converting between C data 48227101Sed * types and an external bit-string representation. Library supplied 49203920Suqs * routines provide for the conversion on built-in C data types. These 504974Sache * routines and utility routines defined here are used to help implement 51227101Sed * a type encode/decode routine for each user-defined type. 52227101Sed * 534974Sache * Each data type provides a single procedure which takes two arguments: 544974Sache * 554974Sache * bool_t 56203920Suqs * xdrproc(xdrs, argresp) 574974Sache * XDR *xdrs; 58210755Suqs * <type> *argresp; 59210827Suqs * 60203920Suqs * xdrs is an instance of a XDR handle, to which or from which the data 61203920Suqs * type is to be converted. argresp is a pointer to the structure to be 62203920Suqs * converted. The XDR handle contains an operation field which indicates 63203920Suqs * which of the operations (ENCODE, DECODE * or FREE) is to be performed. 64203920Suqs * 65203920Suqs * XDR_DECODE may allocate space if the pointer argresp is null. This 664974Sache * data can be freed with the XDR_FREE operation. 67112749Smux * 6883928Sru * We write only one procedure per data type to make it easy 69112749Smux * to keep the encode and decode procedures for a data type consistent. 7083928Sru * In many cases the same code performs all operations on a user defined type, 7183928Sru * because all the hard work is done in the component type routines. 7283928Sru * decode as a series of calls on the nested data types. 7383928Sru */ 74112749Smux 75112749Smux/* 76112749Smux * Xdr operations. XDR_ENCODE causes the type to be encoded into the 7783928Sru * stream. XDR_DECODE causes the type to be extracted from the stream. 7883928Sru * XDR_FREE can be used to release the space allocated by an XDR_DECODE 7983928Sru * request. 8083928Sru */ 8183928Sruenum xdr_op { 8283928Sru XDR_ENCODE=0, 8383928Sru XDR_DECODE=1, 8483928Sru XDR_FREE=2 8583928Sru}; 8683928Sru 8783928Sru/* 8883928Sru * This is the number of bytes per unit of external data. 8983928Sru */ 90210809Suqs#define BYTES_PER_XDR_UNIT (4) 91210755Suqs#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ 92210809Suqs * BYTES_PER_XDR_UNIT) 93210809Suqs 94210809Suqs/* 95210809Suqs * The XDR handle. 96210809Suqs * Contains operation which is being applied to the stream, 97210809Suqs * an operations vector for the particular implementation (e.g. see xdr_mem.c), 9883928Sru * and two private fields for the use of the particular implementation. 9983928Sru */ 1004974Sachetypedef struct __rpc_xdr { 1014974Sache enum xdr_op x_op; /* operation; fast additional param */ 1024974Sache const struct xdr_ops { 1034974Sache /* get a long from underlying stream */ 1044974Sache bool_t (*x_getlong)(struct __rpc_xdr *, long *); 1054974Sache /* put a long to " */ 1064974Sache bool_t (*x_putlong)(struct __rpc_xdr *, const long *); 1074974Sache /* get some bytes from " */ 10851358Sgreen bool_t (*x_getbytes)(struct __rpc_xdr *, char *, u_int); 1098856Srgrimes /* put some bytes to " */ 1104974Sache bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, u_int); 1114974Sache /* returns bytes off from beginning */ 1128856Srgrimes u_int (*x_getpostn)(struct __rpc_xdr *); 1134974Sache /* lets you reposition the stream */ 1144974Sache bool_t (*x_setpostn)(struct __rpc_xdr *, u_int); 1154974Sache /* buf quick ptr to buffered data */ 1164974Sache int32_t *(*x_inline)(struct __rpc_xdr *, u_int); 1174974Sache /* free privates of this xdr_stream */ 1184974Sache void (*x_destroy)(struct __rpc_xdr *); 1198856Srgrimes bool_t (*x_control)(struct __rpc_xdr *, int, void *); 1204974Sache } *x_ops; 1214974Sache char * x_public; /* users' data */ 1224974Sache void * x_private; /* pointer to private data */ 1238856Srgrimes char * x_base; /* private used for position info */ 1244974Sache u_int x_handy; /* extra private word */ 1254974Sache} XDR; 1264974Sache 1274974Sache/* 1284974Sache * A xdrproc_t exists for each data type which is to be encoded or decoded. 1294974Sache * 1304974Sache * The second argument to the xdrproc_t is a pointer to an opaque pointer. 1314974Sache * The opaque pointer generally points to a structure of the data type 1324974Sache * to be decoded. If this pointer is 0, then the type routines should 1334974Sache * allocate dynamic storage of the appropriate size and return it. 1344974Sache */ 1354974Sache#ifdef _KERNEL 1364974Sachetypedef bool_t (*xdrproc_t)(XDR *, void *, ...); 1374974Sache#else 1384974Sache/* 1394974Sache * XXX can't actually prototype it, because some take three args!!! 1404974Sache */ 1414974Sachetypedef bool_t (*xdrproc_t)(XDR *, ...); 142210755Suqs#endif 143210827Suqs 1444974Sache/* 1454974Sache * Operations defined on a XDR handle 146210755Suqs * 1474974Sache * XDR *xdrs; 1484974Sache * long *longp; 1494974Sache * char * addr; 1504974Sache * u_int len; 151112749Smux * u_int pos; 152112749Smux */ 153288185Semaste#define XDR_GETLONG(xdrs, longp) \ 154116739Swill (*(xdrs)->x_ops->x_getlong)(xdrs, longp) 155116739Swill#define xdr_getlong(xdrs, longp) \ 156112749Smux (*(xdrs)->x_ops->x_getlong)(xdrs, longp) 157288185Semaste 158288185Semaste#define XDR_PUTLONG(xdrs, longp) \ 159288185Semaste (*(xdrs)->x_ops->x_putlong)(xdrs, longp) 160288185Semaste#define xdr_putlong(xdrs, longp) \ 161116739Swill (*(xdrs)->x_ops->x_putlong)(xdrs, longp) 162112749Smux 163112749Smuxstatic __inline int 1644974Sachexdr_getint32(XDR *xdrs, int32_t *ip) 1654974Sache{ 1664974Sache long l; 1674974Sache 1684974Sache if (!xdr_getlong(xdrs, &l)) 1694974Sache return (FALSE); 1704974Sache *ip = (int32_t)l; 1714974Sache return (TRUE); 1724974Sache} 1734974Sache 1744974Sachestatic __inline int 1754974Sachexdr_putint32(XDR *xdrs, int32_t *ip) 1764974Sache{ 1774974Sache long l; 1784974Sache 1794974Sache l = (long)*ip; 1804974Sache return xdr_putlong(xdrs, &l); 1814974Sache} 1824974Sache 1834974Sache#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) 1844974Sache#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) 1854974Sache 1864974Sache#define XDR_GETBYTES(xdrs, addr, len) \ 1874974Sache (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) 1884974Sache#define xdr_getbytes(xdrs, addr, len) \ 1894974Sache (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) 1904974Sache 1914974Sache#define XDR_PUTBYTES(xdrs, addr, len) \ 1924974Sache (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) 1934974Sache#define xdr_putbytes(xdrs, addr, len) \ 1944974Sache (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) 1954974Sache 1964974Sache#define XDR_GETPOS(xdrs) \ 1974974Sache (*(xdrs)->x_ops->x_getpostn)(xdrs) 1984974Sache#define xdr_getpos(xdrs) \ 1994974Sache (*(xdrs)->x_ops->x_getpostn)(xdrs) 200210827Suqs 201210827Suqs#define XDR_SETPOS(xdrs, pos) \ 202210809Suqs (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) 203210809Suqs#define xdr_setpos(xdrs, pos) \ 204210827Suqs (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) 205210809Suqs 206210809Suqs#define XDR_INLINE(xdrs, len) \ 207210809Suqs (*(xdrs)->x_ops->x_inline)(xdrs, len) 208210809Suqs#define xdr_inline(xdrs, len) \ 209210809Suqs (*(xdrs)->x_ops->x_inline)(xdrs, len) 210210827Suqs 211210755Suqs#define XDR_DESTROY(xdrs) \ 212210827Suqs if ((xdrs)->x_ops->x_destroy) \ 213210827Suqs (*(xdrs)->x_ops->x_destroy)(xdrs) 2144974Sache#define xdr_destroy(xdrs) \ 2154974Sache if ((xdrs)->x_ops->x_destroy) \ 2164974Sache (*(xdrs)->x_ops->x_destroy)(xdrs) 2174974Sache 2184974Sache#define XDR_CONTROL(xdrs, req, op) \ 21983928Sru if ((xdrs)->x_ops->x_control) \ 2204974Sache (*(xdrs)->x_ops->x_control)(xdrs, req, op) 221210809Suqs#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op) 2224974Sache 2234974Sache/* 2244974Sache * Solaris strips the '_t' from these types -- not sure why. 2254974Sache * But, let's be compatible. 2264974Sache */ 2274974Sache#define xdr_rpcvers(xdrs, versp) xdr_uint32_t(xdrs, versp) 2284974Sache#define xdr_rpcprog(xdrs, progp) xdr_uint32_t(xdrs, progp) 229227101Sed#define xdr_rpcproc(xdrs, procp) xdr_uint32_t(xdrs, procp) 2304974Sache#define xdr_rpcprot(xdrs, protp) xdr_uint32_t(xdrs, protp) 2314974Sache#define xdr_rpcport(xdrs, portp) xdr_uint32_t(xdrs, portp) 232203920Suqs 2334974Sache/* 2344974Sache * Support struct for discriminated unions. 2354974Sache * You create an array of xdrdiscrim structures, terminated with 2364974Sache * an entry with a null procedure pointer. The xdr_union routine gets 2374974Sache * the discriminant value and then searches the array of structures 2384974Sache * for a matching value. If a match is found the associated xdr routine 2394974Sache * is called to handle that part of the union. If there is 2404974Sache * no match, then a default routine may be called. 2414974Sache * If there is no match and no default routine it is an error. 2424974Sache */ 243227101Sed#define NULL_xdrproc_t ((xdrproc_t)0) 2444974Sachestruct xdr_discrim { 2454974Sache int value; 2464974Sache xdrproc_t proc; 2474974Sache}; 2484974Sache 2494974Sache/* 2508856Srgrimes * In-line routines for fast encode/decode of primitive data types. 2518856Srgrimes * Caveat emptor: these use single memory cycles to get the 2524974Sache * data from the underlying buffer, and will fail to operate 2534974Sache * properly if the data is not aligned. The standard way to use these 2544974Sache * is to say: 2554974Sache * if ((buf = XDR_INLINE(xdrs, count)) == NULL) 2564974Sache * return (FALSE); 2574974Sache * <<< macro calls >>> 2584974Sache * where ``count'' is the number of bytes of data occupied 2594974Sache * by the primitive data types. 2604974Sache * 261227101Sed * N.B. and frozen for all time: each data type here uses 4 bytes 2624974Sache * of external representation. 2634974Sache */ 2644974Sache#define IXDR_GET_INT32(buf) ((int32_t)__ntohl((uint32_t)*(buf)++)) 2654974Sache#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v)) 2664974Sache#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) 267227101Sed#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) 26883928Sru 26983928Sru#define IXDR_GET_UINT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) 27083928Sru#define IXDR_PUT_UINT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) 271112749Smux 27283928Sru#define IXDR_GET_LONG(buf) ((long)__ntohl((uint32_t)*(buf)++)) 27383928Sru#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)__htonl((uint32_t)v)) 274 275#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) 276#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) 277#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) 278#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) 279#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) 280 281#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v)) 282#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v)) 283#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v)) 284#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) 285#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) 286 287/* 288 * These are the "generic" xdr routines. 289 */ 290__BEGIN_DECLS 291extern bool_t xdr_void(void); 292extern bool_t xdr_int(XDR *, int *); 293extern bool_t xdr_u_int(XDR *, u_int *); 294extern bool_t xdr_long(XDR *, long *); 295extern bool_t xdr_u_long(XDR *, u_long *); 296extern bool_t xdr_short(XDR *, short *); 297extern bool_t xdr_u_short(XDR *, u_short *); 298extern bool_t xdr_int16_t(XDR *, int16_t *); 299extern bool_t xdr_uint16_t(XDR *, uint16_t *); 300extern bool_t xdr_int32_t(XDR *, int32_t *); 301extern bool_t xdr_uint32_t(XDR *, uint32_t *); 302extern bool_t xdr_int64_t(XDR *, int64_t *); 303extern bool_t xdr_uint64_t(XDR *, uint64_t *); 304extern bool_t xdr_bool(XDR *, bool_t *); 305extern bool_t xdr_enum(XDR *, enum_t *); 306extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t); 307extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int); 308extern bool_t xdr_opaque(XDR *, char *, u_int); 309extern bool_t xdr_string(XDR *, char **, u_int); 310extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); 311extern bool_t xdr_char(XDR *, char *); 312extern bool_t xdr_u_char(XDR *, u_char *); 313extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t); 314extern bool_t xdr_float(XDR *, float *); 315extern bool_t xdr_double(XDR *, double *); 316extern bool_t xdr_quadruple(XDR *, long double *); 317extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t); 318extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t); 319extern bool_t xdr_wrapstring(XDR *, char **); 320extern void xdr_free(xdrproc_t, void *); 321extern bool_t xdr_hyper(XDR *, quad_t *); 322extern bool_t xdr_u_hyper(XDR *, u_quad_t *); 323extern bool_t xdr_longlong_t(XDR *, quad_t *); 324extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *); 325extern unsigned long xdr_sizeof(xdrproc_t func, void *data); 326__END_DECLS 327 328/* 329 * Common opaque bytes objects used by many rpc protocols; 330 * declared here due to commonality. 331 */ 332#define MAX_NETOBJ_SZ 1024 333struct netobj { 334 u_int n_len; 335 char *n_bytes; 336}; 337typedef struct netobj netobj; 338extern bool_t xdr_netobj(XDR *, struct netobj *); 339 340/* 341 * These are XDR control operators 342 */ 343 344#define XDR_GET_BYTES_AVAIL 1 345#define XDR_PEEK 2 346#define XDR_SKIPBYTES 3 347 348struct xdr_bytesrec { 349 bool_t xc_is_last_record; 350 size_t xc_num_avail; 351}; 352 353typedef struct xdr_bytesrec xdr_bytesrec; 354 355 356/* 357 * These are the public routines for the various implementations of 358 * xdr streams. 359 */ 360__BEGIN_DECLS 361/* XDR using memory buffers */ 362extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op); 363 364/* XDR using mbufs */ 365struct mbuf; 366extern void xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op); 367extern void xdrmbuf_append(XDR *, struct mbuf *); 368extern struct mbuf * xdrmbuf_getall(XDR *); 369 370/* XDR pseudo records for tcp */ 371extern void xdrrec_create(XDR *, u_int, u_int, void *, 372 int (*)(void *, void *, int), 373 int (*)(void *, void *, int)); 374 375/* make end of xdr record */ 376extern bool_t xdrrec_endofrecord(XDR *, int); 377 378/* move to beginning of next record */ 379extern bool_t xdrrec_skiprecord(XDR *); 380 381/* true if no more input */ 382extern bool_t xdrrec_eof(XDR *); 383extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int); 384__END_DECLS 385 386#endif /* !_KRPC_XDR_H */ 387