1eae561b3SGarrett Wollman /* 2eae561b3SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3eae561b3SGarrett Wollman * unrestricted use provided that this legend is included on all tape 4eae561b3SGarrett Wollman * media and as a part of the software program in whole or part. Users 5eae561b3SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 6eae561b3SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 7eae561b3SGarrett Wollman * program developed by the user. 8eae561b3SGarrett Wollman * 9eae561b3SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10eae561b3SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11eae561b3SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12eae561b3SGarrett Wollman * 13eae561b3SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 14eae561b3SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 15eae561b3SGarrett Wollman * modification or enhancement. 16eae561b3SGarrett Wollman * 17eae561b3SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18eae561b3SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19eae561b3SGarrett Wollman * OR ANY PART THEREOF. 20eae561b3SGarrett Wollman * 21eae561b3SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22eae561b3SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 23eae561b3SGarrett Wollman * Sun has been advised of the possibility of such damages. 24eae561b3SGarrett Wollman * 25eae561b3SGarrett Wollman * Sun Microsystems, Inc. 26eae561b3SGarrett Wollman * 2550 Garcia Avenue 27eae561b3SGarrett Wollman * Mountain View, California 94043 28eae561b3SGarrett Wollman */ 29eae561b3SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 30eae561b3SGarrett Wollman /*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ 31eae561b3SGarrett Wollman /*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/ 321ce4aec2SBill Paul static char *rcsid = "$Id: xdr_rec.c,v 1.9 1998/05/15 22:57:31 wpaul Exp $"; 33eae561b3SGarrett Wollman #endif 34eae561b3SGarrett Wollman 35eae561b3SGarrett Wollman /* 36eae561b3SGarrett Wollman * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" 37eae561b3SGarrett Wollman * layer above tcp (for rpc's use). 38eae561b3SGarrett Wollman * 39eae561b3SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 40eae561b3SGarrett Wollman * 41eae561b3SGarrett Wollman * These routines interface XDRSTREAMS to a tcp/ip connection. 42eae561b3SGarrett Wollman * There is a record marking layer between the xdr stream 43eae561b3SGarrett Wollman * and the tcp transport level. A record is composed on one or more 44eae561b3SGarrett Wollman * record fragments. A record fragment is a thirty-two bit header followed 45eae561b3SGarrett Wollman * by n bytes of data, where n is contained in the header. The header 46eae561b3SGarrett Wollman * is represented as a htonl(u_long). Thegh order bit encodes 47eae561b3SGarrett Wollman * whether or not the fragment is the last fragment of the record 48eae561b3SGarrett Wollman * (1 => fragment is last, 0 => more fragments to follow. 49eae561b3SGarrett Wollman * The other 31 bits encode the byte length of the fragment. 50eae561b3SGarrett Wollman */ 51eae561b3SGarrett Wollman 52eae561b3SGarrett Wollman #include <stdio.h> 53eae561b3SGarrett Wollman #include <stdlib.h> 5429285d6cSPoul-Henning Kamp #include <string.h> 55eae561b3SGarrett Wollman #include <rpc/types.h> 56eae561b3SGarrett Wollman #include <rpc/xdr.h> 57eae561b3SGarrett Wollman #include <netinet/in.h> 58eae561b3SGarrett Wollman 59eae561b3SGarrett Wollman static u_int fix_buf_size(); 60eae561b3SGarrett Wollman static bool_t flush_out(); 61eae561b3SGarrett Wollman static bool_t get_input_bytes(); 62eae561b3SGarrett Wollman static bool_t set_input_fragment(); 63eae561b3SGarrett Wollman static bool_t skip_input_bytes(); 64eae561b3SGarrett Wollman 65eae561b3SGarrett Wollman static bool_t xdrrec_getlong(); 66eae561b3SGarrett Wollman static bool_t xdrrec_putlong(); 67eae561b3SGarrett Wollman static bool_t xdrrec_getbytes(); 68eae561b3SGarrett Wollman static bool_t xdrrec_putbytes(); 69eae561b3SGarrett Wollman static u_int xdrrec_getpos(); 70eae561b3SGarrett Wollman static bool_t xdrrec_setpos(); 711ad08a09SPeter Wemm static int32_t *xdrrec_inline(); 72eae561b3SGarrett Wollman static void xdrrec_destroy(); 73eae561b3SGarrett Wollman 74eae561b3SGarrett Wollman static struct xdr_ops xdrrec_ops = { 75eae561b3SGarrett Wollman xdrrec_getlong, 76eae561b3SGarrett Wollman xdrrec_putlong, 77eae561b3SGarrett Wollman xdrrec_getbytes, 78eae561b3SGarrett Wollman xdrrec_putbytes, 79eae561b3SGarrett Wollman xdrrec_getpos, 80eae561b3SGarrett Wollman xdrrec_setpos, 81eae561b3SGarrett Wollman xdrrec_inline, 82eae561b3SGarrett Wollman xdrrec_destroy 83eae561b3SGarrett Wollman }; 84eae561b3SGarrett Wollman 85eae561b3SGarrett Wollman /* 86eae561b3SGarrett Wollman * A record is composed of one or more record fragments. 87eae561b3SGarrett Wollman * A record fragment is a two-byte header followed by zero to 88eae561b3SGarrett Wollman * 2**32-1 bytes. The header is treated as a long unsigned and is 89eae561b3SGarrett Wollman * encode/decoded to the network via htonl/ntohl. The low order 31 bits 90eae561b3SGarrett Wollman * are a byte count of the fragment. The highest order bit is a boolean: 91eae561b3SGarrett Wollman * 1 => this fragment is the last fragment of the record, 92eae561b3SGarrett Wollman * 0 => this fragment is followed by more fragment(s). 93eae561b3SGarrett Wollman * 94eae561b3SGarrett Wollman * The fragment/record machinery is not general; it is constructed to 95eae561b3SGarrett Wollman * meet the needs of xdr and rpc based on tcp. 96eae561b3SGarrett Wollman */ 97eae561b3SGarrett Wollman 981ad08a09SPeter Wemm #define LAST_FRAG ((u_int32_t)(1 << 31)) 99eae561b3SGarrett Wollman 100eae561b3SGarrett Wollman typedef struct rec_strm { 101eae561b3SGarrett Wollman caddr_t tcp_handle; 102eae561b3SGarrett Wollman caddr_t the_buffer; 103eae561b3SGarrett Wollman /* 104eae561b3SGarrett Wollman * out-goung bits 105eae561b3SGarrett Wollman */ 1061ad08a09SPeter Wemm int (*writeit) __P((caddr_t, caddr_t, int)); 107eae561b3SGarrett Wollman caddr_t out_base; /* output buffer (points to frag header) */ 108eae561b3SGarrett Wollman caddr_t out_finger; /* next output position */ 109eae561b3SGarrett Wollman caddr_t out_boundry; /* data cannot up to this address */ 1101ad08a09SPeter Wemm u_int32_t *frag_header; /* beginning of current fragment */ 111eae561b3SGarrett Wollman bool_t frag_sent; /* true if buffer sent in middle of record */ 112eae561b3SGarrett Wollman /* 113eae561b3SGarrett Wollman * in-coming bits 114eae561b3SGarrett Wollman */ 1151ad08a09SPeter Wemm int (*readit) __P((caddr_t, caddr_t, int)); 116eae561b3SGarrett Wollman u_long in_size; /* fixed size of the input buffer */ 117eae561b3SGarrett Wollman caddr_t in_base; 118eae561b3SGarrett Wollman caddr_t in_finger; /* location of next byte to be had */ 119eae561b3SGarrett Wollman caddr_t in_boundry; /* can read up to this location */ 120eae561b3SGarrett Wollman long fbtbc; /* fragment bytes to be consumed */ 121eae561b3SGarrett Wollman bool_t last_frag; 122eae561b3SGarrett Wollman u_int sendsize; 123eae561b3SGarrett Wollman u_int recvsize; 124eae561b3SGarrett Wollman } RECSTREAM; 125eae561b3SGarrett Wollman 126eae561b3SGarrett Wollman 127eae561b3SGarrett Wollman /* 128eae561b3SGarrett Wollman * Create an xdr handle for xdrrec 129eae561b3SGarrett Wollman * xdrrec_create fills in xdrs. Sendsize and recvsize are 130eae561b3SGarrett Wollman * send and recv buffer sizes (0 => use default). 131eae561b3SGarrett Wollman * tcp_handle is an opaque handle that is passed as the first parameter to 132eae561b3SGarrett Wollman * the procedures readit and writeit. Readit and writeit are read and 133eae561b3SGarrett Wollman * write respectively. They are like the system 134eae561b3SGarrett Wollman * calls expect that they take an opaque handle rather than an fd. 135eae561b3SGarrett Wollman */ 136eae561b3SGarrett Wollman void 137eae561b3SGarrett Wollman xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) 138eae561b3SGarrett Wollman register XDR *xdrs; 139eae561b3SGarrett Wollman register u_int sendsize; 140eae561b3SGarrett Wollman register u_int recvsize; 141eae561b3SGarrett Wollman caddr_t tcp_handle; 142eae561b3SGarrett Wollman int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ 143eae561b3SGarrett Wollman int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ 144eae561b3SGarrett Wollman { 145eae561b3SGarrett Wollman register RECSTREAM *rstrm = 146eae561b3SGarrett Wollman (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); 147eae561b3SGarrett Wollman 148eae561b3SGarrett Wollman if (rstrm == NULL) { 149eae561b3SGarrett Wollman (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 150eae561b3SGarrett Wollman /* 151eae561b3SGarrett Wollman * This is bad. Should rework xdrrec_create to 152eae561b3SGarrett Wollman * return a handle, and in this case return NULL 153eae561b3SGarrett Wollman */ 154eae561b3SGarrett Wollman return; 155eae561b3SGarrett Wollman } 156eae561b3SGarrett Wollman /* 157eae561b3SGarrett Wollman * adjust sizes and allocate buffer quad byte aligned 158eae561b3SGarrett Wollman */ 159eae561b3SGarrett Wollman rstrm->sendsize = sendsize = fix_buf_size(sendsize); 160eae561b3SGarrett Wollman rstrm->recvsize = recvsize = fix_buf_size(recvsize); 161eae561b3SGarrett Wollman rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); 162eae561b3SGarrett Wollman if (rstrm->the_buffer == NULL) { 163eae561b3SGarrett Wollman (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 164eae561b3SGarrett Wollman return; 165eae561b3SGarrett Wollman } 166eae561b3SGarrett Wollman for (rstrm->out_base = rstrm->the_buffer; 1671ad08a09SPeter Wemm (u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; 168eae561b3SGarrett Wollman rstrm->out_base++); 169eae561b3SGarrett Wollman rstrm->in_base = rstrm->out_base + sendsize; 170eae561b3SGarrett Wollman /* 171eae561b3SGarrett Wollman * now the rest ... 172eae561b3SGarrett Wollman */ 173eae561b3SGarrett Wollman xdrs->x_ops = &xdrrec_ops; 174eae561b3SGarrett Wollman xdrs->x_private = (caddr_t)rstrm; 175eae561b3SGarrett Wollman rstrm->tcp_handle = tcp_handle; 176eae561b3SGarrett Wollman rstrm->readit = readit; 177eae561b3SGarrett Wollman rstrm->writeit = writeit; 178eae561b3SGarrett Wollman rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; 1791ad08a09SPeter Wemm rstrm->frag_header = (u_int32_t *)rstrm->out_base; 1801ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 181eae561b3SGarrett Wollman rstrm->out_boundry += sendsize; 182eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 183eae561b3SGarrett Wollman rstrm->in_size = recvsize; 184eae561b3SGarrett Wollman rstrm->in_boundry = rstrm->in_base; 185eae561b3SGarrett Wollman rstrm->in_finger = (rstrm->in_boundry += recvsize); 186eae561b3SGarrett Wollman rstrm->fbtbc = 0; 187eae561b3SGarrett Wollman rstrm->last_frag = TRUE; 188eae561b3SGarrett Wollman } 189eae561b3SGarrett Wollman 190eae561b3SGarrett Wollman 191eae561b3SGarrett Wollman /* 192eae561b3SGarrett Wollman * The reoutines defined below are the xdr ops which will go into the 193eae561b3SGarrett Wollman * xdr handle filled in by xdrrec_create. 194eae561b3SGarrett Wollman */ 195eae561b3SGarrett Wollman 196eae561b3SGarrett Wollman static bool_t 197eae561b3SGarrett Wollman xdrrec_getlong(xdrs, lp) 198eae561b3SGarrett Wollman XDR *xdrs; 199eae561b3SGarrett Wollman long *lp; 200eae561b3SGarrett Wollman { 201eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2021ad08a09SPeter Wemm register int32_t *buflp = (int32_t *)(rstrm->in_finger); 2031ad08a09SPeter Wemm int32_t mylong; 204eae561b3SGarrett Wollman 205eae561b3SGarrett Wollman /* first try the inline, fast case */ 2061ad08a09SPeter Wemm if ((rstrm->fbtbc >= sizeof(int32_t)) && 2071ad08a09SPeter Wemm (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { 2081ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)(*buflp)); 2091ad08a09SPeter Wemm rstrm->fbtbc -= sizeof(int32_t); 2101ad08a09SPeter Wemm rstrm->in_finger += sizeof(int32_t); 211eae561b3SGarrett Wollman } else { 2121ad08a09SPeter Wemm if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(int32_t))) 213eae561b3SGarrett Wollman return (FALSE); 2141ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)mylong); 215eae561b3SGarrett Wollman } 216eae561b3SGarrett Wollman return (TRUE); 217eae561b3SGarrett Wollman } 218eae561b3SGarrett Wollman 219eae561b3SGarrett Wollman static bool_t 220eae561b3SGarrett Wollman xdrrec_putlong(xdrs, lp) 221eae561b3SGarrett Wollman XDR *xdrs; 222eae561b3SGarrett Wollman long *lp; 223eae561b3SGarrett Wollman { 224eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2251ad08a09SPeter Wemm register int32_t *dest_lp = ((int32_t *)(rstrm->out_finger)); 226eae561b3SGarrett Wollman 2271ad08a09SPeter Wemm if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { 228eae561b3SGarrett Wollman /* 229eae561b3SGarrett Wollman * this case should almost never happen so the code is 230eae561b3SGarrett Wollman * inefficient 231eae561b3SGarrett Wollman */ 2321ad08a09SPeter Wemm rstrm->out_finger -= sizeof(int32_t); 233eae561b3SGarrett Wollman rstrm->frag_sent = TRUE; 234eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE)) 235eae561b3SGarrett Wollman return (FALSE); 2361ad08a09SPeter Wemm dest_lp = ((int32_t *)(rstrm->out_finger)); 2371ad08a09SPeter Wemm rstrm->out_finger += sizeof(int32_t); 238eae561b3SGarrett Wollman } 2391ad08a09SPeter Wemm *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); 240eae561b3SGarrett Wollman return (TRUE); 241eae561b3SGarrett Wollman } 242eae561b3SGarrett Wollman 243eae561b3SGarrett Wollman static bool_t /* must manage buffers, fragments, and records */ 244eae561b3SGarrett Wollman xdrrec_getbytes(xdrs, addr, len) 245eae561b3SGarrett Wollman XDR *xdrs; 246eae561b3SGarrett Wollman register caddr_t addr; 247eae561b3SGarrett Wollman register u_int len; 248eae561b3SGarrett Wollman { 249eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 250eae561b3SGarrett Wollman register int current; 251eae561b3SGarrett Wollman 252eae561b3SGarrett Wollman while (len > 0) { 253eae561b3SGarrett Wollman current = rstrm->fbtbc; 254eae561b3SGarrett Wollman if (current == 0) { 255eae561b3SGarrett Wollman if (rstrm->last_frag) 256eae561b3SGarrett Wollman return (FALSE); 257eae561b3SGarrett Wollman if (! set_input_fragment(rstrm)) 258eae561b3SGarrett Wollman return (FALSE); 259eae561b3SGarrett Wollman continue; 260eae561b3SGarrett Wollman } 261eae561b3SGarrett Wollman current = (len < current) ? len : current; 262eae561b3SGarrett Wollman if (! get_input_bytes(rstrm, addr, current)) 263eae561b3SGarrett Wollman return (FALSE); 264eae561b3SGarrett Wollman addr += current; 265eae561b3SGarrett Wollman rstrm->fbtbc -= current; 266eae561b3SGarrett Wollman len -= current; 267eae561b3SGarrett Wollman } 268eae561b3SGarrett Wollman return (TRUE); 269eae561b3SGarrett Wollman } 270eae561b3SGarrett Wollman 271eae561b3SGarrett Wollman static bool_t 272eae561b3SGarrett Wollman xdrrec_putbytes(xdrs, addr, len) 273eae561b3SGarrett Wollman XDR *xdrs; 274eae561b3SGarrett Wollman register caddr_t addr; 275eae561b3SGarrett Wollman register u_int len; 276eae561b3SGarrett Wollman { 277eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2781ad08a09SPeter Wemm register long current; 279eae561b3SGarrett Wollman 280eae561b3SGarrett Wollman while (len > 0) { 2811ad08a09SPeter Wemm current = (u_long)rstrm->out_boundry - 2821ad08a09SPeter Wemm (u_long)rstrm->out_finger; 283eae561b3SGarrett Wollman current = (len < current) ? len : current; 2841ad08a09SPeter Wemm memcpy(rstrm->out_finger, addr, current); 285eae561b3SGarrett Wollman rstrm->out_finger += current; 286eae561b3SGarrett Wollman addr += current; 287eae561b3SGarrett Wollman len -= current; 288eae561b3SGarrett Wollman if (rstrm->out_finger == rstrm->out_boundry) { 289eae561b3SGarrett Wollman rstrm->frag_sent = TRUE; 290eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE)) 291eae561b3SGarrett Wollman return (FALSE); 292eae561b3SGarrett Wollman } 293eae561b3SGarrett Wollman } 294eae561b3SGarrett Wollman return (TRUE); 295eae561b3SGarrett Wollman } 296eae561b3SGarrett Wollman 297eae561b3SGarrett Wollman static u_int 298eae561b3SGarrett Wollman xdrrec_getpos(xdrs) 299eae561b3SGarrett Wollman register XDR *xdrs; 300eae561b3SGarrett Wollman { 301eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 302eae561b3SGarrett Wollman register long pos; 303eae561b3SGarrett Wollman 3041ad08a09SPeter Wemm pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1); 305eae561b3SGarrett Wollman if (pos != -1) 306eae561b3SGarrett Wollman switch (xdrs->x_op) { 307eae561b3SGarrett Wollman 308eae561b3SGarrett Wollman case XDR_ENCODE: 309eae561b3SGarrett Wollman pos += rstrm->out_finger - rstrm->out_base; 310eae561b3SGarrett Wollman break; 311eae561b3SGarrett Wollman 312eae561b3SGarrett Wollman case XDR_DECODE: 313eae561b3SGarrett Wollman pos -= rstrm->in_boundry - rstrm->in_finger; 314eae561b3SGarrett Wollman break; 315eae561b3SGarrett Wollman 316eae561b3SGarrett Wollman default: 3171ad08a09SPeter Wemm pos = -1; 318eae561b3SGarrett Wollman break; 319eae561b3SGarrett Wollman } 320eae561b3SGarrett Wollman return ((u_int) pos); 321eae561b3SGarrett Wollman } 322eae561b3SGarrett Wollman 323eae561b3SGarrett Wollman static bool_t 324eae561b3SGarrett Wollman xdrrec_setpos(xdrs, pos) 325eae561b3SGarrett Wollman register XDR *xdrs; 326eae561b3SGarrett Wollman u_int pos; 327eae561b3SGarrett Wollman { 328eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 329eae561b3SGarrett Wollman u_int currpos = xdrrec_getpos(xdrs); 330eae561b3SGarrett Wollman int delta = currpos - pos; 331eae561b3SGarrett Wollman caddr_t newpos; 332eae561b3SGarrett Wollman 333eae561b3SGarrett Wollman if ((int)currpos != -1) 334eae561b3SGarrett Wollman switch (xdrs->x_op) { 335eae561b3SGarrett Wollman 336eae561b3SGarrett Wollman case XDR_ENCODE: 337eae561b3SGarrett Wollman newpos = rstrm->out_finger - delta; 338eae561b3SGarrett Wollman if ((newpos > (caddr_t)(rstrm->frag_header)) && 339eae561b3SGarrett Wollman (newpos < rstrm->out_boundry)) { 340eae561b3SGarrett Wollman rstrm->out_finger = newpos; 341eae561b3SGarrett Wollman return (TRUE); 342eae561b3SGarrett Wollman } 343eae561b3SGarrett Wollman break; 344eae561b3SGarrett Wollman 345eae561b3SGarrett Wollman case XDR_DECODE: 346eae561b3SGarrett Wollman newpos = rstrm->in_finger - delta; 347eae561b3SGarrett Wollman if ((delta < (int)(rstrm->fbtbc)) && 348eae561b3SGarrett Wollman (newpos <= rstrm->in_boundry) && 349eae561b3SGarrett Wollman (newpos >= rstrm->in_base)) { 350eae561b3SGarrett Wollman rstrm->in_finger = newpos; 351eae561b3SGarrett Wollman rstrm->fbtbc -= delta; 352eae561b3SGarrett Wollman return (TRUE); 353eae561b3SGarrett Wollman } 354eae561b3SGarrett Wollman break; 355eae561b3SGarrett Wollman } 356eae561b3SGarrett Wollman return (FALSE); 357eae561b3SGarrett Wollman } 358eae561b3SGarrett Wollman 3591ad08a09SPeter Wemm static int32_t * 360eae561b3SGarrett Wollman xdrrec_inline(xdrs, len) 361eae561b3SGarrett Wollman register XDR *xdrs; 362eae561b3SGarrett Wollman int len; 363eae561b3SGarrett Wollman { 364eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3651ad08a09SPeter Wemm int32_t * buf = NULL; 366eae561b3SGarrett Wollman 367eae561b3SGarrett Wollman switch (xdrs->x_op) { 368eae561b3SGarrett Wollman 369eae561b3SGarrett Wollman case XDR_ENCODE: 370eae561b3SGarrett Wollman if ((rstrm->out_finger + len) <= rstrm->out_boundry) { 3711ad08a09SPeter Wemm buf = (int32_t *) rstrm->out_finger; 372eae561b3SGarrett Wollman rstrm->out_finger += len; 373eae561b3SGarrett Wollman } 374eae561b3SGarrett Wollman break; 375eae561b3SGarrett Wollman 376eae561b3SGarrett Wollman case XDR_DECODE: 377eae561b3SGarrett Wollman if ((len <= rstrm->fbtbc) && 378eae561b3SGarrett Wollman ((rstrm->in_finger + len) <= rstrm->in_boundry)) { 3791ad08a09SPeter Wemm buf = (int32_t *) rstrm->in_finger; 380eae561b3SGarrett Wollman rstrm->fbtbc -= len; 381eae561b3SGarrett Wollman rstrm->in_finger += len; 382eae561b3SGarrett Wollman } 383eae561b3SGarrett Wollman break; 384eae561b3SGarrett Wollman } 385eae561b3SGarrett Wollman return (buf); 386eae561b3SGarrett Wollman } 387eae561b3SGarrett Wollman 388eae561b3SGarrett Wollman static void 389eae561b3SGarrett Wollman xdrrec_destroy(xdrs) 390eae561b3SGarrett Wollman register XDR *xdrs; 391eae561b3SGarrett Wollman { 392eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 393eae561b3SGarrett Wollman 394eae561b3SGarrett Wollman mem_free(rstrm->the_buffer, 395eae561b3SGarrett Wollman rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); 396eae561b3SGarrett Wollman mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); 397eae561b3SGarrett Wollman } 398eae561b3SGarrett Wollman 399eae561b3SGarrett Wollman 400eae561b3SGarrett Wollman /* 401eae561b3SGarrett Wollman * Exported routines to manage xdr records 402eae561b3SGarrett Wollman */ 403eae561b3SGarrett Wollman 404eae561b3SGarrett Wollman /* 405eae561b3SGarrett Wollman * Before reading (deserializing from the stream, one should always call 406eae561b3SGarrett Wollman * this procedure to guarantee proper record alignment. 407eae561b3SGarrett Wollman */ 408eae561b3SGarrett Wollman bool_t 409eae561b3SGarrett Wollman xdrrec_skiprecord(xdrs) 410eae561b3SGarrett Wollman XDR *xdrs; 411eae561b3SGarrett Wollman { 412eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 413eae561b3SGarrett Wollman 414eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 415eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 416eae561b3SGarrett Wollman return (FALSE); 417eae561b3SGarrett Wollman rstrm->fbtbc = 0; 418eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 419eae561b3SGarrett Wollman return (FALSE); 420eae561b3SGarrett Wollman } 421eae561b3SGarrett Wollman rstrm->last_frag = FALSE; 422eae561b3SGarrett Wollman return (TRUE); 423eae561b3SGarrett Wollman } 424eae561b3SGarrett Wollman 425eae561b3SGarrett Wollman /* 426eae561b3SGarrett Wollman * Look ahead fuction. 427eae561b3SGarrett Wollman * Returns TRUE iff there is no more input in the buffer 428eae561b3SGarrett Wollman * after consuming the rest of the current record. 429eae561b3SGarrett Wollman */ 430eae561b3SGarrett Wollman bool_t 431eae561b3SGarrett Wollman xdrrec_eof(xdrs) 432eae561b3SGarrett Wollman XDR *xdrs; 433eae561b3SGarrett Wollman { 434eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 435eae561b3SGarrett Wollman 436eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 437eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 438eae561b3SGarrett Wollman return (TRUE); 439eae561b3SGarrett Wollman rstrm->fbtbc = 0; 440eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 441eae561b3SGarrett Wollman return (TRUE); 442eae561b3SGarrett Wollman } 443eae561b3SGarrett Wollman if (rstrm->in_finger == rstrm->in_boundry) 444eae561b3SGarrett Wollman return (TRUE); 445eae561b3SGarrett Wollman return (FALSE); 446eae561b3SGarrett Wollman } 447eae561b3SGarrett Wollman 448eae561b3SGarrett Wollman /* 449eae561b3SGarrett Wollman * The client must tell the package when an end-of-record has occurred. 450eae561b3SGarrett Wollman * The second paraemters tells whether the record should be flushed to the 451eae561b3SGarrett Wollman * (output) tcp stream. (This let's the package support batched or 452eae561b3SGarrett Wollman * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. 453eae561b3SGarrett Wollman */ 454eae561b3SGarrett Wollman bool_t 455eae561b3SGarrett Wollman xdrrec_endofrecord(xdrs, sendnow) 456eae561b3SGarrett Wollman XDR *xdrs; 457eae561b3SGarrett Wollman bool_t sendnow; 458eae561b3SGarrett Wollman { 459eae561b3SGarrett Wollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 460eae561b3SGarrett Wollman register u_long len; /* fragment length */ 461eae561b3SGarrett Wollman 462eae561b3SGarrett Wollman if (sendnow || rstrm->frag_sent || 4631ad08a09SPeter Wemm ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= 464eae561b3SGarrett Wollman (u_long)rstrm->out_boundry)) { 465eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 466eae561b3SGarrett Wollman return (flush_out(rstrm, TRUE)); 467eae561b3SGarrett Wollman } 468eae561b3SGarrett Wollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - 4691ad08a09SPeter Wemm sizeof(u_int32_t); 470eae561b3SGarrett Wollman *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG); 4711ad08a09SPeter Wemm rstrm->frag_header = (u_int32_t *)rstrm->out_finger; 4721ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 473eae561b3SGarrett Wollman return (TRUE); 474eae561b3SGarrett Wollman } 475eae561b3SGarrett Wollman 476eae561b3SGarrett Wollman 477eae561b3SGarrett Wollman /* 478eae561b3SGarrett Wollman * Internal useful routines 479eae561b3SGarrett Wollman */ 480eae561b3SGarrett Wollman static bool_t 481eae561b3SGarrett Wollman flush_out(rstrm, eor) 482eae561b3SGarrett Wollman register RECSTREAM *rstrm; 483eae561b3SGarrett Wollman bool_t eor; 484eae561b3SGarrett Wollman { 485eae561b3SGarrett Wollman register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; 4861ad08a09SPeter Wemm register u_int32_t len = (u_long)(rstrm->out_finger) - 4871ad08a09SPeter Wemm (u_long)(rstrm->frag_header) - sizeof(u_int32_t); 488eae561b3SGarrett Wollman 489eae561b3SGarrett Wollman *(rstrm->frag_header) = htonl(len | eormask); 490eae561b3SGarrett Wollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base); 491eae561b3SGarrett Wollman if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) 492eae561b3SGarrett Wollman != (int)len) 493eae561b3SGarrett Wollman return (FALSE); 4941ad08a09SPeter Wemm rstrm->frag_header = (u_int32_t *)rstrm->out_base; 4951ad08a09SPeter Wemm rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_int32_t); 496eae561b3SGarrett Wollman return (TRUE); 497eae561b3SGarrett Wollman } 498eae561b3SGarrett Wollman 499eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 500eae561b3SGarrett Wollman fill_input_buf(rstrm) 501eae561b3SGarrett Wollman register RECSTREAM *rstrm; 502eae561b3SGarrett Wollman { 503eae561b3SGarrett Wollman register caddr_t where; 5041ad08a09SPeter Wemm u_long i; 5051ad08a09SPeter Wemm register long len; 506eae561b3SGarrett Wollman 507eae561b3SGarrett Wollman where = rstrm->in_base; 5081ad08a09SPeter Wemm i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT; 509eae561b3SGarrett Wollman where += i; 510eae561b3SGarrett Wollman len = rstrm->in_size - i; 511eae561b3SGarrett Wollman if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) 512eae561b3SGarrett Wollman return (FALSE); 513eae561b3SGarrett Wollman rstrm->in_finger = where; 514eae561b3SGarrett Wollman where += len; 515eae561b3SGarrett Wollman rstrm->in_boundry = where; 516eae561b3SGarrett Wollman return (TRUE); 517eae561b3SGarrett Wollman } 518eae561b3SGarrett Wollman 519eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 520eae561b3SGarrett Wollman get_input_bytes(rstrm, addr, len) 521eae561b3SGarrett Wollman register RECSTREAM *rstrm; 522eae561b3SGarrett Wollman register caddr_t addr; 523eae561b3SGarrett Wollman register int len; 524eae561b3SGarrett Wollman { 5251ad08a09SPeter Wemm register long current; 526eae561b3SGarrett Wollman 527eae561b3SGarrett Wollman while (len > 0) { 5281ad08a09SPeter Wemm current = (long)rstrm->in_boundry - (long)rstrm->in_finger; 529eae561b3SGarrett Wollman if (current == 0) { 530eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 531eae561b3SGarrett Wollman return (FALSE); 532eae561b3SGarrett Wollman continue; 533eae561b3SGarrett Wollman } 534eae561b3SGarrett Wollman current = (len < current) ? len : current; 5351ad08a09SPeter Wemm memcpy(addr, rstrm->in_finger, current); 536eae561b3SGarrett Wollman rstrm->in_finger += current; 537eae561b3SGarrett Wollman addr += current; 538eae561b3SGarrett Wollman len -= current; 539eae561b3SGarrett Wollman } 540eae561b3SGarrett Wollman return (TRUE); 541eae561b3SGarrett Wollman } 542eae561b3SGarrett Wollman 543eae561b3SGarrett Wollman static bool_t /* next two bytes of the input stream are treated as a header */ 544eae561b3SGarrett Wollman set_input_fragment(rstrm) 545eae561b3SGarrett Wollman register RECSTREAM *rstrm; 546eae561b3SGarrett Wollman { 5471ad08a09SPeter Wemm u_int32_t header; 548eae561b3SGarrett Wollman 549eae561b3SGarrett Wollman if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) 550eae561b3SGarrett Wollman return (FALSE); 551eae561b3SGarrett Wollman header = (long)ntohl(header); 552eae561b3SGarrett Wollman rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; 553a9352e90SBill Paul /* 554a9352e90SBill Paul * Sanity check. Try not to accept wildly incorrect 5551ce4aec2SBill Paul * record sizes. Unfortunately, the only record size 5561ce4aec2SBill Paul * we can positively identify as being 'wildly incorrect' 5571ce4aec2SBill Paul * is zero. Ridiculously large record sizes may look wrong, 5581ce4aec2SBill Paul * but we don't have any way to be certain that they aren't 5591ce4aec2SBill Paul * what the client actually intended to send us. 560a9352e90SBill Paul */ 5611ce4aec2SBill Paul if ((header & (~LAST_FRAG)) == 0) 562a9352e90SBill Paul return(FALSE); 563eae561b3SGarrett Wollman rstrm->fbtbc = header & (~LAST_FRAG); 564eae561b3SGarrett Wollman return (TRUE); 565eae561b3SGarrett Wollman } 566eae561b3SGarrett Wollman 567eae561b3SGarrett Wollman static bool_t /* consumes input bytes; knows nothing about records! */ 568eae561b3SGarrett Wollman skip_input_bytes(rstrm, cnt) 569eae561b3SGarrett Wollman register RECSTREAM *rstrm; 570eae561b3SGarrett Wollman long cnt; 571eae561b3SGarrett Wollman { 5721ad08a09SPeter Wemm register long current; 573eae561b3SGarrett Wollman 574eae561b3SGarrett Wollman while (cnt > 0) { 5751ad08a09SPeter Wemm current = (long)rstrm->in_boundry - (long)rstrm->in_finger; 576eae561b3SGarrett Wollman if (current == 0) { 577eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 578eae561b3SGarrett Wollman return (FALSE); 579eae561b3SGarrett Wollman continue; 580eae561b3SGarrett Wollman } 581eae561b3SGarrett Wollman current = (cnt < current) ? cnt : current; 582eae561b3SGarrett Wollman rstrm->in_finger += current; 583eae561b3SGarrett Wollman cnt -= current; 584eae561b3SGarrett Wollman } 585eae561b3SGarrett Wollman return (TRUE); 586eae561b3SGarrett Wollman } 587eae561b3SGarrett Wollman 588eae561b3SGarrett Wollman static u_int 589eae561b3SGarrett Wollman fix_buf_size(s) 590eae561b3SGarrett Wollman register u_int s; 591eae561b3SGarrett Wollman { 592eae561b3SGarrett Wollman 593eae561b3SGarrett Wollman if (s < 100) 594eae561b3SGarrett Wollman s = 4000; 595eae561b3SGarrett Wollman return (RNDUP(s)); 596eae561b3SGarrett Wollman } 597