1/* $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32#include <sys/cdefs.h> 33/* 34 * xdr_mem.h, XDR implementation using memory buffers. 35 * 36 * Copyright (C) 1984, Sun Microsystems, Inc. 37 * 38 * If you have some data to be interpreted as external data representation 39 * or to be converted to external data representation in a memory buffer, 40 * then this is the package for you. 41 * 42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/malloc.h> 47 48#include <rpc/types.h> 49#include <rpc/xdr.h> 50 51static void xdrmem_destroy(XDR *); 52static bool_t xdrmem_getlong_aligned(XDR *, long *); 53static bool_t xdrmem_putlong_aligned(XDR *, const long *); 54static bool_t xdrmem_getlong_unaligned(XDR *, long *); 55static bool_t xdrmem_putlong_unaligned(XDR *, const long *); 56static bool_t xdrmem_getbytes(XDR *, char *, u_int); 57static bool_t xdrmem_putbytes(XDR *, const char *, u_int); 58/* XXX: w/64-bit pointers, u_int not enough! */ 59static u_int xdrmem_getpos(XDR *); 60static bool_t xdrmem_setpos(XDR *, u_int); 61static int32_t *xdrmem_inline_aligned(XDR *, u_int); 62static int32_t *xdrmem_inline_unaligned(XDR *, u_int); 63static bool_t xdrmem_control(XDR *xdrs, int request, void *info); 64 65static const struct xdr_ops xdrmem_ops_aligned = { 66 xdrmem_getlong_aligned, 67 xdrmem_putlong_aligned, 68 xdrmem_getbytes, 69 xdrmem_putbytes, 70 xdrmem_getpos, 71 xdrmem_setpos, 72 xdrmem_inline_aligned, 73 xdrmem_destroy, 74 xdrmem_control 75}; 76 77static const struct xdr_ops xdrmem_ops_unaligned = { 78 xdrmem_getlong_unaligned, 79 xdrmem_putlong_unaligned, 80 xdrmem_getbytes, 81 xdrmem_putbytes, 82 xdrmem_getpos, 83 xdrmem_setpos, 84 xdrmem_inline_unaligned, 85 xdrmem_destroy, 86 xdrmem_control 87}; 88 89/* 90 * The procedure xdrmem_create initializes a stream descriptor for a 91 * memory buffer. 92 */ 93void 94xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op) 95{ 96 97 xdrs->x_op = op; 98 xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1)) 99 ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned; 100 xdrs->x_private = xdrs->x_base = addr; 101 xdrs->x_handy = size; 102} 103 104/*ARGSUSED*/ 105static void 106xdrmem_destroy(XDR *xdrs) 107{ 108 109} 110 111static bool_t 112xdrmem_getlong_aligned(XDR *xdrs, long *lp) 113{ 114 115 if (xdrs->x_handy < sizeof(int32_t)) 116 return (FALSE); 117 xdrs->x_handy -= sizeof(int32_t); 118 *lp = ntohl(*(uint32_t *)xdrs->x_private); 119 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 120 return (TRUE); 121} 122 123static bool_t 124xdrmem_putlong_aligned(XDR *xdrs, const long *lp) 125{ 126 127 if (xdrs->x_handy < sizeof(int32_t)) 128 return (FALSE); 129 xdrs->x_handy -= sizeof(int32_t); 130 *(uint32_t *)xdrs->x_private = htonl((uint32_t)*lp); 131 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 132 return (TRUE); 133} 134 135static bool_t 136xdrmem_getlong_unaligned(XDR *xdrs, long *lp) 137{ 138 uint32_t l; 139 140 if (xdrs->x_handy < sizeof(int32_t)) 141 return (FALSE); 142 xdrs->x_handy -= sizeof(int32_t); 143 memmove(&l, xdrs->x_private, sizeof(int32_t)); 144 *lp = ntohl(l); 145 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 146 return (TRUE); 147} 148 149static bool_t 150xdrmem_putlong_unaligned(XDR *xdrs, const long *lp) 151{ 152 uint32_t l; 153 154 if (xdrs->x_handy < sizeof(int32_t)) 155 return (FALSE); 156 xdrs->x_handy -= sizeof(int32_t); 157 l = htonl((uint32_t)*lp); 158 memmove(xdrs->x_private, &l, sizeof(int32_t)); 159 xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); 160 return (TRUE); 161} 162 163static bool_t 164xdrmem_getbytes(XDR *xdrs, char *addr, u_int len) 165{ 166 167 if (xdrs->x_handy < len) 168 return (FALSE); 169 xdrs->x_handy -= len; 170 memmove(addr, xdrs->x_private, len); 171 xdrs->x_private = (char *)xdrs->x_private + len; 172 return (TRUE); 173} 174 175static bool_t 176xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len) 177{ 178 179 if (xdrs->x_handy < len) 180 return (FALSE); 181 xdrs->x_handy -= len; 182 memmove(xdrs->x_private, addr, len); 183 xdrs->x_private = (char *)xdrs->x_private + len; 184 return (TRUE); 185} 186 187static u_int 188xdrmem_getpos(XDR *xdrs) 189{ 190 191 /* XXX w/64-bit pointers, u_int not enough! */ 192 return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base); 193} 194 195static bool_t 196xdrmem_setpos(XDR *xdrs, u_int pos) 197{ 198 char *newaddr = xdrs->x_base + pos; 199 char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy; 200 201 if (newaddr > lastaddr) 202 return (FALSE); 203 xdrs->x_private = newaddr; 204 xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) <? sizeof(ptrdiff_t) */ 205 return (TRUE); 206} 207 208static int32_t * 209xdrmem_inline_aligned(XDR *xdrs, u_int len) 210{ 211 int32_t *buf = NULL; 212 213 if (xdrs->x_handy >= len) { 214 xdrs->x_handy -= len; 215 buf = (int32_t *)xdrs->x_private; 216 xdrs->x_private = (char *)xdrs->x_private + len; 217 } 218 return (buf); 219} 220 221/* ARGSUSED */ 222static int32_t * 223xdrmem_inline_unaligned(XDR *xdrs, u_int len) 224{ 225 226 return (0); 227} 228 229static bool_t 230xdrmem_control(XDR *xdrs, int request, void *info) 231{ 232 xdr_bytesrec *xptr; 233 int32_t *l; 234 int len; 235 236 switch (request) { 237 case XDR_GET_BYTES_AVAIL: 238 xptr = (xdr_bytesrec *)info; 239 xptr->xc_is_last_record = TRUE; 240 xptr->xc_num_avail = xdrs->x_handy; 241 return (TRUE); 242 243 case XDR_PEEK: 244 /* 245 * Return the next 4 byte unit in the XDR stream. 246 */ 247 if (xdrs->x_handy < sizeof (int32_t)) 248 return (FALSE); 249 l = (int32_t *)info; 250 *l = (int32_t)ntohl((uint32_t) 251 (*((int32_t *)(xdrs->x_private)))); 252 return (TRUE); 253 254 case XDR_SKIPBYTES: 255 /* 256 * Skip the next N bytes in the XDR stream. 257 */ 258 l = (int32_t *)info; 259 len = RNDUP((int)(*l)); 260 if (xdrs->x_handy < len) 261 return (FALSE); 262 xdrs->x_handy -= len; 263 xdrs->x_private = (char *)xdrs->x_private + len; 264 return (TRUE); 265 } 266 return (FALSE); 267} 268