| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * xdr_mem.c, XDR implementation using memory buffers. | 
|  | 3 | * | 
|  | 4 | * Copyright (c) 2010, Oracle America, Inc. | 
|  | 5 | * | 
|  | 6 | * Redistribution and use in source and binary forms, with or without | 
|  | 7 | * modification, are permitted provided that the following conditions are | 
|  | 8 | * met: | 
|  | 9 | * | 
|  | 10 | *     * Redistributions of source code must retain the above copyright | 
|  | 11 | *       notice, this list of conditions and the following disclaimer. | 
|  | 12 | *     * Redistributions in binary form must reproduce the above | 
|  | 13 | *       copyright notice, this list of conditions and the following | 
|  | 14 | *       disclaimer in the documentation and/or other materials | 
|  | 15 | *       provided with the distribution. | 
|  | 16 | *     * Neither the name of the "Oracle America, Inc." nor the names of its | 
|  | 17 | *       contributors may be used to endorse or promote products derived | 
|  | 18 | *       from this software without specific prior written permission. | 
|  | 19 | * | 
|  | 20 | *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | 21 | *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | 22 | *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
|  | 23 | *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
|  | 24 | *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | 
|  | 25 | *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | 26 | *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 
|  | 27 | *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|  | 28 | *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 
|  | 29 | *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | 30 | *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | 31 | *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | 32 | * | 
|  | 33 | * If you have some data to be interpreted as external data representation | 
|  | 34 | * or to be converted to external data representation in a memory buffer, | 
|  | 35 | * then this is the package for you. | 
|  | 36 | */ | 
|  | 37 |  | 
|  | 38 | #include <string.h> | 
|  | 39 | #include <limits.h> | 
|  | 40 | #include <rpc/rpc.h> | 
|  | 41 |  | 
|  | 42 | static bool_t xdrmem_getlong (XDR *, long *); | 
|  | 43 | static bool_t xdrmem_putlong (XDR *, const long *); | 
|  | 44 | static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int); | 
|  | 45 | static bool_t xdrmem_putbytes (XDR *, const char *, u_int); | 
|  | 46 | static u_int xdrmem_getpos (const XDR *); | 
|  | 47 | static bool_t xdrmem_setpos (XDR *, u_int); | 
|  | 48 | static int32_t *xdrmem_inline (XDR *, u_int); | 
|  | 49 | static void xdrmem_destroy (XDR *); | 
|  | 50 | static bool_t xdrmem_getint32 (XDR *, int32_t *); | 
|  | 51 | static bool_t xdrmem_putint32 (XDR *, const int32_t *); | 
|  | 52 |  | 
|  | 53 | static const struct xdr_ops xdrmem_ops = | 
|  | 54 | { | 
|  | 55 | xdrmem_getlong, | 
|  | 56 | xdrmem_putlong, | 
|  | 57 | xdrmem_getbytes, | 
|  | 58 | xdrmem_putbytes, | 
|  | 59 | xdrmem_getpos, | 
|  | 60 | xdrmem_setpos, | 
|  | 61 | xdrmem_inline, | 
|  | 62 | xdrmem_destroy, | 
|  | 63 | xdrmem_getint32, | 
|  | 64 | xdrmem_putint32 | 
|  | 65 | }; | 
|  | 66 |  | 
|  | 67 | /* | 
|  | 68 | * The procedure xdrmem_create initializes a stream descriptor for a | 
|  | 69 | * memory buffer. | 
|  | 70 | */ | 
|  | 71 | void | 
|  | 72 | xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) | 
|  | 73 | { | 
|  | 74 | xdrs->x_op = op; | 
|  | 75 | /* We have to add the const since the `struct xdr_ops' in `struct XDR' | 
|  | 76 | is not `const'.  */ | 
|  | 77 | xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; | 
|  | 78 | xdrs->x_private = xdrs->x_base = addr; | 
|  | 79 | xdrs->x_handy = size; | 
|  | 80 | } | 
|  | 81 | #ifdef EXPORT_RPC_SYMBOLS | 
|  | 82 | libc_hidden_def (xdrmem_create) | 
|  | 83 | #else | 
|  | 84 | libc_hidden_nolink_sunrpc (xdrmem_create, GLIBC_2_0) | 
|  | 85 | #endif | 
|  | 86 |  | 
|  | 87 | /* | 
|  | 88 | * Nothing needs to be done for the memory case.  The argument is clearly | 
|  | 89 | * const. | 
|  | 90 | */ | 
|  | 91 |  | 
|  | 92 | static void | 
|  | 93 | xdrmem_destroy (XDR *xdrs) | 
|  | 94 | { | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | /* | 
|  | 98 | * Gets the next word from the memory referenced by xdrs and places it | 
|  | 99 | * in the long pointed to by lp.  It then increments the private word to | 
|  | 100 | * point at the next element.  Neither object pointed to is const | 
|  | 101 | */ | 
|  | 102 | static bool_t | 
|  | 103 | xdrmem_getlong (XDR *xdrs, long *lp) | 
|  | 104 | { | 
|  | 105 | if (xdrs->x_handy < 4) | 
|  | 106 | return FALSE; | 
|  | 107 | xdrs->x_handy -= 4; | 
|  | 108 | *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private)))); | 
|  | 109 | xdrs->x_private += 4; | 
|  | 110 | return TRUE; | 
|  | 111 | } | 
|  | 112 |  | 
|  | 113 | /* | 
|  | 114 | * Puts the long pointed to by lp in the memory referenced by xdrs.  It | 
|  | 115 | * then increments the private word to point at the next element.  The | 
|  | 116 | * long pointed at is const | 
|  | 117 | */ | 
|  | 118 | static bool_t | 
|  | 119 | xdrmem_putlong (XDR *xdrs, const long *lp) | 
|  | 120 | { | 
|  | 121 | if (xdrs->x_handy < 4) | 
|  | 122 | return FALSE; | 
|  | 123 | xdrs->x_handy -= 4; | 
|  | 124 | *(int32_t *) xdrs->x_private = htonl (*lp); | 
|  | 125 | xdrs->x_private += 4; | 
|  | 126 | return TRUE; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | /* | 
|  | 130 | * Gets an unaligned number of bytes from the xdrs structure and writes them | 
|  | 131 | * to the address passed in addr.  Be very careful when calling this routine | 
|  | 132 | * as it could leave the xdrs pointing to an unaligned structure which is not | 
|  | 133 | * a good idea.  None of the things pointed to are const. | 
|  | 134 | */ | 
|  | 135 | static bool_t | 
|  | 136 | xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len) | 
|  | 137 | { | 
|  | 138 | if (xdrs->x_handy < len) | 
|  | 139 | return FALSE; | 
|  | 140 | xdrs->x_handy -= len; | 
|  | 141 | memcpy (addr, xdrs->x_private, len); | 
|  | 142 | xdrs->x_private += len; | 
|  | 143 | return TRUE; | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | /* | 
|  | 147 | * The complementary function to the above.  The same warnings apply about | 
|  | 148 | * unaligned data.  The source address is const. | 
|  | 149 | */ | 
|  | 150 | static bool_t | 
|  | 151 | xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len) | 
|  | 152 | { | 
|  | 153 | if (xdrs->x_handy < len) | 
|  | 154 | return FALSE; | 
|  | 155 | xdrs->x_handy -= len; | 
|  | 156 | memcpy (xdrs->x_private, addr, len); | 
|  | 157 | xdrs->x_private += len; | 
|  | 158 | return TRUE; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | /* | 
|  | 162 | * Not sure what this one does.  But it clearly doesn't modify the contents | 
|  | 163 | * of xdrs.  **FIXME** does this not assume u_int == u_long? | 
|  | 164 | */ | 
|  | 165 | static u_int | 
|  | 166 | xdrmem_getpos (const XDR *xdrs) | 
|  | 167 | { | 
|  | 168 | return (u_long) xdrs->x_private - (u_long) xdrs->x_base; | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | /* | 
|  | 172 | * xdrs modified | 
|  | 173 | */ | 
|  | 174 | static bool_t | 
|  | 175 | xdrmem_setpos (XDR *xdrs, u_int pos) | 
|  | 176 | { | 
|  | 177 | caddr_t newaddr = xdrs->x_base + pos; | 
|  | 178 | caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; | 
|  | 179 | size_t handy = lastaddr - newaddr; | 
|  | 180 |  | 
|  | 181 | if (newaddr > lastaddr | 
|  | 182 | || newaddr < xdrs->x_base | 
|  | 183 | || handy != (u_int) handy) | 
|  | 184 | return FALSE; | 
|  | 185 |  | 
|  | 186 | xdrs->x_private = newaddr; | 
|  | 187 | xdrs->x_handy = (u_int) handy; | 
|  | 188 | return TRUE; | 
|  | 189 | } | 
|  | 190 |  | 
|  | 191 | /* | 
|  | 192 | * xdrs modified | 
|  | 193 | */ | 
|  | 194 | static int32_t * | 
|  | 195 | xdrmem_inline (XDR *xdrs, u_int len) | 
|  | 196 | { | 
|  | 197 | int32_t *buf = 0; | 
|  | 198 |  | 
|  | 199 | if (xdrs->x_handy >= len) | 
|  | 200 | { | 
|  | 201 | xdrs->x_handy -= len; | 
|  | 202 | buf = (int32_t *) xdrs->x_private; | 
|  | 203 | xdrs->x_private += len; | 
|  | 204 | } | 
|  | 205 | return buf; | 
|  | 206 | } | 
|  | 207 |  | 
|  | 208 | /* | 
|  | 209 | * Gets the next word from the memory referenced by xdrs and places it | 
|  | 210 | * in the int pointed to by ip.  It then increments the private word to | 
|  | 211 | * point at the next element.  Neither object pointed to is const | 
|  | 212 | */ | 
|  | 213 | static bool_t | 
|  | 214 | xdrmem_getint32 (XDR *xdrs, int32_t *ip) | 
|  | 215 | { | 
|  | 216 | if (xdrs->x_handy < 4) | 
|  | 217 | return FALSE; | 
|  | 218 | xdrs->x_handy -= 4; | 
|  | 219 | *ip = ntohl ((*((int32_t *) (xdrs->x_private)))); | 
|  | 220 | xdrs->x_private += 4; | 
|  | 221 | return TRUE; | 
|  | 222 | } | 
|  | 223 |  | 
|  | 224 | /* | 
|  | 225 | * Puts the long pointed to by lp in the memory referenced by xdrs.  It | 
|  | 226 | * then increments the private word to point at the next element.  The | 
|  | 227 | * long pointed at is const | 
|  | 228 | */ | 
|  | 229 | static bool_t | 
|  | 230 | xdrmem_putint32 (XDR *xdrs, const int32_t *ip) | 
|  | 231 | { | 
|  | 232 | if (xdrs->x_handy < 4) | 
|  | 233 | return FALSE; | 
|  | 234 | xdrs->x_handy -= 4; | 
|  | 235 | *(int32_t *) xdrs->x_private = htonl (*ip); | 
|  | 236 | xdrs->x_private += 4; | 
|  | 237 | return TRUE; | 
|  | 238 | } |