18360efbdSAlfred Perlstein /* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */ 28360efbdSAlfred Perlstein 3a204967aSHiroki Sato /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro F. Giffuni * 6a204967aSHiroki Sato * Copyright (c) 2010, Oracle America, Inc. 7eae561b3SGarrett Wollman * 8a204967aSHiroki Sato * Redistribution and use in source and binary forms, with or without 9a204967aSHiroki Sato * modification, are permitted provided that the following conditions are 10a204967aSHiroki Sato * met: 11eae561b3SGarrett Wollman * 12a204967aSHiroki Sato * * Redistributions of source code must retain the above copyright 13a204967aSHiroki Sato * notice, this list of conditions and the following disclaimer. 14a204967aSHiroki Sato * * Redistributions in binary form must reproduce the above 15a204967aSHiroki Sato * copyright notice, this list of conditions and the following 16a204967aSHiroki Sato * disclaimer in the documentation and/or other materials 17a204967aSHiroki Sato * provided with the distribution. 18a204967aSHiroki Sato * * Neither the name of the "Oracle America, Inc." nor the names of its 19a204967aSHiroki Sato * contributors may be used to endorse or promote products derived 20a204967aSHiroki Sato * from this software without specific prior written permission. 21eae561b3SGarrett Wollman * 22a204967aSHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23a204967aSHiroki Sato * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24a204967aSHiroki Sato * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25a204967aSHiroki Sato * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26a204967aSHiroki Sato * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27a204967aSHiroki Sato * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28a204967aSHiroki Sato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 29a204967aSHiroki Sato * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30a204967aSHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31a204967aSHiroki Sato * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32a204967aSHiroki Sato * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33a204967aSHiroki Sato * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34eae561b3SGarrett Wollman */ 358360efbdSAlfred Perlstein 36eae561b3SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 37a9bdcd37SDavid E. O'Brien static char *sccsid2 = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 38333fc21eSDavid E. O'Brien static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; 39eae561b3SGarrett Wollman #endif 40333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 41333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 42eae561b3SGarrett Wollman 43eae561b3SGarrett Wollman /* 44eae561b3SGarrett Wollman * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" 45eae561b3SGarrett Wollman * layer above tcp (for rpc's use). 46eae561b3SGarrett Wollman * 47eae561b3SGarrett Wollman * These routines interface XDRSTREAMS to a tcp/ip connection. 48eae561b3SGarrett Wollman * There is a record marking layer between the xdr stream 49eae561b3SGarrett Wollman * and the tcp transport level. A record is composed on one or more 50eae561b3SGarrett Wollman * record fragments. A record fragment is a thirty-two bit header followed 51eae561b3SGarrett Wollman * by n bytes of data, where n is contained in the header. The header 52eae561b3SGarrett Wollman * is represented as a htonl(u_long). Thegh order bit encodes 53eae561b3SGarrett Wollman * whether or not the fragment is the last fragment of the record 54eae561b3SGarrett Wollman * (1 => fragment is last, 0 => more fragments to follow. 55eae561b3SGarrett Wollman * The other 31 bits encode the byte length of the fragment. 56eae561b3SGarrett Wollman */ 57eae561b3SGarrett Wollman 588360efbdSAlfred Perlstein #include "namespace.h" 598360efbdSAlfred Perlstein #include <sys/types.h> 608360efbdSAlfred Perlstein 618360efbdSAlfred Perlstein #include <netinet/in.h> 628360efbdSAlfred Perlstein 638360efbdSAlfred Perlstein #include <err.h> 64eae561b3SGarrett Wollman #include <stdio.h> 65eae561b3SGarrett Wollman #include <stdlib.h> 6629285d6cSPoul-Henning Kamp #include <string.h> 678360efbdSAlfred Perlstein 68eae561b3SGarrett Wollman #include <rpc/types.h> 69eae561b3SGarrett Wollman #include <rpc/xdr.h> 7008497c02SMartin Blapp #include <rpc/auth.h> 7108497c02SMartin Blapp #include <rpc/svc.h> 7208497c02SMartin Blapp #include <rpc/clnt.h> 7308497c02SMartin Blapp #include <sys/stddef.h> 748360efbdSAlfred Perlstein #include "un-namespace.h" 752bbd7cf8SJacques Vidrine #include "rpc_com.h" 76eae561b3SGarrett Wollman 77c05ac53bSDavid E. O'Brien static bool_t xdrrec_getlong(XDR *, long *); 78c05ac53bSDavid E. O'Brien static bool_t xdrrec_putlong(XDR *, const long *); 79c05ac53bSDavid E. O'Brien static bool_t xdrrec_getbytes(XDR *, char *, u_int); 80eae561b3SGarrett Wollman 81c05ac53bSDavid E. O'Brien static bool_t xdrrec_putbytes(XDR *, const char *, u_int); 82c05ac53bSDavid E. O'Brien static u_int xdrrec_getpos(XDR *); 83c05ac53bSDavid E. O'Brien static bool_t xdrrec_setpos(XDR *, u_int); 84c05ac53bSDavid E. O'Brien static int32_t *xdrrec_inline(XDR *, u_int); 85c05ac53bSDavid E. O'Brien static void xdrrec_destroy(XDR *); 86eae561b3SGarrett Wollman 878360efbdSAlfred Perlstein static const struct xdr_ops xdrrec_ops = { 88eae561b3SGarrett Wollman xdrrec_getlong, 89eae561b3SGarrett Wollman xdrrec_putlong, 90eae561b3SGarrett Wollman xdrrec_getbytes, 91eae561b3SGarrett Wollman xdrrec_putbytes, 92eae561b3SGarrett Wollman xdrrec_getpos, 93eae561b3SGarrett Wollman xdrrec_setpos, 94eae561b3SGarrett Wollman xdrrec_inline, 95eae561b3SGarrett Wollman xdrrec_destroy 96eae561b3SGarrett Wollman }; 97eae561b3SGarrett Wollman 98eae561b3SGarrett Wollman /* 99eae561b3SGarrett Wollman * A record is composed of one or more record fragments. 10008497c02SMartin Blapp * A record fragment is a four-byte header followed by zero to 101eae561b3SGarrett Wollman * 2**32-1 bytes. The header is treated as a long unsigned and is 102eae561b3SGarrett Wollman * encode/decoded to the network via htonl/ntohl. The low order 31 bits 103eae561b3SGarrett Wollman * are a byte count of the fragment. The highest order bit is a boolean: 104eae561b3SGarrett Wollman * 1 => this fragment is the last fragment of the record, 105eae561b3SGarrett Wollman * 0 => this fragment is followed by more fragment(s). 106eae561b3SGarrett Wollman * 107eae561b3SGarrett Wollman * The fragment/record machinery is not general; it is constructed to 108eae561b3SGarrett Wollman * meet the needs of xdr and rpc based on tcp. 109eae561b3SGarrett Wollman */ 110eae561b3SGarrett Wollman 1117a22215cSEitan Adler #define LAST_FRAG ((u_int32_t)(1U << 31)) 112eae561b3SGarrett Wollman 113eae561b3SGarrett Wollman typedef struct rec_strm { 1148360efbdSAlfred Perlstein char *tcp_handle; 115eae561b3SGarrett Wollman /* 116eae561b3SGarrett Wollman * out-goung bits 117eae561b3SGarrett Wollman */ 118f249dbccSDag-Erling Smørgrav int (*writeit)(void *, void *, int); 1198360efbdSAlfred Perlstein char *out_base; /* output buffer (points to frag header) */ 1208360efbdSAlfred Perlstein char *out_finger; /* next output position */ 1218360efbdSAlfred Perlstein char *out_boundry; /* data cannot up to this address */ 122*85604f70SGordon Bergling u_int32_t *frag_header; /* beginning of current fragment */ 123eae561b3SGarrett Wollman bool_t frag_sent; /* true if buffer sent in middle of record */ 124eae561b3SGarrett Wollman /* 125eae561b3SGarrett Wollman * in-coming bits 126eae561b3SGarrett Wollman */ 127f249dbccSDag-Erling Smørgrav int (*readit)(void *, void *, int); 128eae561b3SGarrett Wollman u_long in_size; /* fixed size of the input buffer */ 1298360efbdSAlfred Perlstein char *in_base; 1308360efbdSAlfred Perlstein char *in_finger; /* location of next byte to be had */ 1318360efbdSAlfred Perlstein char *in_boundry; /* can read up to this location */ 132eae561b3SGarrett Wollman long fbtbc; /* fragment bytes to be consumed */ 133eae561b3SGarrett Wollman bool_t last_frag; 134eae561b3SGarrett Wollman u_int sendsize; 135eae561b3SGarrett Wollman u_int recvsize; 13608497c02SMartin Blapp 13708497c02SMartin Blapp bool_t nonblock; 13808497c02SMartin Blapp bool_t in_haveheader; 13908497c02SMartin Blapp u_int32_t in_header; 14008497c02SMartin Blapp char *in_hdrp; 14108497c02SMartin Blapp int in_hdrlen; 14208497c02SMartin Blapp int in_reclen; 14308497c02SMartin Blapp int in_received; 14408497c02SMartin Blapp int in_maxrec; 145eae561b3SGarrett Wollman } RECSTREAM; 146eae561b3SGarrett Wollman 147c05ac53bSDavid E. O'Brien static u_int fix_buf_size(u_int); 148c05ac53bSDavid E. O'Brien static bool_t flush_out(RECSTREAM *, bool_t); 149c05ac53bSDavid E. O'Brien static bool_t fill_input_buf(RECSTREAM *); 150c05ac53bSDavid E. O'Brien static bool_t get_input_bytes(RECSTREAM *, char *, int); 151c05ac53bSDavid E. O'Brien static bool_t set_input_fragment(RECSTREAM *); 152c05ac53bSDavid E. O'Brien static bool_t skip_input_bytes(RECSTREAM *, long); 15308497c02SMartin Blapp static bool_t realloc_stream(RECSTREAM *, int); 1548360efbdSAlfred Perlstein 155eae561b3SGarrett Wollman 156eae561b3SGarrett Wollman /* 157eae561b3SGarrett Wollman * Create an xdr handle for xdrrec 158eae561b3SGarrett Wollman * xdrrec_create fills in xdrs. Sendsize and recvsize are 159eae561b3SGarrett Wollman * send and recv buffer sizes (0 => use default). 160eae561b3SGarrett Wollman * tcp_handle is an opaque handle that is passed as the first parameter to 161eae561b3SGarrett Wollman * the procedures readit and writeit. Readit and writeit are read and 162eae561b3SGarrett Wollman * write respectively. They are like the system 163eae561b3SGarrett Wollman * calls expect that they take an opaque handle rather than an fd. 164eae561b3SGarrett Wollman */ 165eae561b3SGarrett Wollman void 166d660d38dSCraig Rodrigues xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, void *tcp_handle, 167d660d38dSCraig Rodrigues int (*readit)(void *, void *, int), int (*writeit)(void *, void *, int)) 168d660d38dSCraig Rodrigues /* 169d660d38dSCraig Rodrigues * XDR *xdrs; 170d660d38dSCraig Rodrigues * u_int sendsize; 171d660d38dSCraig Rodrigues * u_int recvsize; 172d660d38dSCraig Rodrigues * void *tcp_handle; 173d660d38dSCraig Rodrigues * // like read, but pass it a tcp_handle, not sock 174d660d38dSCraig Rodrigues * int (*readit)(void *, void *, int); 175d660d38dSCraig Rodrigues * // like write, but pass it a tcp_handle, not sock 176d660d38dSCraig Rodrigues * int (*writeit)(void *, void *, int); 177d660d38dSCraig Rodrigues */ 178eae561b3SGarrett Wollman { 1798360efbdSAlfred Perlstein RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); 180eae561b3SGarrett Wollman 181eae561b3SGarrett Wollman if (rstrm == NULL) { 1828360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory"); 183eae561b3SGarrett Wollman /* 184eae561b3SGarrett Wollman * This is bad. Should rework xdrrec_create to 185eae561b3SGarrett Wollman * return a handle, and in this case return NULL 186eae561b3SGarrett Wollman */ 187eae561b3SGarrett Wollman return; 188eae561b3SGarrett Wollman } 189eae561b3SGarrett Wollman rstrm->sendsize = sendsize = fix_buf_size(sendsize); 19008497c02SMartin Blapp rstrm->out_base = mem_alloc(rstrm->sendsize); 19108497c02SMartin Blapp if (rstrm->out_base == NULL) { 1928360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory"); 19308497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM)); 194eae561b3SGarrett Wollman return; 195eae561b3SGarrett Wollman } 19608497c02SMartin Blapp rstrm->recvsize = recvsize = fix_buf_size(recvsize); 19708497c02SMartin Blapp rstrm->in_base = mem_alloc(recvsize); 19808497c02SMartin Blapp if (rstrm->in_base == NULL) { 19908497c02SMartin Blapp warnx("xdrrec_create: out of memory"); 20008497c02SMartin Blapp mem_free(rstrm->out_base, sendsize); 20108497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM)); 20208497c02SMartin Blapp return; 20308497c02SMartin Blapp } 204eae561b3SGarrett Wollman /* 205eae561b3SGarrett Wollman * now the rest ... 206eae561b3SGarrett Wollman */ 207eae561b3SGarrett Wollman xdrs->x_ops = &xdrrec_ops; 2088360efbdSAlfred Perlstein xdrs->x_private = rstrm; 209eae561b3SGarrett Wollman rstrm->tcp_handle = tcp_handle; 210eae561b3SGarrett Wollman rstrm->readit = readit; 211eae561b3SGarrett Wollman rstrm->writeit = writeit; 212eae561b3SGarrett Wollman rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; 2138360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; 2141ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 215eae561b3SGarrett Wollman rstrm->out_boundry += sendsize; 216eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 217eae561b3SGarrett Wollman rstrm->in_size = recvsize; 218eae561b3SGarrett Wollman rstrm->in_boundry = rstrm->in_base; 219eae561b3SGarrett Wollman rstrm->in_finger = (rstrm->in_boundry += recvsize); 220eae561b3SGarrett Wollman rstrm->fbtbc = 0; 221eae561b3SGarrett Wollman rstrm->last_frag = TRUE; 22208497c02SMartin Blapp rstrm->in_haveheader = FALSE; 22308497c02SMartin Blapp rstrm->in_hdrlen = 0; 22408497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; 22508497c02SMartin Blapp rstrm->nonblock = FALSE; 22608497c02SMartin Blapp rstrm->in_reclen = 0; 22708497c02SMartin Blapp rstrm->in_received = 0; 228eae561b3SGarrett Wollman } 229eae561b3SGarrett Wollman 230eae561b3SGarrett Wollman 231eae561b3SGarrett Wollman /* 232eae561b3SGarrett Wollman * The reoutines defined below are the xdr ops which will go into the 233eae561b3SGarrett Wollman * xdr handle filled in by xdrrec_create. 234eae561b3SGarrett Wollman */ 235eae561b3SGarrett Wollman 236eae561b3SGarrett Wollman static bool_t 237d660d38dSCraig Rodrigues xdrrec_getlong(XDR *xdrs, long *lp) 238eae561b3SGarrett Wollman { 2398360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2408360efbdSAlfred Perlstein int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger); 2411ad08a09SPeter Wemm int32_t mylong; 242eae561b3SGarrett Wollman 243eae561b3SGarrett Wollman /* first try the inline, fast case */ 2441ad08a09SPeter Wemm if ((rstrm->fbtbc >= sizeof(int32_t)) && 2451ad08a09SPeter Wemm (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { 2461ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)(*buflp)); 2471ad08a09SPeter Wemm rstrm->fbtbc -= sizeof(int32_t); 2481ad08a09SPeter Wemm rstrm->in_finger += sizeof(int32_t); 249eae561b3SGarrett Wollman } else { 2508360efbdSAlfred Perlstein if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, 2518360efbdSAlfred Perlstein sizeof(int32_t))) 252eae561b3SGarrett Wollman return (FALSE); 2531ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)mylong); 254eae561b3SGarrett Wollman } 255eae561b3SGarrett Wollman return (TRUE); 256eae561b3SGarrett Wollman } 257eae561b3SGarrett Wollman 258eae561b3SGarrett Wollman static bool_t 259d660d38dSCraig Rodrigues xdrrec_putlong(XDR *xdrs, 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 */ 281d660d38dSCraig Rodrigues xdrrec_getbytes(XDR *xdrs, char *addr, u_int len) 282eae561b3SGarrett Wollman { 2838360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2848360efbdSAlfred Perlstein int current; 285eae561b3SGarrett Wollman 286eae561b3SGarrett Wollman while (len > 0) { 2878360efbdSAlfred Perlstein current = (int)rstrm->fbtbc; 288eae561b3SGarrett Wollman if (current == 0) { 289eae561b3SGarrett Wollman if (rstrm->last_frag) 290eae561b3SGarrett Wollman return (FALSE); 291eae561b3SGarrett Wollman if (! set_input_fragment(rstrm)) 292eae561b3SGarrett Wollman return (FALSE); 293eae561b3SGarrett Wollman continue; 294eae561b3SGarrett Wollman } 295eae561b3SGarrett Wollman current = (len < current) ? len : current; 296eae561b3SGarrett Wollman if (! get_input_bytes(rstrm, addr, current)) 297eae561b3SGarrett Wollman return (FALSE); 298eae561b3SGarrett Wollman addr += current; 299eae561b3SGarrett Wollman rstrm->fbtbc -= current; 300eae561b3SGarrett Wollman len -= current; 301eae561b3SGarrett Wollman } 302eae561b3SGarrett Wollman return (TRUE); 303eae561b3SGarrett Wollman } 304eae561b3SGarrett Wollman 305eae561b3SGarrett Wollman static bool_t 306d660d38dSCraig Rodrigues xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len) 307eae561b3SGarrett Wollman { 3088360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 3098360efbdSAlfred Perlstein size_t current; 310eae561b3SGarrett Wollman 311eae561b3SGarrett Wollman while (len > 0) { 3128360efbdSAlfred Perlstein current = (size_t)((u_long)rstrm->out_boundry - 3138360efbdSAlfred Perlstein (u_long)rstrm->out_finger); 314eae561b3SGarrett Wollman current = (len < current) ? len : current; 3158360efbdSAlfred Perlstein memmove(rstrm->out_finger, addr, current); 316eae561b3SGarrett Wollman rstrm->out_finger += current; 317eae561b3SGarrett Wollman addr += current; 318eae561b3SGarrett Wollman len -= current; 319eae561b3SGarrett Wollman if (rstrm->out_finger == rstrm->out_boundry) { 320eae561b3SGarrett Wollman rstrm->frag_sent = TRUE; 321eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE)) 322eae561b3SGarrett Wollman return (FALSE); 323eae561b3SGarrett Wollman } 324eae561b3SGarrett Wollman } 325eae561b3SGarrett Wollman return (TRUE); 326eae561b3SGarrett Wollman } 327eae561b3SGarrett Wollman 328eae561b3SGarrett Wollman static u_int 329d660d38dSCraig Rodrigues xdrrec_getpos(XDR *xdrs) 330eae561b3SGarrett Wollman { 3318360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3328360efbdSAlfred Perlstein off_t pos; 333eae561b3SGarrett Wollman 3348360efbdSAlfred Perlstein pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); 3358f55a568SDoug Rabson if (pos == -1) 3368f55a568SDoug Rabson pos = 0; 337eae561b3SGarrett Wollman switch (xdrs->x_op) { 338eae561b3SGarrett Wollman 339eae561b3SGarrett Wollman case XDR_ENCODE: 340eae561b3SGarrett Wollman pos += rstrm->out_finger - rstrm->out_base; 341eae561b3SGarrett Wollman break; 342eae561b3SGarrett Wollman 343eae561b3SGarrett Wollman case XDR_DECODE: 344eae561b3SGarrett Wollman pos -= rstrm->in_boundry - rstrm->in_finger; 345eae561b3SGarrett Wollman break; 346eae561b3SGarrett Wollman 347eae561b3SGarrett Wollman default: 3488360efbdSAlfred Perlstein pos = (off_t) -1; 349eae561b3SGarrett Wollman break; 350eae561b3SGarrett Wollman } 351eae561b3SGarrett Wollman return ((u_int) pos); 352eae561b3SGarrett Wollman } 353eae561b3SGarrett Wollman 354eae561b3SGarrett Wollman static bool_t 355d660d38dSCraig Rodrigues xdrrec_setpos(XDR *xdrs, u_int pos) 356eae561b3SGarrett Wollman { 3578360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 358eae561b3SGarrett Wollman u_int currpos = xdrrec_getpos(xdrs); 359eae561b3SGarrett Wollman int delta = currpos - pos; 3608360efbdSAlfred Perlstein char *newpos; 361eae561b3SGarrett Wollman 362eae561b3SGarrett Wollman if ((int)currpos != -1) 363eae561b3SGarrett Wollman switch (xdrs->x_op) { 364eae561b3SGarrett Wollman 365eae561b3SGarrett Wollman case XDR_ENCODE: 366eae561b3SGarrett Wollman newpos = rstrm->out_finger - delta; 3678360efbdSAlfred Perlstein if ((newpos > (char *)(void *)(rstrm->frag_header)) && 368eae561b3SGarrett Wollman (newpos < rstrm->out_boundry)) { 369eae561b3SGarrett Wollman rstrm->out_finger = newpos; 370eae561b3SGarrett Wollman return (TRUE); 371eae561b3SGarrett Wollman } 372eae561b3SGarrett Wollman break; 373eae561b3SGarrett Wollman 374eae561b3SGarrett Wollman case XDR_DECODE: 375eae561b3SGarrett Wollman newpos = rstrm->in_finger - delta; 376eae561b3SGarrett Wollman if ((delta < (int)(rstrm->fbtbc)) && 377eae561b3SGarrett Wollman (newpos <= rstrm->in_boundry) && 378eae561b3SGarrett Wollman (newpos >= rstrm->in_base)) { 379eae561b3SGarrett Wollman rstrm->in_finger = newpos; 380eae561b3SGarrett Wollman rstrm->fbtbc -= delta; 381eae561b3SGarrett Wollman return (TRUE); 382eae561b3SGarrett Wollman } 383eae561b3SGarrett Wollman break; 3848360efbdSAlfred Perlstein 3858360efbdSAlfred Perlstein case XDR_FREE: 3868360efbdSAlfred Perlstein break; 387eae561b3SGarrett Wollman } 388eae561b3SGarrett Wollman return (FALSE); 389eae561b3SGarrett Wollman } 390eae561b3SGarrett Wollman 3911ad08a09SPeter Wemm static int32_t * 392d660d38dSCraig Rodrigues xdrrec_inline(XDR *xdrs, u_int len) 393eae561b3SGarrett Wollman { 3948360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3951ad08a09SPeter Wemm int32_t *buf = NULL; 396eae561b3SGarrett Wollman 397eae561b3SGarrett Wollman switch (xdrs->x_op) { 398eae561b3SGarrett Wollman 399eae561b3SGarrett Wollman case XDR_ENCODE: 400eae561b3SGarrett Wollman if ((rstrm->out_finger + len) <= rstrm->out_boundry) { 4018360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->out_finger; 402eae561b3SGarrett Wollman rstrm->out_finger += len; 403eae561b3SGarrett Wollman } 404eae561b3SGarrett Wollman break; 405eae561b3SGarrett Wollman 406eae561b3SGarrett Wollman case XDR_DECODE: 407eae561b3SGarrett Wollman if ((len <= rstrm->fbtbc) && 408eae561b3SGarrett Wollman ((rstrm->in_finger + len) <= rstrm->in_boundry)) { 4098360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->in_finger; 410eae561b3SGarrett Wollman rstrm->fbtbc -= len; 411eae561b3SGarrett Wollman rstrm->in_finger += len; 412eae561b3SGarrett Wollman } 413eae561b3SGarrett Wollman break; 4148360efbdSAlfred Perlstein 4158360efbdSAlfred Perlstein case XDR_FREE: 4168360efbdSAlfred Perlstein break; 417eae561b3SGarrett Wollman } 418eae561b3SGarrett Wollman return (buf); 419eae561b3SGarrett Wollman } 420eae561b3SGarrett Wollman 421eae561b3SGarrett Wollman static void 422d660d38dSCraig Rodrigues xdrrec_destroy(XDR *xdrs) 423eae561b3SGarrett Wollman { 4248360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 425eae561b3SGarrett Wollman 42608497c02SMartin Blapp mem_free(rstrm->out_base, rstrm->sendsize); 42708497c02SMartin Blapp mem_free(rstrm->in_base, rstrm->recvsize); 4288360efbdSAlfred Perlstein mem_free(rstrm, sizeof(RECSTREAM)); 429eae561b3SGarrett Wollman } 430eae561b3SGarrett Wollman 431eae561b3SGarrett Wollman 432eae561b3SGarrett Wollman /* 433eae561b3SGarrett Wollman * Exported routines to manage xdr records 434eae561b3SGarrett Wollman */ 435eae561b3SGarrett Wollman 436eae561b3SGarrett Wollman /* 437eae561b3SGarrett Wollman * Before reading (deserializing from the stream, one should always call 438eae561b3SGarrett Wollman * this procedure to guarantee proper record alignment. 439eae561b3SGarrett Wollman */ 440eae561b3SGarrett Wollman bool_t 441d660d38dSCraig Rodrigues xdrrec_skiprecord(XDR *xdrs) 442eae561b3SGarrett Wollman { 4438360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 44408497c02SMartin Blapp enum xprt_stat xstat; 44508497c02SMartin Blapp 44608497c02SMartin Blapp if (rstrm->nonblock) { 44708497c02SMartin Blapp if (__xdrrec_getrec(xdrs, &xstat, FALSE)) { 44808497c02SMartin Blapp rstrm->fbtbc = 0; 44908497c02SMartin Blapp return TRUE; 45008497c02SMartin Blapp } 45108497c02SMartin Blapp if (rstrm->in_finger == rstrm->in_boundry && 45208497c02SMartin Blapp xstat == XPRT_MOREREQS) { 45308497c02SMartin Blapp rstrm->fbtbc = 0; 45408497c02SMartin Blapp return TRUE; 45508497c02SMartin Blapp } 45608497c02SMartin Blapp return FALSE; 45708497c02SMartin Blapp } 458eae561b3SGarrett Wollman 459eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 460eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 461eae561b3SGarrett Wollman return (FALSE); 462eae561b3SGarrett Wollman rstrm->fbtbc = 0; 463eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 464eae561b3SGarrett Wollman return (FALSE); 465eae561b3SGarrett Wollman } 466eae561b3SGarrett Wollman rstrm->last_frag = FALSE; 467eae561b3SGarrett Wollman return (TRUE); 468eae561b3SGarrett Wollman } 469eae561b3SGarrett Wollman 470eae561b3SGarrett Wollman /* 4718360efbdSAlfred Perlstein * Look ahead function. 472eae561b3SGarrett Wollman * Returns TRUE iff there is no more input in the buffer 473eae561b3SGarrett Wollman * after consuming the rest of the current record. 474eae561b3SGarrett Wollman */ 475eae561b3SGarrett Wollman bool_t 476d660d38dSCraig Rodrigues xdrrec_eof(XDR *xdrs) 477eae561b3SGarrett Wollman { 4788360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 479eae561b3SGarrett Wollman 480eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 481eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 482eae561b3SGarrett Wollman return (TRUE); 483eae561b3SGarrett Wollman rstrm->fbtbc = 0; 484eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 485eae561b3SGarrett Wollman return (TRUE); 486eae561b3SGarrett Wollman } 487eae561b3SGarrett Wollman if (rstrm->in_finger == rstrm->in_boundry) 488eae561b3SGarrett Wollman return (TRUE); 489eae561b3SGarrett Wollman return (FALSE); 490eae561b3SGarrett Wollman } 491eae561b3SGarrett Wollman 492eae561b3SGarrett Wollman /* 493eae561b3SGarrett Wollman * The client must tell the package when an end-of-record has occurred. 494eae561b3SGarrett Wollman * The second paraemters tells whether the record should be flushed to the 495eae561b3SGarrett Wollman * (output) tcp stream. (This let's the package support batched or 496eae561b3SGarrett Wollman * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. 497eae561b3SGarrett Wollman */ 498eae561b3SGarrett Wollman bool_t 499d660d38dSCraig Rodrigues xdrrec_endofrecord(XDR *xdrs, bool_t sendnow) 500eae561b3SGarrett Wollman { 5018360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 5028360efbdSAlfred Perlstein u_long len; /* fragment length */ 503eae561b3SGarrett Wollman 504eae561b3SGarrett Wollman if (sendnow || rstrm->frag_sent || 5051ad08a09SPeter Wemm ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= 506eae561b3SGarrett Wollman (u_long)rstrm->out_boundry)) { 507eae561b3SGarrett Wollman rstrm->frag_sent = FALSE; 508eae561b3SGarrett Wollman return (flush_out(rstrm, TRUE)); 509eae561b3SGarrett Wollman } 510eae561b3SGarrett Wollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - 5111ad08a09SPeter Wemm sizeof(u_int32_t); 5128360efbdSAlfred Perlstein *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG); 5138360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger; 5141ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t); 515eae561b3SGarrett Wollman return (TRUE); 516eae561b3SGarrett Wollman } 517eae561b3SGarrett Wollman 51808497c02SMartin Blapp /* 51908497c02SMartin Blapp * Fill the stream buffer with a record for a non-blocking connection. 52008497c02SMartin Blapp * Return true if a record is available in the buffer, false if not. 52108497c02SMartin Blapp */ 52208497c02SMartin Blapp bool_t 523d660d38dSCraig Rodrigues __xdrrec_getrec(XDR *xdrs, enum xprt_stat *statp, bool_t expectdata) 52408497c02SMartin Blapp { 52508497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 52608497c02SMartin Blapp ssize_t n; 52708497c02SMartin Blapp int fraglen; 52808497c02SMartin Blapp 52908497c02SMartin Blapp if (!rstrm->in_haveheader) { 53008497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp, 53108497c02SMartin Blapp (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen); 53208497c02SMartin Blapp if (n == 0) { 53308497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE; 53408497c02SMartin Blapp return FALSE; 53508497c02SMartin Blapp } 53608497c02SMartin Blapp if (n < 0) { 53708497c02SMartin Blapp *statp = XPRT_DIED; 53808497c02SMartin Blapp return FALSE; 53908497c02SMartin Blapp } 54008497c02SMartin Blapp rstrm->in_hdrp += n; 54108497c02SMartin Blapp rstrm->in_hdrlen += n; 54208497c02SMartin Blapp if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) { 54308497c02SMartin Blapp *statp = XPRT_MOREREQS; 54408497c02SMartin Blapp return FALSE; 54508497c02SMartin Blapp } 54608497c02SMartin Blapp rstrm->in_header = ntohl(rstrm->in_header); 54708497c02SMartin Blapp fraglen = (int)(rstrm->in_header & ~LAST_FRAG); 54808497c02SMartin Blapp if (fraglen == 0 || fraglen > rstrm->in_maxrec || 54908497c02SMartin Blapp (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) { 55008497c02SMartin Blapp *statp = XPRT_DIED; 55108497c02SMartin Blapp return FALSE; 55208497c02SMartin Blapp } 55308497c02SMartin Blapp rstrm->in_reclen += fraglen; 55408497c02SMartin Blapp if (rstrm->in_reclen > rstrm->recvsize) 55508497c02SMartin Blapp realloc_stream(rstrm, rstrm->in_reclen); 55608497c02SMartin Blapp if (rstrm->in_header & LAST_FRAG) { 55708497c02SMartin Blapp rstrm->in_header &= ~LAST_FRAG; 55808497c02SMartin Blapp rstrm->last_frag = TRUE; 55908497c02SMartin Blapp } 5607ea7cc4bSDoug Rabson /* 5617ea7cc4bSDoug Rabson * We can only reasonably expect to read once from a 5627ea7cc4bSDoug Rabson * non-blocking stream. Reading the fragment header 5637ea7cc4bSDoug Rabson * may have drained the stream. 5647ea7cc4bSDoug Rabson */ 5657ea7cc4bSDoug Rabson expectdata = FALSE; 56608497c02SMartin Blapp } 56708497c02SMartin Blapp 56808497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle, 56908497c02SMartin Blapp rstrm->in_base + rstrm->in_received, 57008497c02SMartin Blapp (rstrm->in_reclen - rstrm->in_received)); 57108497c02SMartin Blapp 57208497c02SMartin Blapp if (n < 0) { 57308497c02SMartin Blapp *statp = XPRT_DIED; 57408497c02SMartin Blapp return FALSE; 57508497c02SMartin Blapp } 57608497c02SMartin Blapp 57708497c02SMartin Blapp if (n == 0) { 57808497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE; 57908497c02SMartin Blapp return FALSE; 58008497c02SMartin Blapp } 58108497c02SMartin Blapp 58208497c02SMartin Blapp rstrm->in_received += n; 58308497c02SMartin Blapp 58408497c02SMartin Blapp if (rstrm->in_received == rstrm->in_reclen) { 58508497c02SMartin Blapp rstrm->in_haveheader = FALSE; 58608497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; 58708497c02SMartin Blapp rstrm->in_hdrlen = 0; 58808497c02SMartin Blapp if (rstrm->last_frag) { 58908497c02SMartin Blapp rstrm->fbtbc = rstrm->in_reclen; 59008497c02SMartin Blapp rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen; 59108497c02SMartin Blapp rstrm->in_finger = rstrm->in_base; 59240525d3dSMartin Blapp rstrm->in_reclen = rstrm->in_received = 0; 59308497c02SMartin Blapp *statp = XPRT_MOREREQS; 59408497c02SMartin Blapp return TRUE; 59508497c02SMartin Blapp } 59608497c02SMartin Blapp } 59708497c02SMartin Blapp 59808497c02SMartin Blapp *statp = XPRT_MOREREQS; 59908497c02SMartin Blapp return FALSE; 60008497c02SMartin Blapp } 60108497c02SMartin Blapp 60208497c02SMartin Blapp bool_t 603d660d38dSCraig Rodrigues __xdrrec_setnonblock(XDR *xdrs, int maxrec) 60408497c02SMartin Blapp { 60508497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 60608497c02SMartin Blapp 60708497c02SMartin Blapp rstrm->nonblock = TRUE; 60808497c02SMartin Blapp if (maxrec == 0) 60908497c02SMartin Blapp maxrec = rstrm->recvsize; 61008497c02SMartin Blapp rstrm->in_maxrec = maxrec; 61108497c02SMartin Blapp return TRUE; 61208497c02SMartin Blapp } 613eae561b3SGarrett Wollman 614eae561b3SGarrett Wollman /* 615eae561b3SGarrett Wollman * Internal useful routines 616eae561b3SGarrett Wollman */ 617eae561b3SGarrett Wollman static bool_t 618d660d38dSCraig Rodrigues flush_out(RECSTREAM *rstrm, bool_t eor) 619eae561b3SGarrett Wollman { 6208360efbdSAlfred Perlstein u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0; 6218360efbdSAlfred Perlstein u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) - 6228360efbdSAlfred Perlstein (u_long)(rstrm->frag_header) - sizeof(u_int32_t)); 623eae561b3SGarrett Wollman 624eae561b3SGarrett Wollman *(rstrm->frag_header) = htonl(len | eormask); 6258360efbdSAlfred Perlstein len = (u_int32_t)((u_long)(rstrm->out_finger) - 6268360efbdSAlfred Perlstein (u_long)(rstrm->out_base)); 627eae561b3SGarrett Wollman if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) 628eae561b3SGarrett Wollman != (int)len) 629eae561b3SGarrett Wollman return (FALSE); 6308360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; 6318360efbdSAlfred Perlstein rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t); 632eae561b3SGarrett Wollman return (TRUE); 633eae561b3SGarrett Wollman } 634eae561b3SGarrett Wollman 635eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 636d660d38dSCraig Rodrigues fill_input_buf(RECSTREAM *rstrm) 637eae561b3SGarrett Wollman { 6388360efbdSAlfred Perlstein char *where; 6398360efbdSAlfred Perlstein u_int32_t i; 6408360efbdSAlfred Perlstein int len; 641eae561b3SGarrett Wollman 64208497c02SMartin Blapp if (rstrm->nonblock) 64308497c02SMartin Blapp return FALSE; 64408497c02SMartin Blapp 645eae561b3SGarrett Wollman where = rstrm->in_base; 6468360efbdSAlfred Perlstein i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT); 647eae561b3SGarrett Wollman where += i; 6488360efbdSAlfred Perlstein len = (u_int32_t)(rstrm->in_size - i); 649eae561b3SGarrett Wollman if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) 650eae561b3SGarrett Wollman return (FALSE); 651eae561b3SGarrett Wollman rstrm->in_finger = where; 652eae561b3SGarrett Wollman where += len; 653eae561b3SGarrett Wollman rstrm->in_boundry = where; 654eae561b3SGarrett Wollman return (TRUE); 655eae561b3SGarrett Wollman } 656eae561b3SGarrett Wollman 657eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */ 658d660d38dSCraig Rodrigues get_input_bytes(RECSTREAM *rstrm, char *addr, int len) 659eae561b3SGarrett Wollman { 6608360efbdSAlfred Perlstein size_t current; 661eae561b3SGarrett Wollman 66240525d3dSMartin Blapp if (rstrm->nonblock) { 66340525d3dSMartin Blapp if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) 66440525d3dSMartin Blapp return FALSE; 66540525d3dSMartin Blapp memcpy(addr, rstrm->in_finger, (size_t)len); 66640525d3dSMartin Blapp rstrm->in_finger += len; 66740525d3dSMartin Blapp return TRUE; 66840525d3dSMartin Blapp } 66940525d3dSMartin Blapp 670eae561b3SGarrett Wollman while (len > 0) { 6718360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry - 6728360efbdSAlfred Perlstein (long)rstrm->in_finger); 673eae561b3SGarrett Wollman if (current == 0) { 674eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 675eae561b3SGarrett Wollman return (FALSE); 676eae561b3SGarrett Wollman continue; 677eae561b3SGarrett Wollman } 678eae561b3SGarrett Wollman current = (len < current) ? len : current; 6798360efbdSAlfred Perlstein memmove(addr, rstrm->in_finger, current); 680eae561b3SGarrett Wollman rstrm->in_finger += current; 681eae561b3SGarrett Wollman addr += current; 682eae561b3SGarrett Wollman len -= current; 683eae561b3SGarrett Wollman } 684eae561b3SGarrett Wollman return (TRUE); 685eae561b3SGarrett Wollman } 686eae561b3SGarrett Wollman 687eae561b3SGarrett Wollman static bool_t /* next two bytes of the input stream are treated as a header */ 688d660d38dSCraig Rodrigues set_input_fragment(RECSTREAM *rstrm) 689eae561b3SGarrett Wollman { 6901ad08a09SPeter Wemm u_int32_t header; 691eae561b3SGarrett Wollman 69222e4d31aSMartin Blapp if (rstrm->nonblock) 69322e4d31aSMartin Blapp return FALSE; 6948360efbdSAlfred Perlstein if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header))) 695eae561b3SGarrett Wollman return (FALSE); 6968360efbdSAlfred Perlstein header = ntohl(header); 697eae561b3SGarrett Wollman rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; 698a9352e90SBill Paul /* 699a9352e90SBill Paul * Sanity check. Try not to accept wildly incorrect 7001ce4aec2SBill Paul * record sizes. Unfortunately, the only record size 7011ce4aec2SBill Paul * we can positively identify as being 'wildly incorrect' 7021ce4aec2SBill Paul * is zero. Ridiculously large record sizes may look wrong, 7031ce4aec2SBill Paul * but we don't have any way to be certain that they aren't 7041ce4aec2SBill Paul * what the client actually intended to send us. 705a9352e90SBill Paul */ 706c50a9e8fSBill Paul if (header == 0) 707a9352e90SBill Paul return(FALSE); 708eae561b3SGarrett Wollman rstrm->fbtbc = header & (~LAST_FRAG); 709eae561b3SGarrett Wollman return (TRUE); 710eae561b3SGarrett Wollman } 711eae561b3SGarrett Wollman 712eae561b3SGarrett Wollman static bool_t /* consumes input bytes; knows nothing about records! */ 713d660d38dSCraig Rodrigues skip_input_bytes(RECSTREAM *rstrm, long cnt) 714eae561b3SGarrett Wollman { 7158360efbdSAlfred Perlstein u_int32_t current; 716eae561b3SGarrett Wollman 717eae561b3SGarrett Wollman while (cnt > 0) { 7188360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry - 7198360efbdSAlfred Perlstein (long)rstrm->in_finger); 720eae561b3SGarrett Wollman if (current == 0) { 721eae561b3SGarrett Wollman if (! fill_input_buf(rstrm)) 722eae561b3SGarrett Wollman return (FALSE); 723eae561b3SGarrett Wollman continue; 724eae561b3SGarrett Wollman } 7258360efbdSAlfred Perlstein current = (u_int32_t)((cnt < current) ? cnt : current); 726eae561b3SGarrett Wollman rstrm->in_finger += current; 727eae561b3SGarrett Wollman cnt -= current; 728eae561b3SGarrett Wollman } 729eae561b3SGarrett Wollman return (TRUE); 730eae561b3SGarrett Wollman } 731eae561b3SGarrett Wollman 732eae561b3SGarrett Wollman static u_int 733d660d38dSCraig Rodrigues fix_buf_size(u_int s) 734eae561b3SGarrett Wollman { 735eae561b3SGarrett Wollman 736eae561b3SGarrett Wollman if (s < 100) 737eae561b3SGarrett Wollman s = 4000; 738eae561b3SGarrett Wollman return (RNDUP(s)); 739eae561b3SGarrett Wollman } 74008497c02SMartin Blapp 74108497c02SMartin Blapp /* 74208497c02SMartin Blapp * Reallocate the input buffer for a non-block stream. 74308497c02SMartin Blapp */ 74408497c02SMartin Blapp static bool_t 745d660d38dSCraig Rodrigues realloc_stream(RECSTREAM *rstrm, int size) 74608497c02SMartin Blapp { 74708497c02SMartin Blapp ptrdiff_t diff; 74808497c02SMartin Blapp char *buf; 74908497c02SMartin Blapp 75008497c02SMartin Blapp if (size > rstrm->recvsize) { 75108497c02SMartin Blapp buf = realloc(rstrm->in_base, (size_t)size); 75208497c02SMartin Blapp if (buf == NULL) 75308497c02SMartin Blapp return FALSE; 75408497c02SMartin Blapp diff = buf - rstrm->in_base; 75508497c02SMartin Blapp rstrm->in_finger += diff; 75608497c02SMartin Blapp rstrm->in_base = buf; 75708497c02SMartin Blapp rstrm->in_boundry = buf + size; 75808497c02SMartin Blapp rstrm->recvsize = size; 75908497c02SMartin Blapp rstrm->in_size = size; 76008497c02SMartin Blapp } 76108497c02SMartin Blapp 76208497c02SMartin Blapp return TRUE; 76308497c02SMartin Blapp } 764