1 /* $NetBSD: xdr_mem.c,v 1.2 2019/06/05 16:25:43 hannken Exp $ */ 2 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 34 #include <sys/cdefs.h> 35 #if defined(LIBC_SCCS) && !defined(lint) 36 #if 0 37 static char *sccsid = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 38 static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC"; 39 #else 40 __RCSID("$NetBSD: xdr_mem.c,v 1.2 2019/06/05 16:25:43 hannken Exp $"); 41 #endif 42 #endif 43 44 /* 45 * xdr_mem.h, XDR implementation using memory buffers. 46 * 47 * Copyright (C) 1984, Sun Microsystems, Inc. 48 * 49 * If you have some data to be interpreted as external data representation 50 * or to be converted to external data representation in a memory buffer, 51 * then this is the package for you. 52 * 53 */ 54 55 #if defined(_KERNEL) || defined(_STANDALONE) 56 57 #include <lib/libkern/libkern.h> 58 #include <rpc/types.h> 59 #include <rpc/xdr.h> 60 61 #else /* _KERNEL || _STANDALONE */ 62 63 #include "namespace.h" 64 65 #include <sys/types.h> 66 67 #include <netinet/in.h> 68 69 #include <string.h> 70 71 #include <rpc/types.h> 72 #include <rpc/xdr.h> 73 74 #ifdef __weak_alias 75 __weak_alias(xdrmem_create,_xdrmem_create) 76 #endif 77 78 #endif /* _KERNEL || _STANDALONE */ 79 80 static void xdrmem_destroy(XDR *); 81 static bool_t xdrmem_getlong_aligned(XDR *, long *); 82 static bool_t xdrmem_putlong_aligned(XDR *, const long *); 83 static bool_t xdrmem_getlong_unaligned(XDR *, long *); 84 static bool_t xdrmem_putlong_unaligned(XDR *, const long *); 85 static bool_t xdrmem_getbytes(XDR *, char *, u_int); 86 static bool_t xdrmem_putbytes(XDR *, const char *, u_int); 87 /* XXX: w/64-bit pointers, u_int not enough! */ 88 static u_int xdrmem_getpos(XDR *); 89 static bool_t xdrmem_setpos(XDR *, u_int); 90 static int32_t *xdrmem_inline_aligned(XDR *, u_int); 91 static int32_t *xdrmem_inline_unaligned(XDR *, u_int); 92 static bool_t xdrmem_control(XDR *xdrs, int request, void *info); 93 94 static const struct xdr_ops xdrmem_ops_aligned = { 95 xdrmem_getlong_aligned, 96 xdrmem_putlong_aligned, 97 xdrmem_getbytes, 98 xdrmem_putbytes, 99 xdrmem_getpos, 100 xdrmem_setpos, 101 xdrmem_inline_aligned, 102 xdrmem_destroy, 103 xdrmem_control 104 }; 105 106 static const struct xdr_ops xdrmem_ops_unaligned = { 107 xdrmem_getlong_unaligned, 108 xdrmem_putlong_unaligned, 109 xdrmem_getbytes, 110 xdrmem_putbytes, 111 xdrmem_getpos, 112 xdrmem_setpos, 113 xdrmem_inline_unaligned, 114 xdrmem_destroy, 115 xdrmem_control 116 }; 117 118 /* 119 * The procedure xdrmem_create initializes a stream descriptor for a 120 * memory buffer. 121 */ 122 void 123 xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op) 124 { 125 126 xdrs->x_op = op; 127 xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1)) 128 ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned; 129 xdrs->x_private = xdrs->x_base = addr; 130 xdrs->x_handy = size; 131 } 132 133 /*ARGSUSED*/ 134 static void 135 xdrmem_destroy(XDR *xdrs) 136 { 137 138 } 139 140 static bool_t 141 xdrmem_getlong_aligned(XDR *xdrs, long *lp) 142 { 143 144 if (xdrs->x_handy < sizeof(int32_t)) 145 return (FALSE); 146 xdrs->x_handy -= sizeof(int32_t); 147 *lp = ntohl(*(u_int32_t *)xdrs->x_private); 148 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 149 return (TRUE); 150 } 151 152 static bool_t 153 xdrmem_putlong_aligned(XDR *xdrs, const long *lp) 154 { 155 156 if (xdrs->x_handy < sizeof(int32_t)) 157 return (FALSE); 158 xdrs->x_handy -= sizeof(int32_t); 159 *(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp); 160 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 161 return (TRUE); 162 } 163 164 static bool_t 165 xdrmem_getlong_unaligned(XDR *xdrs, long *lp) 166 { 167 u_int32_t l; 168 169 if (xdrs->x_handy < sizeof(int32_t)) 170 return (FALSE); 171 xdrs->x_handy -= sizeof(int32_t); 172 memmove(&l, xdrs->x_private, sizeof(int32_t)); 173 *lp = ntohl(l); 174 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 175 return (TRUE); 176 } 177 178 static bool_t 179 xdrmem_putlong_unaligned(XDR *xdrs, const long *lp) 180 { 181 u_int32_t l; 182 183 if (xdrs->x_handy < sizeof(int32_t)) 184 return (FALSE); 185 xdrs->x_handy -= sizeof(int32_t); 186 l = htonl((u_int32_t)*lp); 187 memmove(xdrs->x_private, &l, sizeof(int32_t)); 188 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 189 return (TRUE); 190 } 191 192 static bool_t 193 xdrmem_getbytes(XDR *xdrs, char *addr, u_int len) 194 { 195 196 if (xdrs->x_handy < len) 197 return (FALSE); 198 xdrs->x_handy -= len; 199 memmove(addr, xdrs->x_private, len); 200 xdrs->x_private = (char *)xdrs->x_private + len; 201 return (TRUE); 202 } 203 204 static bool_t 205 xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len) 206 { 207 208 if (xdrs->x_handy < len) 209 return (FALSE); 210 xdrs->x_handy -= len; 211 memmove(xdrs->x_private, addr, len); 212 xdrs->x_private = (char *)xdrs->x_private + len; 213 return (TRUE); 214 } 215 216 static u_int 217 xdrmem_getpos(XDR *xdrs) 218 { 219 220 /* XXX w/64-bit pointers, u_int not enough! */ 221 return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base); 222 } 223 224 static bool_t 225 xdrmem_setpos(XDR *xdrs, u_int pos) 226 { 227 char *newaddr = xdrs->x_base + pos; 228 char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy; 229 230 if ((long)newaddr > (long)lastaddr) 231 return (FALSE); 232 xdrs->x_private = newaddr; 233 xdrs->x_handy = (int)((long)lastaddr - (long)newaddr); 234 return (TRUE); 235 } 236 237 static int32_t * 238 xdrmem_inline_aligned(XDR *xdrs, u_int len) 239 { 240 int32_t *buf = 0; 241 242 if (xdrs->x_handy >= len) { 243 xdrs->x_handy -= len; 244 buf = (int32_t *)xdrs->x_private; 245 xdrs->x_private = (char *)xdrs->x_private + len; 246 } 247 return (buf); 248 } 249 250 /* ARGSUSED */ 251 static int32_t * 252 xdrmem_inline_unaligned(XDR *xdrs, u_int len) 253 { 254 255 return (0); 256 } 257 258 static bool_t 259 xdrmem_control(XDR *xdrs, int request, void *info) 260 { 261 xdr_bytesrec *xptr; 262 263 switch (request) { 264 265 case XDR_GET_BYTES_AVAIL: 266 xptr = (xdr_bytesrec *)info; 267 xptr->xc_is_last_record = TRUE; 268 xptr->xc_num_avail = xdrs->x_handy; 269 return (TRUE); 270 271 } 272 return (FALSE); 273 } 274