// -*-c++-*- /* $Id: xdrmisc.h,v 1.29 2001/10/08 22:40:13 dm Exp $ */ /* * * Copyright (C) 1998 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #ifndef _ARPC_XDRMISC_H_ #define _ARPC_XDRMISC_H_ 1 #include "sysconf.h" extern "C" { #define xdrproc_t sun_xdrproc_t #define xdr_free foil_xdr_free #define xdr_void foil_xdr_void #define xdr_bool foil_xdr_bool #define xdr_int foil_xdr_int #define xdr_int32_t foil_xdr_int32_t #define xdr_u_int32_t foil_xdr_u_int32_t #define xdr_hyper foil_xdr_hyper #define xdr_int64_t foil_xdr_int64_t #define xdr_u_int64_t foil_xdr_u_int64_t #define xdr_string foil_xdr_string #define xdr_pointer foil_xdr_pointer #define xdr_array foil_xdr_array #define xdr_vector foil_xdr_vector #define pmaplist foil_pmaplist #define xdr_pmaplist foil_xdr_pmaplist #include #undef xdrproc_t #undef xdr_free #undef xdr_void #undef xdr_bool #undef xdr_int #undef xdr_int32_t #undef xdr_u_int32_t #undef xdr_hyper #undef xdr_int64_t #undef xdr_u_int64_t #undef xdr_string #undef xdr_pointer #undef xdr_array #undef xdr_vector #undef pmaplist #undef xdr_pmaplist #undef PMAPPROC_NULL #undef PMAPPROC_SET #undef PMAPPROC_UNSET #undef PMAPPROC_GETPORT #undef PMAPPROC_DUMP #undef PMAPPROC_CALLIT } #define BOOL bool_t typedef BOOL (*xdrproc_t) (XDR *, void *); #include "rpctypes.h" #ifdef __APPLE__ # define XDROPS_KNRPROTO 1 #endif /* __APPLE__ */ #ifdef XDROPS_KNRPROTO #undef xdrlong_t #define xdrlong_t long #undef XDR_GETLONG #define XDR_GETLONG(xdrs, longp) \ (*(bool_t (*) (...)) (xdrs)->x_ops->x_getlong) (xdrs, longp) #undef XDR_PUTLONG #define XDR_PUTLONG(xdrs, longp) \ (*(bool_t (*) (...)) (xdrs)->x_ops->x_putlong) (xdrs, longp) #undef XDR_GETBYTES #define XDR_GETBYTES(xdrs, addr, len) \ (*(bool_t (*) (...)) (xdrs)->x_ops->x_getbytes) (xdrs, addr, len) #undef XDR_PUTBYTES #define XDR_PUTBYTES(xdrs, addr, len) \ (*(bool_t (*) (...)) (xdrs)->x_ops->x_putbytes) (xdrs, addr, len) #undef XDR_GETPOS #define XDR_GETPOS(xdrs) \ (*(u_int (*) (...)) (xdrs)->x_ops->x_getpostn) (xdrs) #undef XDR_INLINE #define XDR_INLINE(xdrs, len) \ (*(xdrlong_t *(*) (...)) (xdrs)->x_ops->x_inline) (xdrs, len) #undef XDR_DESTROY #define XDR_DESTROY(xdrs) \ if ((xdrs)->x_ops->x_destroy) \ (*(void (*) (...)) (xdrs)->x_ops->x_destroy) (xdrs) #undef AUTH_MARSHALL #define AUTH_MARSHALL(auth, xdrs) \ (*(bool_t (*) (...)) (auth)->ah_ops->ah_marshal) (auth, xdrs) #undef AUTH_DESTROY #define AUTH_DESTROY(auth) \ (*(void (*) (...)) (auth)->ah_ops->ah_destroy) (auth) #endif /* XDROPS_KNRPROTO */ /* * rpc_traverse instantiation for sunrpc XDRs */ inline bool xdr_putint (XDR *xdrs, u_int32_t val) { xdrlong_t l = val; return XDR_PUTLONG (xdrs, &l); } inline bool xdr_getint (XDR *xdrs, u_int32_t &val) { xdrlong_t l; if (!XDR_GETLONG (xdrs, &l)) return false; val = l; return true; } inline bool xdr_puthyper (XDR *xdrs, u_int64_t val) { xdrlong_t h = val >> 32, l = val & 0xffffffff; return XDR_PUTLONG (xdrs, &h) && XDR_PUTLONG (xdrs, &l); } inline bool xdr_gethyper (XDR *xdrs, u_int64_t &val) { xdrlong_t h, l; if (!XDR_GETLONG (xdrs, &h) || !XDR_GETLONG (xdrs, &l)) return false; val = (u_int64_t) h << 32 | l; return true; } extern const char __xdr_zero_bytes[4]; inline bool xdr_putpadbytes (XDR *xdrs, const void *p, size_t n) { return XDR_PUTBYTES (xdrs, static_cast (const_cast (p)), n) && XDR_PUTBYTES (xdrs, const_cast (__xdr_zero_bytes), -n & 3); } inline bool xdr_getpadbytes (XDR *xdrs, void *p, size_t n) { char garbage[3]; if (!XDR_GETBYTES (xdrs, static_cast (p), n)) return false; if (size_t nn = -n & 3) return XDR_GETBYTES (xdrs, garbage, nn); return true; } inline bool rpc_traverse (XDR *xdrs, u_int32_t &obj) { switch (xdrs->x_op) { case XDR_ENCODE: return xdr_putint (xdrs, obj); case XDR_DECODE: return xdr_getint (xdrs, obj); default: return true; } } template inline bool rpc_traverse (XDR *xdrs, rpc_opaque &obj) { switch (xdrs->x_op) { case XDR_ENCODE: return xdr_putpadbytes (xdrs, obj.base (), obj.size ()); case XDR_DECODE: return xdr_getpadbytes (xdrs, obj.base (), obj.size ()); default: return true; } } template inline bool rpc_traverse (XDR *xdrs, rpc_bytes &obj) { switch (xdrs->x_op) { case XDR_ENCODE: return xdr_putint (xdrs, obj.size ()) && xdr_putpadbytes (xdrs, obj.base (), obj.size ()); case XDR_DECODE: { u_int32_t size; if (!xdr_getint (xdrs, size) || size > obj.maxsize) return false; obj.setsize (size); return xdr_getpadbytes (xdrs, obj.base (), size); } default: return true; } } template inline bool rpc_traverse (XDR *xdrs, rpc_str &obj) { switch (xdrs->x_op) { case XDR_ENCODE: return obj && xdr_putint (xdrs, obj.len ()) && xdr_putpadbytes (xdrs, obj.cstr (), obj.len ()); case XDR_DECODE: { u_int32_t size; if (!xdr_getint (xdrs, size) || size > max) return false; mstr m (size); if (!xdr_getpadbytes (xdrs, m, size) || memchr (m.cstr (), '\0', size)) return false; obj = m; } return true; default: return true; } } inline bool rpc_traverse (XDR *xdrs, str &obj) { switch (xdrs->x_op) { case XDR_ENCODE: return obj && xdr_putint (xdrs, obj.len ()) && xdr_putpadbytes (xdrs, obj.cstr (), obj.len ()); case XDR_DECODE: { u_int32_t size; if (!xdr_getint (xdrs, size)) return false; mstr m (size); if (!xdr_getpadbytes (xdrs, m, size) || memchr (m.cstr (), '\0', size)) return false; obj = m; } return true; default: return true; } } template inline void rpc_destruct (T *objp) { objp->~T (); } inline void xdr_free (xdrproc_t proc, void *objp) { XDR x; x.x_op = XDR_FREE; proc (&x, objp); } inline void xdr_delete (xdrproc_t proc, void *objp) { xdr_free (proc, objp); operator delete (objp); } class auto_xdr_delete { const xdrproc_t proc; void *const objp; auto_xdr_delete (const auto_xdr_delete &); auto_xdr_delete &operator= (const auto_xdr_delete &); public: auto_xdr_delete (xdrproc_t p, void *o) : proc (p), objp (o) {} ~auto_xdr_delete () { xdr_delete (proc, objp); } }; #define DECLXDR(type) \ extern BOOL xdr_##type (XDR *, void *); \ extern void *type##_alloc (); DECLXDR(void) DECLXDR(false) DECLXDR(string) DECLXDR(bool) DECLXDR(int) DECLXDR(int32_t) DECLXDR(u_int32_t) DECLXDR(int64_t) DECLXDR(u_int64_t) #undef DECLXDR #ifdef MAINTAINER # define RPC_TYPE_DECL(type) \ RPC_TYPE2STR_DECL (type) \ RPC_PRINT_DECL (type) \ RPC_PRINT_TYPE_DECL (type) # define XDRTBL_DECL(proc, arg, res) \ { \ #proc, \ &typeid (arg), arg##_alloc, xdr_##arg, print_##arg, \ &typeid (res), res##_alloc, xdr_##res, print_##res \ }, #else /* !MAINTAINER */ # define RPC_TYPE_DECL(type) # define XDRTBL_DECL(proc, arg, res) \ { \ #proc, \ &typeid (arg), arg##_alloc, xdr_##arg, NULL, \ &typeid (res), res##_alloc, xdr_##res, NULL \ }, #endif /* !MAINTAINER */ #define RPC_STRUCT_DECL(type) RPC_TYPE_DECL (type) #define RPC_UNION_DECL(type) RPC_TYPE_DECL (type) #define RPC_ENUM_DECL(type) RPC_TYPE_DECL (type) #ifdef MAINTAINER #define RPC_TYPEDEF_DECL(type) RPC_PRINT_TYPE_DECL (type) #endif /* MAINTAINER */ #define RPCUNION_SET(type, field) field.select () #define RPCUNION_TRAVERSE(type, field) return rpc_traverse (t, *obj.field) #define RPCUNION_STOMPCAST(type, field) field.Xstompcast () #define RPCUNION_REC_STOMPCAST(type, field) \ obj.field.Xstompcast (); return rpc_traverse (s, *obj.field); class xdrbase : public XDR { protected: xdrbase () {} ~xdrbase () { XDR_DESTROY (implicit_cast (this)); } xdrbase (const xdrbase &); // No copying const xdrbase &operator= (const xdrbase &); public: XDR *xdrp () { return this; } }; extern "C" void xdrsuio_create (XDR *, enum xdr_op); extern "C" void xdrsuio_scrub_create (XDR *, enum xdr_op); struct xdrsuio : xdrbase { explicit xdrsuio (xdr_op op = XDR_ENCODE, bool scrub = false) { if (scrub) xdrsuio_scrub_create (this, op); else xdrsuio_create (this, op); } suio *uio (); const iovec *iov (); u_int iovcnt (); }; struct xdrmem : xdrbase { explicit xdrmem (char *base, size_t len, xdr_op op = XDR_DECODE) { xdrmem_create (this, base, len, op); } explicit xdrmem (const char *base, size_t len, xdr_op op = XDR_DECODE) { assert (op == XDR_DECODE); xdrmem_create (this, const_cast (base), len, op); } }; template str xdr2str (const T &t, bool scrub = false) { xdrsuio x (XDR_ENCODE, scrub); XDR *xp = &x; if (!rpc_traverse (xp, const_cast (t))) return NULL; mstr m (x.uio ()->resid ()); x.uio ()->copyout (m); if (scrub) return str2wstr (m); return m; } template bool str2xdr (T &t, const str &s) { xdrmem x (s, s.len ()); XDR *xp = &x; return rpc_traverse (xp, t); } template bool xdr2bytes (rpc_bytes &out, const T &t, bool scrub = false) { xdrsuio x (XDR_ENCODE, scrub); XDR *xp = &x; if (!rpc_traverse (xp, const_cast (t)) || x.uio ()->resid () > n) return false; if (scrub) bzero (out.base (), out.size ()); out.setsize (x.uio ()->resid ()); x.uio ()->copyout (out.base ()); return true; } template bool bytes2xdr (T &t, const rpc_bytes &in) { xdrmem x (in.base (), in.size ()); XDR *xp = &x; return rpc_traverse (xp, t); } template bool buf2xdr (T &t, const void *buf, size_t len) { xdrmem x (reinterpret_cast (buf), len); XDR *xp = &x; return rpc_traverse (xp, t); } #endif /* !_ARPC_XDRMISC_H_ */