18360efbdSAlfred Perlstein /* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein 3eae561b3SGarrett Wollman /* 4eae561b3SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5eae561b3SGarrett Wollman * unrestricted use provided that this legend is included on all tape 6eae561b3SGarrett Wollman * media and as a part of the software program in whole or part. Users 7eae561b3SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 8eae561b3SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 9eae561b3SGarrett Wollman * program developed by the user. 10eae561b3SGarrett Wollman * 11eae561b3SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12eae561b3SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13eae561b3SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14eae561b3SGarrett Wollman * 15eae561b3SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 16eae561b3SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 17eae561b3SGarrett Wollman * modification or enhancement. 18eae561b3SGarrett Wollman * 19eae561b3SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20eae561b3SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21eae561b3SGarrett Wollman * OR ANY PART THEREOF. 22eae561b3SGarrett Wollman * 23eae561b3SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24eae561b3SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 25eae561b3SGarrett Wollman * Sun has been advised of the possibility of such damages. 26eae561b3SGarrett Wollman * 27eae561b3SGarrett Wollman * Sun Microsystems, Inc. 28eae561b3SGarrett Wollman * 2550 Garcia Avenue 29eae561b3SGarrett Wollman * Mountain View, California 94043 30eae561b3SGarrett Wollman */ 318360efbdSAlfred Perlstein 328360efbdSAlfred Perlstein #include <sys/cdefs.h> 33eae561b3SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 34333fc21eSDavid E. O'Brien static char *sccsid = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 35333fc21eSDavid E. O'Brien static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; 36eae561b3SGarrett Wollman #endif 37333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 38333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 39eae561b3SGarrett Wollman 40eae561b3SGarrett Wollman /* 41eae561b3SGarrett Wollman * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" 42eae561b3SGarrett Wollman * layer above tcp (for rpc's use). 43eae561b3SGarrett Wollman * 44eae561b3SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 45eae561b3SGarrett Wollman * 46eae561b3SGarrett Wollman * These routines interface XDRSTREAMS to a tcp/ip connection. 47eae561b3SGarrett Wollman * There is a record marking layer between the xdr stream 48eae561b3SGarrett Wollman * and the tcp transport level. A record is composed on one or more 49eae561b3SGarrett Wollman * record fragments. A record fragment is a thirty-two bit header followed 50eae561b3SGarrett Wollman * by n bytes of data, where n is contained in the header. The header 51eae561b3SGarrett Wollman * is represented as a htonl(u_long). Thegh order bit encodes 52eae561b3SGarrett Wollman * whether or not the fragment is the last fragment of the record 53eae561b3SGarrett Wollman * (1 => fragment is last, 0 => more fragments to follow. 54eae561b3SGarrett Wollman * The other 31 bits encode the byte length of the fragment. 55eae561b3SGarrett Wollman */ 56eae561b3SGarrett Wollman 578360efbdSAlfred Perlstein #include "namespace.h" 588360efbdSAlfred Perlstein #include <sys/types.h> 598360efbdSAlfred Perlstein 608360efbdSAlfred Perlstein #include <netinet/in.h> 618360efbdSAlfred Perlstein 628360efbdSAlfred Perlstein #include <err.h> 63eae561b3SGarrett Wollman #include <stdio.h> 64eae561b3SGarrett Wollman #include <stdlib.h> 6529285d6cSPoul-Henning Kamp #include <string.h> 668360efbdSAlfred Perlstein 67eae561b3SGarrett Wollman #include <rpc/types.h> 68eae561b3SGarrett Wollman #include <rpc/xdr.h> 6908497c02SMartin Blapp #include <rpc/auth.h> 7008497c02SMartin Blapp #include <rpc/svc.h> 7108497c02SMartin Blapp #include <rpc/clnt.h> 7208497c02SMartin Blapp #include <sys/stddef.h> 738360efbdSAlfred Perlstein #include "un-namespace.h" 742bbd7cf8SJacques Vidrine #include "rpc_com.h" 75eae561b3SGarrett Wollman 76c05ac53bSDavid E. O'Brien static bool_t xdrrec_getlong(XDR *, long *); 77c05ac53bSDavid E. O'Brien static bool_t xdrrec_putlong(XDR *, const long *); 78c05ac53bSDavid E. O'Brien static bool_t xdrrec_getbytes(XDR *, char *, u_int); 79eae561b3SGarrett Wollman 80c05ac53bSDavid E. O'Brien static bool_t xdrrec_putbytes(XDR *, const char *, u_int); 81c05ac53bSDavid E. O'Brien static u_int xdrrec_getpos(XDR *); 82c05ac53bSDavid E. O'Brien static bool_t xdrrec_setpos(XDR *, u_int); 83c05ac53bSDavid E. O'Brien static int32_t *xdrrec_inline(XDR *, u_int); 84c05ac53bSDavid E. O'Brien static void xdrrec_destroy(XDR *); 85eae561b3SGarrett Wollman 868360efbdSAlfred Perlstein static const struct xdr_ops xdrrec_ops = { 87eae561b3SGarrett Wollman xdrrec_getlong, 88eae561b3SGarrett Wollman xdrrec_putlong, 89eae561b3SGarrett Wollman xdrrec_getbytes, 90eae561b3SGarrett Wollman xdrrec_putbytes, 91eae561b3SGarrett Wollman xdrrec_getpos, 92eae561b3SGarrett Wollman xdrrec_setpos, 93eae561b3SGarrett Wollman xdrrec_inline, 94eae561b3SGarrett Wollman xdrrec_destroy 95eae561b3SGarrett Wollman }; 96eae561b3SGarrett Wollman 97eae561b3SGarrett Wollman /* 98eae561b3SGarrett Wollman * A record is composed of one or more record fragments. 9908497c02SMartin Blapp * A record fragment is a four-byte header followed by zero to 100eae561b3SGarrett Wollman * 2**32-1 bytes. The header is treated as a long unsigned and is 101eae561b3SGarrett Wollman * encode/decoded to the network via htonl/ntohl. The low order 31 bits 102eae561b3SGarrett Wollman * are a byte count of the fragment. The highest order bit is a boolean: 103eae561b3SGarrett Wollman * 1 => this fragment is the last fragment of the record, 104eae561b3SGarrett Wollman * 0 => this fragment is followed by more fragment(s). 105eae561b3SGarrett Wollman * 106eae561b3SGarrett Wollman * The fragment/record machinery is not general; it is constructed to 107eae561b3SGarrett Wollman * meet the needs of xdr and rpc based on tcp. 108eae561b3SGarrett Wollman */ 109eae561b3SGarrett Wollman 1101ad08a09SPeter Wemm #define LAST_FRAG ((u_int32_t)(1 << 31)) 111eae561b3SGarrett Wollman 112eae561b3SGarrett Wollman typedef struct rec_strm { 1138360efbdSAlfred Perlstein char *tcp_handle; 114eae561b3SGarrett Wollman /* 115eae561b3SGarrett Wollman * out-goung bits 116eae561b3SGarrett Wollman */ 117f249dbccSDag-Erling Smørgrav int (*writeit)(void *, void *, int); 1188360efbdSAlfred Perlstein char *out_base; /* output buffer (points to frag header) */ 1198360efbdSAlfred Perlstein char *out_finger; /* next output position */ 1208360efbdSAlfred Perlstein char *out_boundry; /* data cannot up to this address */ 1218360efbdSAlfred Perlstein u_int32_t *frag_header; /* beginning of curren fragment */ 122eae561b3SGarrett Wollman bool_t frag_sent; /* true if buffer sent in middle of record */ 123eae561b3SGarrett Wollman /* 124eae561b3SGarrett Wollman * in-coming bits 125eae561b3SGarrett Wollman */ 126f249dbccSDag-Erling Smørgrav int (*readit)(void *, void *, int); 127eae561b3SGarrett Wollman u_long in_size; /* fixed size of the input buffer */ 1288360efbdSAlfred Perlstein char *in_base; 1298360efbdSAlfred Perlstein char *in_finger; /* location of next byte to be had */ 1308360efbdSAlfred Perlstein char *in_boundry; /* can read up to this location */ 131eae561b3SGarrett Wollman long fbtbc; /* fragment bytes to be consumed */ 132eae561b3SGarrett Wollman bool_t last_frag; 133eae561b3SGarrett Wollman u_int sendsize; 134eae561b3SGarrett Wollman u_int recvsize; 13508497c02SMartin Blapp 13608497c02SMartin Blapp bool_t nonblock; 13708497c02SMartin Blapp bool_t in_haveheader; 13808497c02SMartin Blapp u_int32_t in_header; 13908497c02SMartin Blapp char *in_hdrp; 14008497c02SMartin Blapp int in_hdrlen; 14108497c02SMartin Blapp int in_reclen; 14208497c02SMartin Blapp int in_received; 14308497c02SMartin Blapp int in_maxrec; 144eae561b3SGarrett Wollman } RECSTREAM; 145eae561b3SGarrett Wollman 146c05ac53bSDavid E. O'Brien static u_int fix_buf_size(u_int); 147c05ac53bSDavid E. O'Brien static bool_t flush_out(RECSTREAM *, bool_t); 148c05ac53bSDavid E. O'Brien static bool_t fill_input_buf(RECSTREAM *); 149c05ac53bSDavid E. O'Brien static bool_t get_input_bytes(RECSTREAM *, char *, int); 150c05ac53bSDavid E. O'Brien static bool_t set_input_fragment(RECSTREAM *); 151c05ac53bSDavid E. O'Brien static bool_t skip_input_bytes(RECSTREAM *, long); 15208497c02SMartin Blapp static bool_t realloc_stream(RECSTREAM *, int); 1538360efbdSAlfred Perlstein 154eae561b3SGarrett Wollman 155eae561b3SGarrett Wollman /* 156eae561b3SGarrett Wollman * Create an xdr handle for xdrrec 157eae561b3SGarrett Wollman * xdrrec_create fills in xdrs. Sendsize and recvsize are 158eae561b3SGarrett Wollman * send and recv buffer sizes (0 => use default). 159eae561b3SGarrett Wollman * tcp_handle is an opaque handle that is passed as the first parameter to 160eae561b3SGarrett Wollman * the procedures readit and writeit. Readit and writeit are read and 161eae561b3SGarrett Wollman * write respectively. They are like the system 162eae561b3SGarrett Wollman * calls expect that they take an opaque handle rather than an fd. 163eae561b3SGarrett Wollman */ 164eae561b3SGarrett Wollman void 165eae561b3SGarrett Wollman xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) 1668360efbdSAlfred Perlstein XDR *xdrs; 1678360efbdSAlfred Perlstein u_int sendsize; 1688360efbdSAlfred Perlstein u_int recvsize; 169f249dbccSDag-Erling Smørgrav void *tcp_handle; 1708360efbdSAlfred Perlstein /* like read, but pass it a tcp_handle, not sock */ 171f249dbccSDag-Erling Smørgrav int (*readit)(void *, void *, int); 1728360efbdSAlfred Perlstein /* like write, but pass it a tcp_handle, not sock */ 173f249dbccSDag-Erling Smørgrav int (*writeit)(void *, void *, int); 174eae561b3SGarrett Wollman { 1758360efbdSAlfred Perlstein RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); 176eae561b3SGarrett Wollman 177eae561b3SGarrett Wollman if (rstrm == NULL) { 1788360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory"); 179eae561b3SGarrett Wollman /* 180eae561b3SGarrett Wollman * This is bad. Should rework xdrrec_create to 181eae561b3SGarrett Wollman * return a handle, and in this case return NULL 182eae561b3SGarrett Wollman */ 183eae561b3SGarrett Wollman return; 184eae561b3SGarrett Wollman } 185eae561b3SGarrett Wollman rstrm->sendsize = sendsize = fix_buf_size(sendsize); 18608497c02SMartin Blapp rstrm->out_base = mem_alloc(rstrm->sendsize); 18708497c02SMartin Blapp if (rstrm->out_base == NULL) { 1888360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory"); 18908497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM)); 190eae561b3SGarrett Wollman return; 191eae561b3SGarrett Wollman } 19208497c02SMartin Blapp rstrm->recvsize = recvsize = fix_buf_size(recvsize); 19308497c02SMartin Blapp rstrm->in_base = mem_alloc(recvsize); 19408497c02SMartin Blapp if (rstrm->in_base == NULL) { 19508497c02SMartin Blapp warnx("xdrrec_create: out of memory"); 19608497c02SMartin Blapp mem_free(rstrm->out_base, sendsize); 19708497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM)); 19808497c02SMartin Blapp return; 19908497c02SMartin Blapp } 200eae561b3SGarrett Wollman /* 201eae561b3SGarrett Wollman * now the rest ... 202eae561b3SGarrett Wollman */ 203eae561b3SGarrett Wollman xdrs->x_ops = &xdrrec_ops; 2048360efbdSAlfred Perlstein xdrs->x_private = rstrm; 205eae561b3SGarrett Wollman rstrm->tcp_handle = tcp_handle; 206eae561b3SGarrett Wollman rstrm->readit = readit; 207eae561b3SGarrett Wollman rstrm->writeit = writeit; 208eae561b3SGarrett Wollman rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; 2098360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; 2101ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 211eae561b3SGarrett Wollman rstrm->out_boundry += sendsize; 212eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 213eae561b3SGarrett Wollman rstrm->in_size = recvsize; 214eae561b3SGarrett Wollman rstrm->in_boundry = rstrm->in_base; 215eae561b3SGarrett Wollman rstrm->in_finger = (rstrm->in_boundry += recvsize); 216eae561b3SGarrett Wollman rstrm->fbtbc = 0; 217eae561b3SGarrett Wollman rstrm->last_frag = TRUE; 21808497c02SMartin Blapp rstrm->in_haveheader = FALSE; 21908497c02SMartin Blapp rstrm->in_hdrlen = 0; 22008497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; 22108497c02SMartin Blapp rstrm->nonblock = FALSE; 22208497c02SMartin Blapp rstrm->in_reclen = 0; 22308497c02SMartin Blapp rstrm->in_received = 0; 224eae561b3SGarrett Wollman } 225eae561b3SGarrett Wollman 226eae561b3SGarrett Wollman 227eae561b3SGarrett Wollman /* 228eae561b3SGarrett Wollman * The reoutines defined below are the xdr ops which will go into the 229eae561b3SGarrett Wollman * xdr handle filled in by xdrrec_create. 230eae561b3SGarrett Wollman */ 231eae561b3SGarrett Wollman 232eae561b3SGarrett Wollman static bool_t 233eae561b3SGarrett Wollman xdrrec_getlong(xdrs, lp) 234eae561b3SGarrett Wollman XDR *xdrs; 235eae561b3SGarrett Wollman long *lp; 236eae561b3SGarrett Wollman { 2378360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2388360efbdSAlfred Perlstein int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger); 2391ad08a09SPeter Wemm int32_t mylong; 240eae561b3SGarrett Wollman 241eae561b3SGarrett Wollman /* first try the inline, fast case */ 2421ad08a09SPeter Wemm if ((rstrm->fbtbc >= sizeof(int32_t)) && 2431ad08a09SPeter Wemm (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { 2441ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)(*buflp)); 2451ad08a09SPeter Wemm rstrm->fbtbc -= sizeof(int32_t); 2461ad08a09SPeter Wemm rstrm->in_finger += sizeof(int32_t); 247eae561b3SGarrett Wollman } else { 2488360efbdSAlfred Perlstein if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, 2498360efbdSAlfred Perlstein sizeof(int32_t))) 250eae561b3SGarrett Wollman return (FALSE); 2511ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)mylong); 252eae561b3SGarrett Wollman } 253eae561b3SGarrett Wollman return (TRUE); 254eae561b3SGarrett Wollman } 255eae561b3SGarrett Wollman 256eae561b3SGarrett Wollman static bool_t 257eae561b3SGarrett Wollman xdrrec_putlong(xdrs, lp) 258eae561b3SGarrett Wollman XDR *xdrs; 2598360efbdSAlfred Perlstein const long *lp; 260eae561b3SGarrett Wollman { 2618360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2628360efbdSAlfred Perlstein int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); 263eae561b3SGarrett Wollman 2641ad08a09SPeter Wemm if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { 265eae561b3SGarrett Wollman /* 266eae561b3SGarrett Wollman * this case should almost never happen so the code is 267eae561b3SGarrett Wollman * inefficient 268eae561b3SGarrett Wollman */ 2691ad08a09SPeter Wemm rstrm->out_finger -= sizeof(int32_t); 270eae561b3SGarrett Wollman rstrm->frag_sent = TRUE; 271eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE)) 272eae561b3SGarrett Wollman return (FALSE); 2738360efbdSAlfred Perlstein dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); 2741ad08a09SPeter Wemm rstrm->out_finger += sizeof(int32_t); 275eae561b3SGarrett Wollman } 2761ad08a09SPeter Wemm *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); 277eae561b3SGarrett Wollman return (TRUE); 278eae561b3SGarrett Wollman } 279eae561b3SGarrett Wollman 280eae561b3SGarrett Wollman static bool_t /* must manage buffers, fragments, and records */ 281eae561b3SGarrett Wollman xdrrec_getbytes(xdrs, addr, len) 282eae561b3SGarrett Wollman XDR *xdrs; 2838360efbdSAlfred Perlstein char *addr; 2848360efbdSAlfred Perlstein u_int len; 285eae561b3SGarrett Wollman { 2868360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2878360efbdSAlfred Perlstein int current; 288eae561b3SGarrett Wollman 289eae561b3SGarrett Wollman while (len > 0) { 2908360efbdSAlfred Perlstein current = (int)rstrm->fbtbc; 291eae561b3SGarrett Wollman if (current == 0) { 292eae561b3SGarrett Wollman if (rstrm->last_frag) 293eae561b3SGarrett Wollman return (FALSE); 294eae561b3SGarrett Wollman if (! set_input_fragment(rstrm)) 295eae561b3SGarrett Wollman return (FALSE); 296eae561b3SGarrett Wollman continue; 297eae561b3SGarrett Wollman } 298eae561b3SGarrett Wollman current = (len < current) ? len : current; 299eae561b3SGarrett Wollman if (! get_input_bytes(rstrm, addr, current)) 300eae561b3SGarrett Wollman return (FALSE); 301eae561b3SGarrett Wollman addr += current; 302eae561b3SGarrett Wollman rstrm->fbtbc -= current; 303eae561b3SGarrett Wollman len -= current; 304eae561b3SGarrett Wollman } 305eae561b3SGarrett Wollman return (TRUE); 306eae561b3SGarrett Wollman } 307eae561b3SGarrett Wollman 308eae561b3SGarrett Wollman static bool_t 309eae561b3SGarrett Wollman xdrrec_putbytes(xdrs, addr, len) 310eae561b3SGarrett Wollman XDR *xdrs; 3118360efbdSAlfred Perlstein const char *addr; 3128360efbdSAlfred Perlstein u_int len; 313eae561b3SGarrett Wollman { 3148360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 3158360efbdSAlfred Perlstein size_t current; 316eae561b3SGarrett Wollman 317eae561b3SGarrett Wollman while (len > 0) { 3188360efbdSAlfred Perlstein current = (size_t)((u_long)rstrm->out_boundry - 3198360efbdSAlfred Perlstein (u_long)rstrm->out_finger); 320eae561b3SGarrett Wollman current = (len < current) ? len : current; 3218360efbdSAlfred Perlstein memmove(rstrm->out_finger, addr, current); 322eae561b3SGarrett Wollman rstrm->out_finger += current; 323eae561b3SGarrett Wollman addr += current; 324eae561b3SGarrett Wollman len -= current; 325eae561b3SGarrett Wollman if (rstrm->out_finger == rstrm->out_boundry) { 326eae561b3SGarrett Wollman rstrm->frag_sent = TRUE; 327eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE)) 328eae561b3SGarrett Wollman return (FALSE); 329eae561b3SGarrett Wollman } 330eae561b3SGarrett Wollman } 331eae561b3SGarrett Wollman return (TRUE); 332eae561b3SGarrett Wollman } 333eae561b3SGarrett Wollman 334eae561b3SGarrett Wollman static u_int 335eae561b3SGarrett Wollman xdrrec_getpos(xdrs) 3368360efbdSAlfred Perlstein XDR *xdrs; 337eae561b3SGarrett Wollman { 3388360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3398360efbdSAlfred Perlstein off_t pos; 340eae561b3SGarrett Wollman 3418360efbdSAlfred Perlstein pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); 342eae561b3SGarrett Wollman if (pos != -1) 343eae561b3SGarrett Wollman switch (xdrs->x_op) { 344eae561b3SGarrett Wollman 345eae561b3SGarrett Wollman case XDR_ENCODE: 346eae561b3SGarrett Wollman pos += rstrm->out_finger - rstrm->out_base; 347eae561b3SGarrett Wollman break; 348eae561b3SGarrett Wollman 349eae561b3SGarrett Wollman case XDR_DECODE: 350eae561b3SGarrett Wollman pos -= rstrm->in_boundry - rstrm->in_finger; 351eae561b3SGarrett Wollman break; 352eae561b3SGarrett Wollman 353eae561b3SGarrett Wollman default: 3548360efbdSAlfred Perlstein pos = (off_t) -1; 355eae561b3SGarrett Wollman break; 356eae561b3SGarrett Wollman } 357eae561b3SGarrett Wollman return ((u_int) pos); 358eae561b3SGarrett Wollman } 359eae561b3SGarrett Wollman 360eae561b3SGarrett Wollman static bool_t 361eae561b3SGarrett Wollman xdrrec_setpos(xdrs, pos) 3628360efbdSAlfred Perlstein XDR *xdrs; 363eae561b3SGarrett Wollman u_int pos; 364eae561b3SGarrett Wollman { 3658360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 366eae561b3SGarrett Wollman u_int currpos = xdrrec_getpos(xdrs); 367eae561b3SGarrett Wollman int delta = currpos - pos; 3688360efbdSAlfred Perlstein char *newpos; 369eae561b3SGarrett Wollman 370eae561b3SGarrett Wollman if ((int)currpos != -1) 371eae561b3SGarrett Wollman switch (xdrs->x_op) { 372eae561b3SGarrett Wollman 373eae561b3SGarrett Wollman case XDR_ENCODE: 374eae561b3SGarrett Wollman newpos = rstrm->out_finger - delta; 3758360efbdSAlfred Perlstein if ((newpos > (char *)(void *)(rstrm->frag_header)) && 376eae561b3SGarrett Wollman (newpos < rstrm->out_boundry)) { 377eae561b3SGarrett Wollman rstrm->out_finger = newpos; 378eae561b3SGarrett Wollman return (TRUE); 379eae561b3SGarrett Wollman } 380eae561b3SGarrett Wollman break; 381eae561b3SGarrett Wollman 382eae561b3SGarrett Wollman case XDR_DECODE: 383eae561b3SGarrett Wollman newpos = rstrm->in_finger - delta; 384eae561b3SGarrett Wollman if ((delta < (int)(rstrm->fbtbc)) && 385eae561b3SGarrett Wollman (newpos <= rstrm->in_boundry) && 386eae561b3SGarrett Wollman (newpos >= rstrm->in_base)) { 387eae561b3SGarrett Wollman rstrm->in_finger = newpos; 388eae561b3SGarrett Wollman rstrm->fbtbc -= delta; 389eae561b3SGarrett Wollman return (TRUE); 390eae561b3SGarrett Wollman } 391eae561b3SGarrett Wollman break; 3928360efbdSAlfred Perlstein 3938360efbdSAlfred Perlstein case XDR_FREE: 3948360efbdSAlfred Perlstein break; 395eae561b3SGarrett Wollman } 396eae561b3SGarrett Wollman return (FALSE); 397eae561b3SGarrett Wollman } 398eae561b3SGarrett Wollman 3991ad08a09SPeter Wemm static int32_t * 400eae561b3SGarrett Wollman xdrrec_inline(xdrs, len) 4018360efbdSAlfred Perlstein XDR *xdrs; 4028360efbdSAlfred Perlstein u_int len; 403eae561b3SGarrett Wollman { 4048360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 4051ad08a09SPeter Wemm int32_t *buf = NULL; 406eae561b3SGarrett Wollman 407eae561b3SGarrett Wollman switch (xdrs->x_op) { 408eae561b3SGarrett Wollman 409eae561b3SGarrett Wollman case XDR_ENCODE: 410eae561b3SGarrett Wollman if ((rstrm->out_finger + len) <= rstrm->out_boundry) { 4118360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->out_finger; 412eae561b3SGarrett Wollman rstrm->out_finger += len; 413eae561b3SGarrett Wollman } 414eae561b3SGarrett Wollman break; 415eae561b3SGarrett Wollman 416eae561b3SGarrett Wollman case XDR_DECODE: 417eae561b3SGarrett Wollman if ((len <= rstrm->fbtbc) && 418eae561b3SGarrett Wollman ((rstrm->in_finger + len) <= rstrm->in_boundry)) { 4198360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->in_finger; 420eae561b3SGarrett Wollman rstrm->fbtbc -= len; 421eae561b3SGarrett Wollman rstrm->in_finger += len; 422eae561b3SGarrett Wollman } 423eae561b3SGarrett Wollman break; 4248360efbdSAlfred Perlstein 4258360efbdSAlfred Perlstein case XDR_FREE: 4268360efbdSAlfred Perlstein break; 427eae561b3SGarrett Wollman } 428eae561b3SGarrett Wollman return (buf); 429eae561b3SGarrett Wollman } 430eae561b3SGarrett Wollman 431eae561b3SGarrett Wollman static void 432eae561b3SGarrett Wollman xdrrec_destroy(xdrs) 4338360efbdSAlfred Perlstein XDR *xdrs; 434eae561b3SGarrett Wollman { 4358360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 436eae561b3SGarrett Wollman 43708497c02SMartin Blapp mem_free(rstrm->out_base, rstrm->sendsize); 43808497c02SMartin Blapp mem_free(rstrm->in_base, rstrm->recvsize); 4398360efbdSAlfred Perlstein mem_free(rstrm, sizeof(RECSTREAM)); 440eae561b3SGarrett Wollman } 441eae561b3SGarrett Wollman 442eae561b3SGarrett Wollman 443eae561b3SGarrett Wollman /* 444eae561b3SGarrett Wollman * Exported routines to manage xdr records 445eae561b3SGarrett Wollman */ 446eae561b3SGarrett Wollman 447eae561b3SGarrett Wollman /* 448eae561b3SGarrett Wollman * Before reading (deserializing from the stream, one should always call 449eae561b3SGarrett Wollman * this procedure to guarantee proper record alignment. 450eae561b3SGarrett Wollman */ 451eae561b3SGarrett Wollman bool_t 452eae561b3SGarrett Wollman xdrrec_skiprecord(xdrs) 453eae561b3SGarrett Wollman XDR *xdrs; 454eae561b3SGarrett Wollman { 4558360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 45608497c02SMartin Blapp enum xprt_stat xstat; 45708497c02SMartin Blapp 45808497c02SMartin Blapp if (rstrm->nonblock) { 45908497c02SMartin Blapp if (__xdrrec_getrec(xdrs, &xstat, FALSE)) { 46008497c02SMartin Blapp rstrm->fbtbc = 0; 46108497c02SMartin Blapp return TRUE; 46208497c02SMartin Blapp } 46308497c02SMartin Blapp if (rstrm->in_finger == rstrm->in_boundry && 46408497c02SMartin Blapp xstat == XPRT_MOREREQS) { 46508497c02SMartin Blapp rstrm->fbtbc = 0; 46608497c02SMartin Blapp return TRUE; 46708497c02SMartin Blapp } 46808497c02SMartin Blapp return FALSE; 46908497c02SMartin Blapp } 470eae561b3SGarrett Wollman 471eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 472eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 473eae561b3SGarrett Wollman return (FALSE); 474eae561b3SGarrett Wollman rstrm->fbtbc = 0; 475eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 476eae561b3SGarrett Wollman return (FALSE); 477eae561b3SGarrett Wollman } 478eae561b3SGarrett Wollman rstrm->last_frag = FALSE; 479eae561b3SGarrett Wollman return (TRUE); 480eae561b3SGarrett Wollman } 481eae561b3SGarrett Wollman 482eae561b3SGarrett Wollman /* 4838360efbdSAlfred Perlstein * Look ahead function. 484eae561b3SGarrett Wollman * Returns TRUE iff there is no more input in the buffer 485eae561b3SGarrett Wollman * after consuming the rest of the current record. 486eae561b3SGarrett Wollman */ 487eae561b3SGarrett Wollman bool_t 488eae561b3SGarrett Wollman xdrrec_eof(xdrs) 489eae561b3SGarrett Wollman XDR *xdrs; 490eae561b3SGarrett Wollman { 4918360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 49208497c02SMartin Blapp enum xprt_stat xstat; 49308497c02SMartin Blapp 49408497c02SMartin Blapp if (rstrm->nonblock) { 49508497c02SMartin Blapp if (__xdrrec_getrec(xdrs, &xstat, FALSE)) 49608497c02SMartin Blapp return FALSE; 49708497c02SMartin Blapp if (!rstrm->in_haveheader && xstat == XPRT_IDLE) 49808497c02SMartin Blapp return TRUE; 49908497c02SMartin Blapp return FALSE; 50008497c02SMartin Blapp } 501eae561b3SGarrett Wollman 502eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 503eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 504eae561b3SGarrett Wollman return (TRUE); 505eae561b3SGarrett Wollman rstrm->fbtbc = 0; 506eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 507eae561b3SGarrett Wollman return (TRUE); 508eae561b3SGarrett Wollman } 509eae561b3SGarrett Wollman if (rstrm->in_finger == rstrm->in_boundry) 510eae561b3SGarrett Wollman return (TRUE); 511eae561b3SGarrett Wollman return (FALSE); 512eae561b3SGarrett Wollman } 513eae561b3SGarrett Wollman 514eae561b3SGarrett Wollman /* 515eae561b3SGarrett Wollman * The client must tell the package when an end-of-record has occurred. 516eae561b3SGarrett Wollman * The second paraemters tells whether the record should be flushed to the 517eae561b3SGarrett Wollman * (output) tcp stream. (This let's the package support batched or 518eae561b3SGarrett Wollman * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. 519eae561b3SGarrett Wollman */ 520eae561b3SGarrett Wollman bool_t 521eae561b3SGarrett Wollman xdrrec_endofrecord(xdrs, sendnow) 522eae561b3SGarrett Wollman XDR *xdrs; 523eae561b3SGarrett Wollman bool_t sendnow; 524eae561b3SGarrett Wollman { 5258360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 5268360efbdSAlfred Perlstein u_long len; /* fragment length */ 527eae561b3SGarrett Wollman 528eae561b3SGarrett Wollman if (sendnow || rstrm->frag_sent || 5291ad08a09SPeter Wemm ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= 530eae561b3SGarrett Wollman (u_long)rstrm->out_boundry)) { 531eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 532eae561b3SGarrett Wollman return (flush_out(rstrm, TRUE)); 533eae561b3SGarrett Wollman } 534eae561b3SGarrett Wollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - 5351ad08a09SPeter Wemm sizeof(u_int32_t); 5368360efbdSAlfred Perlstein *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG); 5378360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger; 5381ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 539eae561b3SGarrett Wollman return (TRUE); 540eae561b3SGarrett Wollman } 541eae561b3SGarrett Wollman 54208497c02SMartin Blapp /* 54308497c02SMartin Blapp * Fill the stream buffer with a record for a non-blocking connection. 54408497c02SMartin Blapp * Return true if a record is available in the buffer, false if not. 54508497c02SMartin Blapp */ 54608497c02SMartin Blapp bool_t 54708497c02SMartin Blapp __xdrrec_getrec(xdrs, statp, expectdata) 54808497c02SMartin Blapp XDR *xdrs; 54908497c02SMartin Blapp enum xprt_stat *statp; 55008497c02SMartin Blapp bool_t expectdata; 55108497c02SMartin Blapp { 55208497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 55308497c02SMartin Blapp ssize_t n; 55408497c02SMartin Blapp int fraglen; 55508497c02SMartin Blapp 55608497c02SMartin Blapp if (!rstrm->in_haveheader) { 55708497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp, 55808497c02SMartin Blapp (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen); 55908497c02SMartin Blapp if (n == 0) { 56008497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE; 56108497c02SMartin Blapp return FALSE; 56208497c02SMartin Blapp } 56308497c02SMartin Blapp if (n < 0) { 56408497c02SMartin Blapp *statp = XPRT_DIED; 56508497c02SMartin Blapp return FALSE; 56608497c02SMartin Blapp } 56708497c02SMartin Blapp rstrm->in_hdrp += n; 56808497c02SMartin Blapp rstrm->in_hdrlen += n; 56908497c02SMartin Blapp if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) { 57008497c02SMartin Blapp *statp = XPRT_MOREREQS; 57108497c02SMartin Blapp return FALSE; 57208497c02SMartin Blapp } 57308497c02SMartin Blapp rstrm->in_header = ntohl(rstrm->in_header); 57408497c02SMartin Blapp fraglen = (int)(rstrm->in_header & ~LAST_FRAG); 57508497c02SMartin Blapp if (fraglen == 0 || fraglen > rstrm->in_maxrec || 57608497c02SMartin Blapp (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) { 57708497c02SMartin Blapp *statp = XPRT_DIED; 57808497c02SMartin Blapp return FALSE; 57908497c02SMartin Blapp } 58008497c02SMartin Blapp rstrm->in_reclen += fraglen; 58108497c02SMartin Blapp if (rstrm->in_reclen > rstrm->recvsize) 58208497c02SMartin Blapp realloc_stream(rstrm, rstrm->in_reclen); 58308497c02SMartin Blapp if (rstrm->in_header & LAST_FRAG) { 58408497c02SMartin Blapp rstrm->in_header &= ~LAST_FRAG; 58508497c02SMartin Blapp rstrm->last_frag = TRUE; 58608497c02SMartin Blapp } 58708497c02SMartin Blapp } 58808497c02SMartin Blapp 58908497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle, 59008497c02SMartin Blapp rstrm->in_base + rstrm->in_received, 59108497c02SMartin Blapp (rstrm->in_reclen - rstrm->in_received)); 59208497c02SMartin Blapp 59308497c02SMartin Blapp if (n < 0) { 59408497c02SMartin Blapp *statp = XPRT_DIED; 59508497c02SMartin Blapp return FALSE; 59608497c02SMartin Blapp } 59708497c02SMartin Blapp 59808497c02SMartin Blapp if (n == 0) { 59908497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE; 60008497c02SMartin Blapp return FALSE; 60108497c02SMartin Blapp } 60208497c02SMartin Blapp 60308497c02SMartin Blapp rstrm->in_received += n; 60408497c02SMartin Blapp 60508497c02SMartin Blapp if (rstrm->in_received == rstrm->in_reclen) { 60608497c02SMartin Blapp rstrm->in_haveheader = FALSE; 60708497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; 60808497c02SMartin Blapp rstrm->in_hdrlen = 0; 60908497c02SMartin Blapp if (rstrm->last_frag) { 61008497c02SMartin Blapp rstrm->fbtbc = rstrm->in_reclen; 61108497c02SMartin Blapp rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen; 61208497c02SMartin Blapp rstrm->in_finger = rstrm->in_base; 61340525d3dSMartin Blapp rstrm->in_reclen = rstrm->in_received = 0; 61408497c02SMartin Blapp *statp = XPRT_MOREREQS; 61508497c02SMartin Blapp return TRUE; 61608497c02SMartin Blapp } 61708497c02SMartin Blapp } 61808497c02SMartin Blapp 61908497c02SMartin Blapp *statp = XPRT_MOREREQS; 62008497c02SMartin Blapp return FALSE; 62108497c02SMartin Blapp } 62208497c02SMartin Blapp 62308497c02SMartin Blapp bool_t 62408497c02SMartin Blapp __xdrrec_setnonblock(xdrs, maxrec) 62508497c02SMartin Blapp XDR *xdrs; 62608497c02SMartin Blapp int maxrec; 62708497c02SMartin Blapp { 62808497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 62908497c02SMartin Blapp 63008497c02SMartin Blapp rstrm->nonblock = TRUE; 63108497c02SMartin Blapp if (maxrec == 0) 63208497c02SMartin Blapp maxrec = rstrm->recvsize; 63308497c02SMartin Blapp rstrm->in_maxrec = maxrec; 63408497c02SMartin Blapp return TRUE; 63508497c02SMartin Blapp } 636eae561b3SGarrett Wollman 637eae561b3SGarrett Wollman /* 638eae561b3SGarrett Wollman * Internal useful routines 639eae561b3SGarrett Wollman */ 640eae561b3SGarrett Wollman static bool_t 641eae561b3SGarrett Wollman flush_out(rstrm, eor) 6428360efbdSAlfred Perlstein RECSTREAM *rstrm; 643eae561b3SGarrett Wollman bool_t eor; 644eae561b3SGarrett Wollman { 6458360efbdSAlfred Perlstein u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0; 6468360efbdSAlfred Perlstein u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) - 6478360efbdSAlfred Perlstein (u_long)(rstrm->frag_header) - sizeof(u_int32_t)); 648eae561b3SGarrett Wollman 649eae561b3SGarrett Wollman *(rstrm->frag_header) = htonl(len | eormask); 6508360efbdSAlfred Perlstein len = (u_int32_t)((u_long)(rstrm->out_finger) - 6518360efbdSAlfred Perlstein (u_long)(rstrm->out_base)); 652eae561b3SGarrett Wollman if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) 653eae561b3SGarrett Wollman != (int)len) 654eae561b3SGarrett Wollman return (FALSE); 6558360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; 6568360efbdSAlfred Perlstein rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t); 657eae561b3SGarrett Wollman return (TRUE); 658eae561b3SGarrett Wollman } 659eae561b3SGarrett Wollman 660eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 661eae561b3SGarrett Wollman fill_input_buf(rstrm) 6628360efbdSAlfred Perlstein RECSTREAM *rstrm; 663eae561b3SGarrett Wollman { 6648360efbdSAlfred Perlstein char *where; 6658360efbdSAlfred Perlstein u_int32_t i; 6668360efbdSAlfred Perlstein int len; 667eae561b3SGarrett Wollman 66808497c02SMartin Blapp if (rstrm->nonblock) 66908497c02SMartin Blapp return FALSE; 67008497c02SMartin Blapp 671eae561b3SGarrett Wollman where = rstrm->in_base; 6728360efbdSAlfred Perlstein i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT); 673eae561b3SGarrett Wollman where += i; 6748360efbdSAlfred Perlstein len = (u_int32_t)(rstrm->in_size - i); 675eae561b3SGarrett Wollman if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) 676eae561b3SGarrett Wollman return (FALSE); 677eae561b3SGarrett Wollman rstrm->in_finger = where; 678eae561b3SGarrett Wollman where += len; 679eae561b3SGarrett Wollman rstrm->in_boundry = where; 680eae561b3SGarrett Wollman return (TRUE); 681eae561b3SGarrett Wollman } 682eae561b3SGarrett Wollman 683eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 684eae561b3SGarrett Wollman get_input_bytes(rstrm, addr, len) 6858360efbdSAlfred Perlstein RECSTREAM *rstrm; 6868360efbdSAlfred Perlstein char *addr; 6878360efbdSAlfred Perlstein int len; 688eae561b3SGarrett Wollman { 6898360efbdSAlfred Perlstein size_t current; 690eae561b3SGarrett Wollman 69140525d3dSMartin Blapp if (rstrm->nonblock) { 69240525d3dSMartin Blapp if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) 69340525d3dSMartin Blapp return FALSE; 69440525d3dSMartin Blapp memcpy(addr, rstrm->in_finger, (size_t)len); 69540525d3dSMartin Blapp rstrm->in_finger += len; 69640525d3dSMartin Blapp return TRUE; 69740525d3dSMartin Blapp } 69840525d3dSMartin Blapp 699eae561b3SGarrett Wollman while (len > 0) { 7008360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry - 7018360efbdSAlfred Perlstein (long)rstrm->in_finger); 702eae561b3SGarrett Wollman if (current == 0) { 703eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 704eae561b3SGarrett Wollman return (FALSE); 705eae561b3SGarrett Wollman continue; 706eae561b3SGarrett Wollman } 707eae561b3SGarrett Wollman current = (len < current) ? len : current; 7088360efbdSAlfred Perlstein memmove(addr, rstrm->in_finger, current); 709eae561b3SGarrett Wollman rstrm->in_finger += current; 710eae561b3SGarrett Wollman addr += current; 711eae561b3SGarrett Wollman len -= current; 712eae561b3SGarrett Wollman } 713eae561b3SGarrett Wollman return (TRUE); 714eae561b3SGarrett Wollman } 715eae561b3SGarrett Wollman 716eae561b3SGarrett Wollman static bool_t /* next two bytes of the input stream are treated as a header */ 717eae561b3SGarrett Wollman set_input_fragment(rstrm) 7188360efbdSAlfred Perlstein RECSTREAM *rstrm; 719eae561b3SGarrett Wollman { 7201ad08a09SPeter Wemm u_int32_t header; 721eae561b3SGarrett Wollman 7228360efbdSAlfred Perlstein if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header))) 723eae561b3SGarrett Wollman return (FALSE); 7248360efbdSAlfred Perlstein header = ntohl(header); 725eae561b3SGarrett Wollman rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; 726a9352e90SBill Paul /* 727a9352e90SBill Paul * Sanity check. Try not to accept wildly incorrect 7281ce4aec2SBill Paul * record sizes. Unfortunately, the only record size 7291ce4aec2SBill Paul * we can positively identify as being 'wildly incorrect' 7301ce4aec2SBill Paul * is zero. Ridiculously large record sizes may look wrong, 7311ce4aec2SBill Paul * but we don't have any way to be certain that they aren't 7321ce4aec2SBill Paul * what the client actually intended to send us. 733a9352e90SBill Paul */ 734c50a9e8fSBill Paul if (header == 0) 735a9352e90SBill Paul return(FALSE); 736eae561b3SGarrett Wollman rstrm->fbtbc = header & (~LAST_FRAG); 737eae561b3SGarrett Wollman return (TRUE); 738eae561b3SGarrett Wollman } 739eae561b3SGarrett Wollman 740eae561b3SGarrett Wollman static bool_t /* consumes input bytes; knows nothing about records! */ 741eae561b3SGarrett Wollman skip_input_bytes(rstrm, cnt) 7428360efbdSAlfred Perlstein RECSTREAM *rstrm; 743eae561b3SGarrett Wollman long cnt; 744eae561b3SGarrett Wollman { 7458360efbdSAlfred Perlstein u_int32_t current; 746eae561b3SGarrett Wollman 747eae561b3SGarrett Wollman while (cnt > 0) { 7488360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry - 7498360efbdSAlfred Perlstein (long)rstrm->in_finger); 750eae561b3SGarrett Wollman if (current == 0) { 751eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 752eae561b3SGarrett Wollman return (FALSE); 753eae561b3SGarrett Wollman continue; 754eae561b3SGarrett Wollman } 7558360efbdSAlfred Perlstein current = (u_int32_t)((cnt < current) ? cnt : current); 756eae561b3SGarrett Wollman rstrm->in_finger += current; 757eae561b3SGarrett Wollman cnt -= current; 758eae561b3SGarrett Wollman } 759eae561b3SGarrett Wollman return (TRUE); 760eae561b3SGarrett Wollman } 761eae561b3SGarrett Wollman 762eae561b3SGarrett Wollman static u_int 763eae561b3SGarrett Wollman fix_buf_size(s) 7648360efbdSAlfred Perlstein u_int s; 765eae561b3SGarrett Wollman { 766eae561b3SGarrett Wollman 767eae561b3SGarrett Wollman if (s < 100) 768eae561b3SGarrett Wollman s = 4000; 769eae561b3SGarrett Wollman return (RNDUP(s)); 770eae561b3SGarrett Wollman } 77108497c02SMartin Blapp 77208497c02SMartin Blapp /* 77308497c02SMartin Blapp * Reallocate the input buffer for a non-block stream. 77408497c02SMartin Blapp */ 77508497c02SMartin Blapp static bool_t 77608497c02SMartin Blapp realloc_stream(rstrm, size) 77708497c02SMartin Blapp RECSTREAM *rstrm; 77808497c02SMartin Blapp int size; 77908497c02SMartin Blapp { 78008497c02SMartin Blapp ptrdiff_t diff; 78108497c02SMartin Blapp char *buf; 78208497c02SMartin Blapp 78308497c02SMartin Blapp if (size > rstrm->recvsize) { 78408497c02SMartin Blapp buf = realloc(rstrm->in_base, (size_t)size); 78508497c02SMartin Blapp if (buf == NULL) 78608497c02SMartin Blapp return FALSE; 78708497c02SMartin Blapp diff = buf - rstrm->in_base; 78808497c02SMartin Blapp rstrm->in_finger += diff; 78908497c02SMartin Blapp rstrm->in_base = buf; 79008497c02SMartin Blapp rstrm->in_boundry = buf + size; 79108497c02SMartin Blapp rstrm->recvsize = size; 79208497c02SMartin Blapp rstrm->in_size = size; 79308497c02SMartin Blapp } 79408497c02SMartin Blapp 79508497c02SMartin Blapp return TRUE; 79608497c02SMartin Blapp } 797