1*0a6a1f1dSLionel Sambuc /* $NetBSD: xdr_rec.c,v 1.36 2015/03/26 11:31:57 justin Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*
484d9c625SLionel Sambuc * Copyright (c) 2010, Oracle America, Inc.
52fe8fb19SBen Gras *
684d9c625SLionel Sambuc * Redistribution and use in source and binary forms, with or without
784d9c625SLionel Sambuc * modification, are permitted provided that the following conditions are
884d9c625SLionel Sambuc * met:
92fe8fb19SBen Gras *
1084d9c625SLionel Sambuc * * Redistributions of source code must retain the above copyright
1184d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1284d9c625SLionel Sambuc * * Redistributions in binary form must reproduce the above
1384d9c625SLionel Sambuc * copyright notice, this list of conditions and the following
1484d9c625SLionel Sambuc * disclaimer in the documentation and/or other materials
1584d9c625SLionel Sambuc * provided with the distribution.
1684d9c625SLionel Sambuc * * Neither the name of the "Oracle America, Inc." nor the names of its
1784d9c625SLionel Sambuc * contributors may be used to endorse or promote products derived
1884d9c625SLionel Sambuc * from this software without specific prior written permission.
192fe8fb19SBen Gras *
2084d9c625SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2184d9c625SLionel Sambuc * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2284d9c625SLionel Sambuc * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2384d9c625SLionel Sambuc * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2484d9c625SLionel Sambuc * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2584d9c625SLionel Sambuc * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2684d9c625SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2784d9c625SLionel Sambuc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2884d9c625SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2984d9c625SLionel Sambuc * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3084d9c625SLionel Sambuc * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3184d9c625SLionel Sambuc * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322fe8fb19SBen Gras */
332fe8fb19SBen Gras
342fe8fb19SBen Gras #include <sys/cdefs.h>
352fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
362fe8fb19SBen Gras #if 0
372fe8fb19SBen Gras static char *sccsid = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
382fe8fb19SBen Gras static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";
392fe8fb19SBen Gras #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: xdr_rec.c,v 1.36 2015/03/26 11:31:57 justin Exp $");
412fe8fb19SBen Gras #endif
422fe8fb19SBen Gras #endif
432fe8fb19SBen Gras
442fe8fb19SBen Gras /*
452fe8fb19SBen Gras * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
462fe8fb19SBen Gras * layer above tcp (for rpc's use).
472fe8fb19SBen Gras *
482fe8fb19SBen Gras * Copyright (C) 1984, Sun Microsystems, Inc.
492fe8fb19SBen Gras *
502fe8fb19SBen Gras * These routines interface XDRSTREAMS to a tcp/ip connection.
512fe8fb19SBen Gras * There is a record marking layer between the xdr stream
522fe8fb19SBen Gras * and the tcp transport level. A record is composed on one or more
532fe8fb19SBen Gras * record fragments. A record fragment is a thirty-two bit header followed
542fe8fb19SBen Gras * by n bytes of data, where n is contained in the header. The header
552fe8fb19SBen Gras * is represented as a htonl(u_long). Thegh order bit encodes
562fe8fb19SBen Gras * whether or not the fragment is the last fragment of the record
572fe8fb19SBen Gras * (1 => fragment is last, 0 => more fragments to follow.
582fe8fb19SBen Gras * The other 31 bits encode the byte length of the fragment.
592fe8fb19SBen Gras */
602fe8fb19SBen Gras
612fe8fb19SBen Gras #include "namespace.h"
622fe8fb19SBen Gras
632fe8fb19SBen Gras #include <sys/types.h>
642fe8fb19SBen Gras
652fe8fb19SBen Gras #include <netinet/in.h>
662fe8fb19SBen Gras
67f14fb602SLionel Sambuc #include <assert.h>
682fe8fb19SBen Gras #include <err.h>
692fe8fb19SBen Gras #include <stddef.h>
702fe8fb19SBen Gras #include <stdio.h>
712fe8fb19SBen Gras #include <stdlib.h>
722fe8fb19SBen Gras #include <string.h>
732fe8fb19SBen Gras
742fe8fb19SBen Gras #include <rpc/types.h>
752fe8fb19SBen Gras #include <rpc/xdr.h>
762fe8fb19SBen Gras #include <rpc/auth.h>
772fe8fb19SBen Gras #include <rpc/svc.h>
782fe8fb19SBen Gras #include <rpc/clnt.h>
792fe8fb19SBen Gras
802fe8fb19SBen Gras #include "rpc_internal.h"
812fe8fb19SBen Gras
822fe8fb19SBen Gras #ifdef __weak_alias
832fe8fb19SBen Gras __weak_alias(xdrrec_create,_xdrrec_create)
842fe8fb19SBen Gras __weak_alias(xdrrec_endofrecord,_xdrrec_endofrecord)
852fe8fb19SBen Gras __weak_alias(xdrrec_eof,_xdrrec_eof)
862fe8fb19SBen Gras __weak_alias(xdrrec_skiprecord,_xdrrec_skiprecord)
872fe8fb19SBen Gras #endif
882fe8fb19SBen Gras
89f14fb602SLionel Sambuc static bool_t xdrrec_getlong(XDR *, long *);
90f14fb602SLionel Sambuc static bool_t xdrrec_putlong(XDR *, const long *);
91f14fb602SLionel Sambuc static bool_t xdrrec_getbytes(XDR *, char *, u_int);
922fe8fb19SBen Gras
93f14fb602SLionel Sambuc static bool_t xdrrec_putbytes(XDR *, const char *, u_int);
94f14fb602SLionel Sambuc static u_int xdrrec_getpos(XDR *);
95f14fb602SLionel Sambuc static bool_t xdrrec_setpos(XDR *, u_int);
96f14fb602SLionel Sambuc static int32_t *xdrrec_inline(XDR *, u_int);
97f14fb602SLionel Sambuc static void xdrrec_destroy(XDR *);
982fe8fb19SBen Gras
992fe8fb19SBen Gras static const struct xdr_ops xdrrec_ops = {
1002fe8fb19SBen Gras xdrrec_getlong,
1012fe8fb19SBen Gras xdrrec_putlong,
1022fe8fb19SBen Gras xdrrec_getbytes,
1032fe8fb19SBen Gras xdrrec_putbytes,
1042fe8fb19SBen Gras xdrrec_getpos,
1052fe8fb19SBen Gras xdrrec_setpos,
1062fe8fb19SBen Gras xdrrec_inline,
1072fe8fb19SBen Gras xdrrec_destroy,
1082fe8fb19SBen Gras NULL, /* xdrrec_control */
1092fe8fb19SBen Gras };
1102fe8fb19SBen Gras
1112fe8fb19SBen Gras /*
1122fe8fb19SBen Gras * A record is composed of one or more record fragments.
1132fe8fb19SBen Gras * A record fragment is a four-byte header followed by zero to
1142fe8fb19SBen Gras * 2**32-1 bytes. The header is treated as a long unsigned and is
1152fe8fb19SBen Gras * encode/decoded to the network via htonl/ntohl. The low order 31 bits
1162fe8fb19SBen Gras * are a byte count of the fragment. The highest order bit is a boolean:
1172fe8fb19SBen Gras * 1 => this fragment is the last fragment of the record,
1182fe8fb19SBen Gras * 0 => this fragment is followed by more fragment(s).
1192fe8fb19SBen Gras *
1202fe8fb19SBen Gras * The fragment/record machinery is not general; it is constructed to
1212fe8fb19SBen Gras * meet the needs of xdr and rpc based on tcp.
1222fe8fb19SBen Gras */
1232fe8fb19SBen Gras
124f14fb602SLionel Sambuc #define LAST_FRAG ((uint32_t)(1 << 31))
1252fe8fb19SBen Gras
1262fe8fb19SBen Gras typedef struct rec_strm {
1272fe8fb19SBen Gras char *tcp_handle;
1282fe8fb19SBen Gras /*
1292fe8fb19SBen Gras * out-goung bits
1302fe8fb19SBen Gras */
131f14fb602SLionel Sambuc int (*writeit)(char *, char *, int);
1322fe8fb19SBen Gras char *out_base; /* output buffer (points to frag header) */
1332fe8fb19SBen Gras char *out_finger; /* next output position */
1342fe8fb19SBen Gras char *out_boundry; /* data cannot up to this address */
135f14fb602SLionel Sambuc uint32_t *frag_header; /* beginning of curren fragment */
1362fe8fb19SBen Gras bool_t frag_sent; /* true if buffer sent in middle of record */
1372fe8fb19SBen Gras /*
1382fe8fb19SBen Gras * in-coming bits
1392fe8fb19SBen Gras */
140f14fb602SLionel Sambuc int (*readit)(char *, char *, int);
1412fe8fb19SBen Gras u_long in_size; /* fixed size of the input buffer */
1422fe8fb19SBen Gras char *in_base;
1432fe8fb19SBen Gras char *in_finger; /* location of next byte to be had */
1442fe8fb19SBen Gras char *in_boundry; /* can read up to this location */
1452fe8fb19SBen Gras long fbtbc; /* fragment bytes to be consumed */
1462fe8fb19SBen Gras bool_t last_frag;
1472fe8fb19SBen Gras u_int sendsize;
1482fe8fb19SBen Gras u_int recvsize;
1492fe8fb19SBen Gras
1502fe8fb19SBen Gras bool_t nonblock;
1512fe8fb19SBen Gras bool_t in_haveheader;
152f14fb602SLionel Sambuc uint32_t in_header;
1532fe8fb19SBen Gras char *in_hdrp;
1542fe8fb19SBen Gras int in_hdrlen;
1552fe8fb19SBen Gras int in_reclen;
1562fe8fb19SBen Gras int in_received;
1572fe8fb19SBen Gras int in_maxrec;
1582fe8fb19SBen Gras } RECSTREAM;
1592fe8fb19SBen Gras
160f14fb602SLionel Sambuc static u_int fix_buf_size(u_int);
161f14fb602SLionel Sambuc static bool_t flush_out(RECSTREAM *, bool_t);
162f14fb602SLionel Sambuc static bool_t fill_input_buf(RECSTREAM *);
163f14fb602SLionel Sambuc static bool_t get_input_bytes(RECSTREAM *, char *, u_int);
164f14fb602SLionel Sambuc static bool_t set_input_fragment(RECSTREAM *);
165f14fb602SLionel Sambuc static bool_t skip_input_bytes(RECSTREAM *, long);
166f14fb602SLionel Sambuc static bool_t realloc_stream(RECSTREAM *, int);
1672fe8fb19SBen Gras
1682fe8fb19SBen Gras
1692fe8fb19SBen Gras /*
1702fe8fb19SBen Gras * Create an xdr handle for xdrrec
1712fe8fb19SBen Gras * xdrrec_create fills in xdrs. Sendsize and recvsize are
1722fe8fb19SBen Gras * send and recv buffer sizes (0 => use default).
1732fe8fb19SBen Gras * tcp_handle is an opaque handle that is passed as the first parameter to
1742fe8fb19SBen Gras * the procedures readit and writeit. Readit and writeit are read and
1752fe8fb19SBen Gras * write respectively. They are like the system
1762fe8fb19SBen Gras * calls expect that they take an opaque handle rather than an fd.
1772fe8fb19SBen Gras */
1782fe8fb19SBen Gras void
xdrrec_create(XDR * xdrs,u_int sendsize,u_int recvsize,char * tcp_handle,int (* readit)(char *,char *,int),int (* writeit)(char *,char *,int))179f14fb602SLionel Sambuc xdrrec_create(
180f14fb602SLionel Sambuc XDR *xdrs,
181f14fb602SLionel Sambuc u_int sendsize,
182f14fb602SLionel Sambuc u_int recvsize,
183f14fb602SLionel Sambuc char *tcp_handle,
1842fe8fb19SBen Gras /* like read, but pass it a tcp_handle, not sock */
185f14fb602SLionel Sambuc int (*readit)(char *, char *, int),
1862fe8fb19SBen Gras /* like write, but pass it a tcp_handle, not sock */
187f14fb602SLionel Sambuc int (*writeit)(char *, char *, int))
1882fe8fb19SBen Gras {
1892fe8fb19SBen Gras RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
1902fe8fb19SBen Gras
1912fe8fb19SBen Gras if (rstrm == NULL) {
19284d9c625SLionel Sambuc warn("%s: out of memory", __func__);
1932fe8fb19SBen Gras /*
1942fe8fb19SBen Gras * This is bad. Should rework xdrrec_create to
1952fe8fb19SBen Gras * return a handle, and in this case return NULL
1962fe8fb19SBen Gras */
1972fe8fb19SBen Gras return;
1982fe8fb19SBen Gras }
1992fe8fb19SBen Gras
2002fe8fb19SBen Gras rstrm->sendsize = sendsize = fix_buf_size(sendsize);
2012fe8fb19SBen Gras rstrm->out_base = malloc(rstrm->sendsize);
2022fe8fb19SBen Gras if (rstrm->out_base == NULL) {
20384d9c625SLionel Sambuc warn("%s: out of memory", __func__);
2042fe8fb19SBen Gras mem_free(rstrm, sizeof(RECSTREAM));
2052fe8fb19SBen Gras return;
2062fe8fb19SBen Gras }
2072fe8fb19SBen Gras
2082fe8fb19SBen Gras rstrm->recvsize = recvsize = fix_buf_size(recvsize);
2092fe8fb19SBen Gras rstrm->in_base = malloc(recvsize);
2102fe8fb19SBen Gras if (rstrm->in_base == NULL) {
21184d9c625SLionel Sambuc warn("%s: out of memory", __func__);
2122fe8fb19SBen Gras mem_free(rstrm->out_base, sendsize);
2132fe8fb19SBen Gras mem_free(rstrm, sizeof(RECSTREAM));
2142fe8fb19SBen Gras return;
2152fe8fb19SBen Gras }
2162fe8fb19SBen Gras /*
2172fe8fb19SBen Gras * now the rest ...
2182fe8fb19SBen Gras */
2192fe8fb19SBen Gras xdrs->x_ops = &xdrrec_ops;
2202fe8fb19SBen Gras xdrs->x_private = rstrm;
2212fe8fb19SBen Gras rstrm->tcp_handle = tcp_handle;
2222fe8fb19SBen Gras rstrm->readit = readit;
2232fe8fb19SBen Gras rstrm->writeit = writeit;
2242fe8fb19SBen Gras rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
225f14fb602SLionel Sambuc rstrm->frag_header = (uint32_t *)(void *)rstrm->out_base;
226f14fb602SLionel Sambuc rstrm->out_finger += sizeof(uint32_t);
2272fe8fb19SBen Gras rstrm->out_boundry += sendsize;
2282fe8fb19SBen Gras rstrm->frag_sent = FALSE;
2292fe8fb19SBen Gras rstrm->in_size = recvsize;
2302fe8fb19SBen Gras rstrm->in_boundry = rstrm->in_base;
2312fe8fb19SBen Gras rstrm->in_finger = (rstrm->in_boundry += recvsize);
2322fe8fb19SBen Gras rstrm->fbtbc = 0;
2332fe8fb19SBen Gras rstrm->last_frag = TRUE;
2342fe8fb19SBen Gras rstrm->in_haveheader = FALSE;
2352fe8fb19SBen Gras rstrm->in_hdrlen = 0;
2362fe8fb19SBen Gras rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
2372fe8fb19SBen Gras rstrm->nonblock = FALSE;
2382fe8fb19SBen Gras rstrm->in_reclen = 0;
2392fe8fb19SBen Gras rstrm->in_received = 0;
2402fe8fb19SBen Gras }
2412fe8fb19SBen Gras
2422fe8fb19SBen Gras
2432fe8fb19SBen Gras /*
2442fe8fb19SBen Gras * The reoutines defined below are the xdr ops which will go into the
2452fe8fb19SBen Gras * xdr handle filled in by xdrrec_create.
2462fe8fb19SBen Gras */
2472fe8fb19SBen Gras
2482fe8fb19SBen Gras static bool_t
xdrrec_getlong(XDR * xdrs,long * lp)249f14fb602SLionel Sambuc xdrrec_getlong(XDR *xdrs, long *lp)
2502fe8fb19SBen Gras {
2512fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2522fe8fb19SBen Gras int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
2532fe8fb19SBen Gras int32_t mylong;
2542fe8fb19SBen Gras
2552fe8fb19SBen Gras /* first try the inline, fast case */
2562fe8fb19SBen Gras if ((rstrm->fbtbc >= (long)sizeof(int32_t)) &&
2572fe8fb19SBen Gras (((uintptr_t)rstrm->in_boundry - (uintptr_t)buflp) >= sizeof(int32_t))) {
258f14fb602SLionel Sambuc *lp = (long)ntohl((uint32_t)(*buflp));
2592fe8fb19SBen Gras rstrm->fbtbc -= sizeof(int32_t);
2602fe8fb19SBen Gras rstrm->in_finger += sizeof(int32_t);
2612fe8fb19SBen Gras } else {
2622fe8fb19SBen Gras if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
263f14fb602SLionel Sambuc (u_int)sizeof(int32_t)))
2642fe8fb19SBen Gras return (FALSE);
265f14fb602SLionel Sambuc *lp = (long)ntohl((uint32_t)mylong);
2662fe8fb19SBen Gras }
2672fe8fb19SBen Gras return (TRUE);
2682fe8fb19SBen Gras }
2692fe8fb19SBen Gras
2702fe8fb19SBen Gras static bool_t
xdrrec_putlong(XDR * xdrs,const long * lp)271f14fb602SLionel Sambuc xdrrec_putlong(XDR *xdrs, const long *lp)
2722fe8fb19SBen Gras {
2732fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2742fe8fb19SBen Gras int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
2752fe8fb19SBen Gras
2762fe8fb19SBen Gras if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
2772fe8fb19SBen Gras /*
2782fe8fb19SBen Gras * this case should almost never happen so the code is
2792fe8fb19SBen Gras * inefficient
2802fe8fb19SBen Gras */
2812fe8fb19SBen Gras rstrm->out_finger -= sizeof(int32_t);
2822fe8fb19SBen Gras rstrm->frag_sent = TRUE;
2832fe8fb19SBen Gras if (! flush_out(rstrm, FALSE))
2842fe8fb19SBen Gras return (FALSE);
2852fe8fb19SBen Gras dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
2862fe8fb19SBen Gras rstrm->out_finger += sizeof(int32_t);
2872fe8fb19SBen Gras }
288f14fb602SLionel Sambuc *dest_lp = (int32_t)htonl((uint32_t)(*lp));
2892fe8fb19SBen Gras return (TRUE);
2902fe8fb19SBen Gras }
2912fe8fb19SBen Gras
2922fe8fb19SBen Gras static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes(XDR * xdrs,char * addr,u_int len)293f14fb602SLionel Sambuc xdrrec_getbytes(XDR *xdrs, char *addr, u_int len)
2942fe8fb19SBen Gras {
2952fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2962fe8fb19SBen Gras u_int current;
2972fe8fb19SBen Gras
2982fe8fb19SBen Gras while (len > 0) {
2992fe8fb19SBen Gras current = (u_int)rstrm->fbtbc;
3002fe8fb19SBen Gras if (current == 0) {
3012fe8fb19SBen Gras if (rstrm->last_frag)
3022fe8fb19SBen Gras return (FALSE);
3032fe8fb19SBen Gras if (! set_input_fragment(rstrm))
3042fe8fb19SBen Gras return (FALSE);
3052fe8fb19SBen Gras continue;
3062fe8fb19SBen Gras }
3072fe8fb19SBen Gras current = (len < current) ? len : current;
3082fe8fb19SBen Gras if (! get_input_bytes(rstrm, addr, current))
3092fe8fb19SBen Gras return (FALSE);
3102fe8fb19SBen Gras addr += current;
3112fe8fb19SBen Gras rstrm->fbtbc -= current;
3122fe8fb19SBen Gras len -= current;
3132fe8fb19SBen Gras }
3142fe8fb19SBen Gras return (TRUE);
3152fe8fb19SBen Gras }
3162fe8fb19SBen Gras
3172fe8fb19SBen Gras static bool_t
xdrrec_putbytes(XDR * xdrs,const char * addr,u_int len)318f14fb602SLionel Sambuc xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len)
3192fe8fb19SBen Gras {
3202fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
3212fe8fb19SBen Gras size_t current;
3222fe8fb19SBen Gras
3232fe8fb19SBen Gras while (len > 0) {
3242fe8fb19SBen Gras current = (size_t)((u_long)rstrm->out_boundry -
3252fe8fb19SBen Gras (u_long)rstrm->out_finger);
3262fe8fb19SBen Gras current = (len < current) ? len : current;
3272fe8fb19SBen Gras memmove(rstrm->out_finger, addr, current);
3282fe8fb19SBen Gras rstrm->out_finger += current;
3292fe8fb19SBen Gras addr += current;
330f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(u_int, current));
331f14fb602SLionel Sambuc len -= (u_int)current;
3322fe8fb19SBen Gras if (rstrm->out_finger == rstrm->out_boundry) {
3332fe8fb19SBen Gras rstrm->frag_sent = TRUE;
3342fe8fb19SBen Gras if (! flush_out(rstrm, FALSE))
3352fe8fb19SBen Gras return (FALSE);
3362fe8fb19SBen Gras }
3372fe8fb19SBen Gras }
3382fe8fb19SBen Gras return (TRUE);
3392fe8fb19SBen Gras }
3402fe8fb19SBen Gras
3412fe8fb19SBen Gras static u_int
xdrrec_getpos(XDR * xdrs)342f14fb602SLionel Sambuc xdrrec_getpos(XDR *xdrs)
3432fe8fb19SBen Gras {
3442fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
3452fe8fb19SBen Gras off_t pos;
3462fe8fb19SBen Gras
3472fe8fb19SBen Gras pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1);
3482fe8fb19SBen Gras if (pos != -1)
3492fe8fb19SBen Gras switch (xdrs->x_op) {
3502fe8fb19SBen Gras
3512fe8fb19SBen Gras case XDR_ENCODE:
3522fe8fb19SBen Gras pos += rstrm->out_finger - rstrm->out_base;
3532fe8fb19SBen Gras break;
3542fe8fb19SBen Gras
3552fe8fb19SBen Gras case XDR_DECODE:
3562fe8fb19SBen Gras pos -= rstrm->in_boundry - rstrm->in_finger;
3572fe8fb19SBen Gras break;
3582fe8fb19SBen Gras
3592fe8fb19SBen Gras default:
3602fe8fb19SBen Gras pos = (off_t) -1;
3612fe8fb19SBen Gras break;
3622fe8fb19SBen Gras }
3632fe8fb19SBen Gras return ((u_int) pos);
3642fe8fb19SBen Gras }
3652fe8fb19SBen Gras
3662fe8fb19SBen Gras static bool_t
xdrrec_setpos(XDR * xdrs,u_int pos)367f14fb602SLionel Sambuc xdrrec_setpos(XDR *xdrs, u_int pos)
3682fe8fb19SBen Gras {
3692fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
3702fe8fb19SBen Gras u_int currpos = xdrrec_getpos(xdrs);
3712fe8fb19SBen Gras int delta = currpos - pos;
3722fe8fb19SBen Gras char *newpos;
3732fe8fb19SBen Gras
3742fe8fb19SBen Gras if ((int)currpos != -1)
3752fe8fb19SBen Gras switch (xdrs->x_op) {
3762fe8fb19SBen Gras
3772fe8fb19SBen Gras case XDR_ENCODE:
3782fe8fb19SBen Gras newpos = rstrm->out_finger - delta;
3792fe8fb19SBen Gras if ((newpos > (char *)(void *)(rstrm->frag_header)) &&
3802fe8fb19SBen Gras (newpos < rstrm->out_boundry)) {
3812fe8fb19SBen Gras rstrm->out_finger = newpos;
3822fe8fb19SBen Gras return (TRUE);
3832fe8fb19SBen Gras }
3842fe8fb19SBen Gras break;
3852fe8fb19SBen Gras
3862fe8fb19SBen Gras case XDR_DECODE:
3872fe8fb19SBen Gras newpos = rstrm->in_finger - delta;
3882fe8fb19SBen Gras if ((delta < (int)(rstrm->fbtbc)) &&
3892fe8fb19SBen Gras (newpos <= rstrm->in_boundry) &&
3902fe8fb19SBen Gras (newpos >= rstrm->in_base)) {
3912fe8fb19SBen Gras rstrm->in_finger = newpos;
3922fe8fb19SBen Gras rstrm->fbtbc -= delta;
3932fe8fb19SBen Gras return (TRUE);
3942fe8fb19SBen Gras }
3952fe8fb19SBen Gras break;
3962fe8fb19SBen Gras
3972fe8fb19SBen Gras case XDR_FREE:
3982fe8fb19SBen Gras break;
3992fe8fb19SBen Gras }
4002fe8fb19SBen Gras return (FALSE);
4012fe8fb19SBen Gras }
4022fe8fb19SBen Gras
4032fe8fb19SBen Gras static int32_t *
xdrrec_inline(XDR * xdrs,u_int len)404f14fb602SLionel Sambuc xdrrec_inline(XDR *xdrs, u_int len)
4052fe8fb19SBen Gras {
4062fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
4072fe8fb19SBen Gras int32_t *buf = NULL;
4082fe8fb19SBen Gras
4092fe8fb19SBen Gras switch (xdrs->x_op) {
4102fe8fb19SBen Gras
4112fe8fb19SBen Gras case XDR_ENCODE:
4122fe8fb19SBen Gras if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
4132fe8fb19SBen Gras buf = (int32_t *)(void *)rstrm->out_finger;
4142fe8fb19SBen Gras rstrm->out_finger += len;
4152fe8fb19SBen Gras }
4162fe8fb19SBen Gras break;
4172fe8fb19SBen Gras
4182fe8fb19SBen Gras case XDR_DECODE:
4192fe8fb19SBen Gras if ((len <= (u_int)rstrm->fbtbc) &&
4202fe8fb19SBen Gras ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
4212fe8fb19SBen Gras buf = (int32_t *)(void *)rstrm->in_finger;
4222fe8fb19SBen Gras rstrm->fbtbc -= len;
4232fe8fb19SBen Gras rstrm->in_finger += len;
4242fe8fb19SBen Gras }
4252fe8fb19SBen Gras break;
4262fe8fb19SBen Gras
4272fe8fb19SBen Gras case XDR_FREE:
4282fe8fb19SBen Gras break;
4292fe8fb19SBen Gras }
4302fe8fb19SBen Gras return (buf);
4312fe8fb19SBen Gras }
4322fe8fb19SBen Gras
4332fe8fb19SBen Gras static void
xdrrec_destroy(XDR * xdrs)434f14fb602SLionel Sambuc xdrrec_destroy(XDR *xdrs)
4352fe8fb19SBen Gras {
4362fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
4372fe8fb19SBen Gras
4382fe8fb19SBen Gras mem_free(rstrm->out_base, rstrm->sendsize);
4392fe8fb19SBen Gras mem_free(rstrm->in_base, rstrm->recvsize);
4402fe8fb19SBen Gras mem_free(rstrm, sizeof(RECSTREAM));
4412fe8fb19SBen Gras }
4422fe8fb19SBen Gras
4432fe8fb19SBen Gras
4442fe8fb19SBen Gras /*
4452fe8fb19SBen Gras * Exported routines to manage xdr records
4462fe8fb19SBen Gras */
4472fe8fb19SBen Gras
4482fe8fb19SBen Gras /*
4492fe8fb19SBen Gras * Before reading (deserializing from the stream, one should always call
4502fe8fb19SBen Gras * this procedure to guarantee proper record alignment.
4512fe8fb19SBen Gras */
4522fe8fb19SBen Gras bool_t
xdrrec_skiprecord(XDR * xdrs)453f14fb602SLionel Sambuc xdrrec_skiprecord(XDR *xdrs)
4542fe8fb19SBen Gras {
4552fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
4562fe8fb19SBen Gras enum xprt_stat xstat;
4572fe8fb19SBen Gras
4582fe8fb19SBen Gras if (rstrm->nonblock) {
4592fe8fb19SBen Gras if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
4602fe8fb19SBen Gras rstrm->fbtbc = 0;
4612fe8fb19SBen Gras return TRUE;
4622fe8fb19SBen Gras }
4632fe8fb19SBen Gras if (rstrm->in_finger == rstrm->in_boundry &&
4642fe8fb19SBen Gras xstat == XPRT_MOREREQS) {
4652fe8fb19SBen Gras rstrm->fbtbc = 0;
4662fe8fb19SBen Gras return TRUE;
4672fe8fb19SBen Gras }
4682fe8fb19SBen Gras return FALSE;
4692fe8fb19SBen Gras }
4702fe8fb19SBen Gras while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
4712fe8fb19SBen Gras if (! skip_input_bytes(rstrm, rstrm->fbtbc))
4722fe8fb19SBen Gras return (FALSE);
4732fe8fb19SBen Gras rstrm->fbtbc = 0;
4742fe8fb19SBen Gras if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
4752fe8fb19SBen Gras return (FALSE);
4762fe8fb19SBen Gras }
4772fe8fb19SBen Gras rstrm->last_frag = FALSE;
4782fe8fb19SBen Gras return (TRUE);
4792fe8fb19SBen Gras }
4802fe8fb19SBen Gras
4812fe8fb19SBen Gras /*
4822fe8fb19SBen Gras * Look ahead fuction.
4832fe8fb19SBen Gras * Returns TRUE iff there is no more input in the buffer
4842fe8fb19SBen Gras * after consuming the rest of the current record.
4852fe8fb19SBen Gras */
4862fe8fb19SBen Gras bool_t
xdrrec_eof(XDR * xdrs)487f14fb602SLionel Sambuc xdrrec_eof(XDR *xdrs)
4882fe8fb19SBen Gras {
4892fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
4902fe8fb19SBen Gras
4912fe8fb19SBen Gras while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
4922fe8fb19SBen Gras if (!skip_input_bytes(rstrm, rstrm->fbtbc))
4932fe8fb19SBen Gras return (TRUE);
4942fe8fb19SBen Gras rstrm->fbtbc = 0;
4952fe8fb19SBen Gras if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
4962fe8fb19SBen Gras return (TRUE);
4972fe8fb19SBen Gras }
4982fe8fb19SBen Gras if (rstrm->in_finger == rstrm->in_boundry)
4992fe8fb19SBen Gras return (TRUE);
5002fe8fb19SBen Gras return (FALSE);
5012fe8fb19SBen Gras }
5022fe8fb19SBen Gras
5032fe8fb19SBen Gras /*
5042fe8fb19SBen Gras * The client must tell the package when an end-of-record has occurred.
5052fe8fb19SBen Gras * The second paraemters tells whether the record should be flushed to the
5062fe8fb19SBen Gras * (output) tcp stream. (This let's the package support batched or
5072fe8fb19SBen Gras * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
5082fe8fb19SBen Gras */
5092fe8fb19SBen Gras bool_t
xdrrec_endofrecord(XDR * xdrs,int sendnow)510*0a6a1f1dSLionel Sambuc xdrrec_endofrecord(XDR *xdrs, int sendnow)
5112fe8fb19SBen Gras {
5122fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
5132fe8fb19SBen Gras u_long len; /* fragment length */
5142fe8fb19SBen Gras
5152fe8fb19SBen Gras if (sendnow || rstrm->frag_sent ||
516f14fb602SLionel Sambuc ((u_long)rstrm->out_finger + sizeof(uint32_t) >=
5172fe8fb19SBen Gras (u_long)rstrm->out_boundry)) {
5182fe8fb19SBen Gras rstrm->frag_sent = FALSE;
5192fe8fb19SBen Gras return (flush_out(rstrm, TRUE));
5202fe8fb19SBen Gras }
5212fe8fb19SBen Gras len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
522f14fb602SLionel Sambuc sizeof(uint32_t);
523f14fb602SLionel Sambuc *(rstrm->frag_header) = htonl((uint32_t)len | LAST_FRAG);
524f14fb602SLionel Sambuc rstrm->frag_header = (uint32_t *)(void *)rstrm->out_finger;
525f14fb602SLionel Sambuc rstrm->out_finger += sizeof(uint32_t);
5262fe8fb19SBen Gras return (TRUE);
5272fe8fb19SBen Gras }
5282fe8fb19SBen Gras
5292fe8fb19SBen Gras /*
5302fe8fb19SBen Gras * Fill the stream buffer with a record for a non-blocking connection.
5312fe8fb19SBen Gras * Return true if a record is available in the buffer, false if not.
5322fe8fb19SBen Gras */
5332fe8fb19SBen Gras bool_t
__xdrrec_getrec(XDR * xdrs,enum xprt_stat * statp,bool_t expectdata)534f14fb602SLionel Sambuc __xdrrec_getrec(XDR *xdrs, enum xprt_stat *statp, bool_t expectdata)
5352fe8fb19SBen Gras {
5362fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
5372fe8fb19SBen Gras ssize_t n;
5382fe8fb19SBen Gras int fraglen;
5392fe8fb19SBen Gras
5402fe8fb19SBen Gras if (!rstrm->in_haveheader) {
5412fe8fb19SBen Gras n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
5422fe8fb19SBen Gras (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
5432fe8fb19SBen Gras if (n == 0) {
5442fe8fb19SBen Gras *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
5452fe8fb19SBen Gras return FALSE;
5462fe8fb19SBen Gras }
5472fe8fb19SBen Gras if (n < 0) {
5482fe8fb19SBen Gras *statp = XPRT_DIED;
5492fe8fb19SBen Gras return FALSE;
5502fe8fb19SBen Gras }
5512fe8fb19SBen Gras rstrm->in_hdrp += n;
552f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, n));
553f14fb602SLionel Sambuc rstrm->in_hdrlen += (int)n;
5542fe8fb19SBen Gras if (rstrm->in_hdrlen < (int)sizeof(rstrm->in_header)) {
5552fe8fb19SBen Gras *statp = XPRT_MOREREQS;
5562fe8fb19SBen Gras return FALSE;
5572fe8fb19SBen Gras }
5582fe8fb19SBen Gras rstrm->in_header = ntohl(rstrm->in_header);
5592fe8fb19SBen Gras fraglen = (int)(rstrm->in_header & ~LAST_FRAG);
5602fe8fb19SBen Gras if (fraglen == 0 || fraglen > rstrm->in_maxrec ||
5612fe8fb19SBen Gras (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) {
5622fe8fb19SBen Gras *statp = XPRT_DIED;
5632fe8fb19SBen Gras return FALSE;
5642fe8fb19SBen Gras }
5652fe8fb19SBen Gras rstrm->in_reclen += fraglen;
5662fe8fb19SBen Gras if ((u_int)rstrm->in_reclen > rstrm->recvsize) {
5672fe8fb19SBen Gras if (!realloc_stream(rstrm, rstrm->in_reclen)) {
5682fe8fb19SBen Gras *statp = XPRT_DIED;
5692fe8fb19SBen Gras return FALSE;
5702fe8fb19SBen Gras }
5712fe8fb19SBen Gras }
5722fe8fb19SBen Gras if (rstrm->in_header & LAST_FRAG) {
5732fe8fb19SBen Gras rstrm->in_header &= ~LAST_FRAG;
5742fe8fb19SBen Gras rstrm->last_frag = TRUE;
5752fe8fb19SBen Gras }
5762fe8fb19SBen Gras }
5772fe8fb19SBen Gras
5782fe8fb19SBen Gras n = rstrm->readit(rstrm->tcp_handle,
5792fe8fb19SBen Gras rstrm->in_base + rstrm->in_received,
5802fe8fb19SBen Gras (rstrm->in_reclen - rstrm->in_received));
5812fe8fb19SBen Gras
5822fe8fb19SBen Gras if (n < 0) {
5832fe8fb19SBen Gras *statp = XPRT_DIED;
5842fe8fb19SBen Gras return FALSE;
5852fe8fb19SBen Gras }
5862fe8fb19SBen Gras
5872fe8fb19SBen Gras if (n == 0) {
5882fe8fb19SBen Gras *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
5892fe8fb19SBen Gras return FALSE;
5902fe8fb19SBen Gras }
5912fe8fb19SBen Gras
592f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, n));
593f14fb602SLionel Sambuc rstrm->in_received += (int)n;
5942fe8fb19SBen Gras
5952fe8fb19SBen Gras if (rstrm->in_received == rstrm->in_reclen) {
5962fe8fb19SBen Gras rstrm->in_haveheader = FALSE;
5972fe8fb19SBen Gras rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
5982fe8fb19SBen Gras rstrm->in_hdrlen = 0;
5992fe8fb19SBen Gras if (rstrm->last_frag) {
6002fe8fb19SBen Gras rstrm->fbtbc = rstrm->in_reclen;
6012fe8fb19SBen Gras rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
6022fe8fb19SBen Gras rstrm->in_finger = rstrm->in_base;
6032fe8fb19SBen Gras rstrm->in_reclen = rstrm->in_received = 0;
6042fe8fb19SBen Gras *statp = XPRT_MOREREQS;
6052fe8fb19SBen Gras return TRUE;
6062fe8fb19SBen Gras }
6072fe8fb19SBen Gras }
6082fe8fb19SBen Gras
6092fe8fb19SBen Gras *statp = XPRT_MOREREQS;
6102fe8fb19SBen Gras return FALSE;
6112fe8fb19SBen Gras }
6122fe8fb19SBen Gras
6132fe8fb19SBen Gras bool_t
__xdrrec_setnonblock(XDR * xdrs,int maxrec)614f14fb602SLionel Sambuc __xdrrec_setnonblock(XDR *xdrs, int maxrec)
6152fe8fb19SBen Gras {
6162fe8fb19SBen Gras RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
6172fe8fb19SBen Gras
6182fe8fb19SBen Gras rstrm->nonblock = TRUE;
6192fe8fb19SBen Gras if (maxrec == 0)
6202fe8fb19SBen Gras maxrec = rstrm->recvsize;
6212fe8fb19SBen Gras rstrm->in_maxrec = maxrec;
6222fe8fb19SBen Gras return TRUE;
6232fe8fb19SBen Gras }
6242fe8fb19SBen Gras
6252fe8fb19SBen Gras
6262fe8fb19SBen Gras /*
6272fe8fb19SBen Gras * Internal useful routines
6282fe8fb19SBen Gras */
6292fe8fb19SBen Gras static bool_t
flush_out(RECSTREAM * rstrm,bool_t eor)630f14fb602SLionel Sambuc flush_out(RECSTREAM *rstrm, bool_t eor)
6312fe8fb19SBen Gras {
632f14fb602SLionel Sambuc uint32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
633f14fb602SLionel Sambuc uint32_t len = (uint32_t)((u_long)(rstrm->out_finger) -
634f14fb602SLionel Sambuc (u_long)(rstrm->frag_header) - sizeof(uint32_t));
6352fe8fb19SBen Gras
6362fe8fb19SBen Gras *(rstrm->frag_header) = htonl(len | eormask);
637f14fb602SLionel Sambuc len = (uint32_t)((u_long)(rstrm->out_finger) -
6382fe8fb19SBen Gras (u_long)(rstrm->out_base));
6392fe8fb19SBen Gras if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
6402fe8fb19SBen Gras != (int)len)
6412fe8fb19SBen Gras return (FALSE);
642f14fb602SLionel Sambuc rstrm->frag_header = (uint32_t *)(void *)rstrm->out_base;
643f14fb602SLionel Sambuc rstrm->out_finger = (char *)rstrm->out_base + sizeof(uint32_t);
6442fe8fb19SBen Gras return (TRUE);
6452fe8fb19SBen Gras }
6462fe8fb19SBen Gras
6472fe8fb19SBen Gras static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf(RECSTREAM * rstrm)648f14fb602SLionel Sambuc fill_input_buf(RECSTREAM *rstrm)
6492fe8fb19SBen Gras {
6502fe8fb19SBen Gras char *where;
651f14fb602SLionel Sambuc uint32_t i;
6522fe8fb19SBen Gras int len;
6532fe8fb19SBen Gras
6542fe8fb19SBen Gras if (rstrm->nonblock)
6552fe8fb19SBen Gras return FALSE;
6562fe8fb19SBen Gras where = rstrm->in_base;
657f14fb602SLionel Sambuc i = (uint32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
6582fe8fb19SBen Gras where += i;
659f14fb602SLionel Sambuc len = (uint32_t)(rstrm->in_size - i);
6602fe8fb19SBen Gras if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
6612fe8fb19SBen Gras return (FALSE);
6622fe8fb19SBen Gras rstrm->in_finger = where;
6632fe8fb19SBen Gras where += len;
6642fe8fb19SBen Gras rstrm->in_boundry = where;
6652fe8fb19SBen Gras return (TRUE);
6662fe8fb19SBen Gras }
6672fe8fb19SBen Gras
6682fe8fb19SBen Gras static bool_t /* knows nothing about records! Only about input buffers */
get_input_bytes(RECSTREAM * rstrm,char * addr,u_int len)669f14fb602SLionel Sambuc get_input_bytes(RECSTREAM *rstrm, char *addr, u_int len)
6702fe8fb19SBen Gras {
6712fe8fb19SBen Gras u_int current;
6722fe8fb19SBen Gras
6732fe8fb19SBen Gras if (rstrm->nonblock) {
6742fe8fb19SBen Gras if (len > ((uintptr_t)rstrm->in_boundry - (uintptr_t)rstrm->in_finger))
6752fe8fb19SBen Gras return FALSE;
6762fe8fb19SBen Gras memcpy(addr, rstrm->in_finger, len);
6772fe8fb19SBen Gras rstrm->in_finger += len;
6782fe8fb19SBen Gras return TRUE;
6792fe8fb19SBen Gras }
6802fe8fb19SBen Gras
6812fe8fb19SBen Gras while (len > 0) {
682f14fb602SLionel Sambuc uintptr_t d = ((uintptr_t)rstrm->in_boundry -
6832fe8fb19SBen Gras (uintptr_t)rstrm->in_finger);
684f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(u_int, d));
685f14fb602SLionel Sambuc current = (u_int)d;
6862fe8fb19SBen Gras if (current == 0) {
6872fe8fb19SBen Gras if (! fill_input_buf(rstrm))
6882fe8fb19SBen Gras return (FALSE);
6892fe8fb19SBen Gras continue;
6902fe8fb19SBen Gras }
6912fe8fb19SBen Gras current = (len < current) ? len : current;
6922fe8fb19SBen Gras memmove(addr, rstrm->in_finger, current);
6932fe8fb19SBen Gras rstrm->in_finger += current;
6942fe8fb19SBen Gras addr += current;
6952fe8fb19SBen Gras len -= current;
6962fe8fb19SBen Gras }
6972fe8fb19SBen Gras return (TRUE);
6982fe8fb19SBen Gras }
6992fe8fb19SBen Gras
7002fe8fb19SBen Gras static bool_t /* next two bytes of the input stream are treated as a header */
set_input_fragment(RECSTREAM * rstrm)701f14fb602SLionel Sambuc set_input_fragment(RECSTREAM *rstrm)
7022fe8fb19SBen Gras {
703f14fb602SLionel Sambuc uint32_t header;
7042fe8fb19SBen Gras
7052fe8fb19SBen Gras if (rstrm->nonblock)
7062fe8fb19SBen Gras return FALSE;
707f14fb602SLionel Sambuc if (! get_input_bytes(rstrm, (char *)(void *)&header,
708f14fb602SLionel Sambuc (u_int)sizeof(header)))
7092fe8fb19SBen Gras return (FALSE);
7102fe8fb19SBen Gras header = ntohl(header);
7112fe8fb19SBen Gras rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
7122fe8fb19SBen Gras /*
7132fe8fb19SBen Gras * Sanity check. Try not to accept wildly incorrect
7142fe8fb19SBen Gras * record sizes. Unfortunately, the only record size
7152fe8fb19SBen Gras * we can positively identify as being 'wildly incorrect'
7162fe8fb19SBen Gras * is zero. Ridiculously large record sizes may look wrong,
7172fe8fb19SBen Gras * but we don't have any way to be certain that they aren't
7182fe8fb19SBen Gras * what the client actually intended to send us.
7192fe8fb19SBen Gras */
7202fe8fb19SBen Gras if (header == 0)
7212fe8fb19SBen Gras return(FALSE);
7222fe8fb19SBen Gras rstrm->fbtbc = header & (~LAST_FRAG);
7232fe8fb19SBen Gras return (TRUE);
7242fe8fb19SBen Gras }
7252fe8fb19SBen Gras
7262fe8fb19SBen Gras static bool_t /* consumes input bytes; knows nothing about records! */
skip_input_bytes(RECSTREAM * rstrm,long cnt)727f14fb602SLionel Sambuc skip_input_bytes(RECSTREAM *rstrm, long cnt)
7282fe8fb19SBen Gras {
729f14fb602SLionel Sambuc uint32_t current;
7302fe8fb19SBen Gras
7312fe8fb19SBen Gras while (cnt > 0) {
732f14fb602SLionel Sambuc current = (uint32_t)((long)rstrm->in_boundry -
7332fe8fb19SBen Gras (long)rstrm->in_finger);
7342fe8fb19SBen Gras if (current == 0) {
7352fe8fb19SBen Gras if (! fill_input_buf(rstrm))
7362fe8fb19SBen Gras return (FALSE);
7372fe8fb19SBen Gras continue;
7382fe8fb19SBen Gras }
739f14fb602SLionel Sambuc current = ((uint32_t)cnt < current) ? (uint32_t)cnt : current;
7402fe8fb19SBen Gras rstrm->in_finger += current;
7412fe8fb19SBen Gras cnt -= current;
7422fe8fb19SBen Gras }
7432fe8fb19SBen Gras return (TRUE);
7442fe8fb19SBen Gras }
7452fe8fb19SBen Gras
7462fe8fb19SBen Gras static u_int
fix_buf_size(u_int s)747f14fb602SLionel Sambuc fix_buf_size(u_int s)
7482fe8fb19SBen Gras {
7492fe8fb19SBen Gras
7502fe8fb19SBen Gras if (s < 100)
7512fe8fb19SBen Gras s = 4000;
7522fe8fb19SBen Gras return (RNDUP(s));
7532fe8fb19SBen Gras }
7542fe8fb19SBen Gras
7552fe8fb19SBen Gras /*
7562fe8fb19SBen Gras * Reallocate the input buffer for a non-block stream.
7572fe8fb19SBen Gras */
7582fe8fb19SBen Gras static bool_t
realloc_stream(RECSTREAM * rstrm,int size)759f14fb602SLionel Sambuc realloc_stream(RECSTREAM *rstrm, int size)
7602fe8fb19SBen Gras {
7612fe8fb19SBen Gras ptrdiff_t diff;
7622fe8fb19SBen Gras char *buf;
7632fe8fb19SBen Gras
7642fe8fb19SBen Gras if ((u_int)size > rstrm->recvsize) {
7652fe8fb19SBen Gras buf = realloc(rstrm->in_base, (size_t)size);
7662fe8fb19SBen Gras if (buf == NULL)
7672fe8fb19SBen Gras return FALSE;
7682fe8fb19SBen Gras diff = buf - rstrm->in_base;
7692fe8fb19SBen Gras rstrm->in_finger += diff;
7702fe8fb19SBen Gras rstrm->in_base = buf;
7712fe8fb19SBen Gras rstrm->in_boundry = buf + size;
7722fe8fb19SBen Gras rstrm->recvsize = size;
7732fe8fb19SBen Gras rstrm->in_size = size;
7742fe8fb19SBen Gras }
7752fe8fb19SBen Gras
7762fe8fb19SBen Gras return TRUE;
7772fe8fb19SBen Gras }
778