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 51 static void xdrmem_destroy(XDR *); 52 static bool_t xdrmem_getlong_aligned(XDR *, long *); 53 static bool_t xdrmem_putlong_aligned(XDR *, const long *); 54 static bool_t xdrmem_getlong_unaligned(XDR *, long *); 55 static bool_t xdrmem_putlong_unaligned(XDR *, const long *); 56 static bool_t xdrmem_getbytes(XDR *, char *, u_int); 57 static bool_t xdrmem_putbytes(XDR *, const char *, u_int); 58 /* XXX: w/64-bit pointers, u_int not enough! */ 59 static u_int xdrmem_getpos(XDR *); 60 static bool_t xdrmem_setpos(XDR *, u_int); 61 static int32_t *xdrmem_inline_aligned(XDR *, u_int); 62 static int32_t *xdrmem_inline_unaligned(XDR *, u_int); 63 static bool_t xdrmem_control(XDR *xdrs, int request, void *info); 64 65 static 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 77 static 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 */ 93 void 94 xdrmem_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*/ 105 static void 106 xdrmem_destroy(XDR *xdrs) 107 { 108 109 } 110 111 static bool_t 112 xdrmem_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 123 static bool_t 124 xdrmem_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 135 static bool_t 136 xdrmem_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 149 static bool_t 150 xdrmem_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 163 static bool_t 164 xdrmem_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 175 static bool_t 176 xdrmem_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 187 static u_int 188 xdrmem_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 195 static bool_t 196 xdrmem_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 208 static int32_t * 209 xdrmem_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 */ 222 static int32_t * 223 xdrmem_inline_unaligned(XDR *xdrs, u_int len) 224 { 225 226 return (0); 227 } 228 229 static bool_t 230 xdrmem_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