|  | /* | 
|  | * xdr_mem.c, XDR implementation using memory buffers. | 
|  | * | 
|  | * Copyright (c) 2010, Oracle America, Inc. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions are | 
|  | * met: | 
|  | * | 
|  | *     * Redistributions of source code must retain the above copyright | 
|  | *       notice, this list of conditions and the following disclaimer. | 
|  | *     * Redistributions in binary form must reproduce the above | 
|  | *       copyright notice, this list of conditions and the following | 
|  | *       disclaimer in the documentation and/or other materials | 
|  | *       provided with the distribution. | 
|  | *     * Neither the name of the "Oracle America, Inc." nor the names of its | 
|  | *       contributors may be used to endorse or promote products derived | 
|  | *       from this software without specific prior written permission. | 
|  | * | 
|  | *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
|  | *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
|  | *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | 
|  | *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 
|  | *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 
|  | *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | * | 
|  | * If you have some data to be interpreted as external data representation | 
|  | * or to be converted to external data representation in a memory buffer, | 
|  | * then this is the package for you. | 
|  | */ | 
|  |  | 
|  | #include <string.h> | 
|  | #include <limits.h> | 
|  | #include <rpc/rpc.h> | 
|  |  | 
|  | static bool_t xdrmem_getlong (XDR *, long *); | 
|  | static bool_t xdrmem_putlong (XDR *, const long *); | 
|  | static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int); | 
|  | static bool_t xdrmem_putbytes (XDR *, const char *, u_int); | 
|  | static u_int xdrmem_getpos (const XDR *); | 
|  | static bool_t xdrmem_setpos (XDR *, u_int); | 
|  | static int32_t *xdrmem_inline (XDR *, u_int); | 
|  | static void xdrmem_destroy (XDR *); | 
|  | static bool_t xdrmem_getint32 (XDR *, int32_t *); | 
|  | static bool_t xdrmem_putint32 (XDR *, const int32_t *); | 
|  |  | 
|  | static const struct xdr_ops xdrmem_ops = | 
|  | { | 
|  | xdrmem_getlong, | 
|  | xdrmem_putlong, | 
|  | xdrmem_getbytes, | 
|  | xdrmem_putbytes, | 
|  | xdrmem_getpos, | 
|  | xdrmem_setpos, | 
|  | xdrmem_inline, | 
|  | xdrmem_destroy, | 
|  | xdrmem_getint32, | 
|  | xdrmem_putint32 | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * The procedure xdrmem_create initializes a stream descriptor for a | 
|  | * memory buffer. | 
|  | */ | 
|  | void | 
|  | xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) | 
|  | { | 
|  | xdrs->x_op = op; | 
|  | /* We have to add the const since the `struct xdr_ops' in `struct XDR' | 
|  | is not `const'.  */ | 
|  | xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; | 
|  | xdrs->x_private = xdrs->x_base = addr; | 
|  | xdrs->x_handy = size; | 
|  | } | 
|  | #ifdef EXPORT_RPC_SYMBOLS | 
|  | libc_hidden_def (xdrmem_create) | 
|  | #else | 
|  | libc_hidden_nolink_sunrpc (xdrmem_create, GLIBC_2_0) | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * Nothing needs to be done for the memory case.  The argument is clearly | 
|  | * const. | 
|  | */ | 
|  |  | 
|  | static void | 
|  | xdrmem_destroy (XDR *xdrs) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Gets the next word from the memory referenced by xdrs and places it | 
|  | * in the long pointed to by lp.  It then increments the private word to | 
|  | * point at the next element.  Neither object pointed to is const | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_getlong (XDR *xdrs, long *lp) | 
|  | { | 
|  | if (xdrs->x_handy < 4) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= 4; | 
|  | *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private)))); | 
|  | xdrs->x_private += 4; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Puts the long pointed to by lp in the memory referenced by xdrs.  It | 
|  | * then increments the private word to point at the next element.  The | 
|  | * long pointed at is const | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_putlong (XDR *xdrs, const long *lp) | 
|  | { | 
|  | if (xdrs->x_handy < 4) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= 4; | 
|  | *(int32_t *) xdrs->x_private = htonl (*lp); | 
|  | xdrs->x_private += 4; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Gets an unaligned number of bytes from the xdrs structure and writes them | 
|  | * to the address passed in addr.  Be very careful when calling this routine | 
|  | * as it could leave the xdrs pointing to an unaligned structure which is not | 
|  | * a good idea.  None of the things pointed to are const. | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len) | 
|  | { | 
|  | if (xdrs->x_handy < len) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= len; | 
|  | memcpy (addr, xdrs->x_private, len); | 
|  | xdrs->x_private += len; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The complementary function to the above.  The same warnings apply about | 
|  | * unaligned data.  The source address is const. | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len) | 
|  | { | 
|  | if (xdrs->x_handy < len) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= len; | 
|  | memcpy (xdrs->x_private, addr, len); | 
|  | xdrs->x_private += len; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Not sure what this one does.  But it clearly doesn't modify the contents | 
|  | * of xdrs.  **FIXME** does this not assume u_int == u_long? | 
|  | */ | 
|  | static u_int | 
|  | xdrmem_getpos (const XDR *xdrs) | 
|  | { | 
|  | return (u_long) xdrs->x_private - (u_long) xdrs->x_base; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * xdrs modified | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_setpos (XDR *xdrs, u_int pos) | 
|  | { | 
|  | caddr_t newaddr = xdrs->x_base + pos; | 
|  | caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; | 
|  | size_t handy = lastaddr - newaddr; | 
|  |  | 
|  | if (newaddr > lastaddr | 
|  | || newaddr < xdrs->x_base | 
|  | || handy != (u_int) handy) | 
|  | return FALSE; | 
|  |  | 
|  | xdrs->x_private = newaddr; | 
|  | xdrs->x_handy = (u_int) handy; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * xdrs modified | 
|  | */ | 
|  | static int32_t * | 
|  | xdrmem_inline (XDR *xdrs, u_int len) | 
|  | { | 
|  | int32_t *buf = 0; | 
|  |  | 
|  | if (xdrs->x_handy >= len) | 
|  | { | 
|  | xdrs->x_handy -= len; | 
|  | buf = (int32_t *) xdrs->x_private; | 
|  | xdrs->x_private += len; | 
|  | } | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Gets the next word from the memory referenced by xdrs and places it | 
|  | * in the int pointed to by ip.  It then increments the private word to | 
|  | * point at the next element.  Neither object pointed to is const | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_getint32 (XDR *xdrs, int32_t *ip) | 
|  | { | 
|  | if (xdrs->x_handy < 4) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= 4; | 
|  | *ip = ntohl ((*((int32_t *) (xdrs->x_private)))); | 
|  | xdrs->x_private += 4; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Puts the long pointed to by lp in the memory referenced by xdrs.  It | 
|  | * then increments the private word to point at the next element.  The | 
|  | * long pointed at is const | 
|  | */ | 
|  | static bool_t | 
|  | xdrmem_putint32 (XDR *xdrs, const int32_t *ip) | 
|  | { | 
|  | if (xdrs->x_handy < 4) | 
|  | return FALSE; | 
|  | xdrs->x_handy -= 4; | 
|  | *(int32_t *) xdrs->x_private = htonl (*ip); | 
|  | xdrs->x_private += 4; | 
|  | return TRUE; | 
|  | } |