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 /*
37eae561b3SGarrett Wollman * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
38eae561b3SGarrett Wollman * layer above tcp (for rpc's use).
39eae561b3SGarrett Wollman *
40eae561b3SGarrett Wollman * These routines interface XDRSTREAMS to a tcp/ip connection.
41eae561b3SGarrett Wollman * There is a record marking layer between the xdr stream
42eae561b3SGarrett Wollman * and the tcp transport level. A record is composed on one or more
43eae561b3SGarrett Wollman * record fragments. A record fragment is a thirty-two bit header followed
44eae561b3SGarrett Wollman * by n bytes of data, where n is contained in the header. The header
45eae561b3SGarrett Wollman * is represented as a htonl(u_long). Thegh order bit encodes
46eae561b3SGarrett Wollman * whether or not the fragment is the last fragment of the record
47eae561b3SGarrett Wollman * (1 => fragment is last, 0 => more fragments to follow.
48eae561b3SGarrett Wollman * The other 31 bits encode the byte length of the fragment.
49eae561b3SGarrett Wollman */
50eae561b3SGarrett Wollman
518360efbdSAlfred Perlstein #include "namespace.h"
528360efbdSAlfred Perlstein #include <sys/types.h>
538360efbdSAlfred Perlstein
548360efbdSAlfred Perlstein #include <netinet/in.h>
558360efbdSAlfred Perlstein
568360efbdSAlfred Perlstein #include <err.h>
57eae561b3SGarrett Wollman #include <stdio.h>
58eae561b3SGarrett Wollman #include <stdlib.h>
5929285d6cSPoul-Henning Kamp #include <string.h>
608360efbdSAlfred Perlstein
61eae561b3SGarrett Wollman #include <rpc/types.h>
62eae561b3SGarrett Wollman #include <rpc/xdr.h>
6308497c02SMartin Blapp #include <rpc/auth.h>
6408497c02SMartin Blapp #include <rpc/svc.h>
6508497c02SMartin Blapp #include <rpc/clnt.h>
6608497c02SMartin Blapp #include <sys/stddef.h>
678360efbdSAlfred Perlstein #include "un-namespace.h"
682bbd7cf8SJacques Vidrine #include "rpc_com.h"
69eae561b3SGarrett Wollman
70c05ac53bSDavid E. O'Brien static bool_t xdrrec_getlong(XDR *, long *);
71c05ac53bSDavid E. O'Brien static bool_t xdrrec_putlong(XDR *, const long *);
72c05ac53bSDavid E. O'Brien static bool_t xdrrec_getbytes(XDR *, char *, u_int);
73eae561b3SGarrett Wollman
74c05ac53bSDavid E. O'Brien static bool_t xdrrec_putbytes(XDR *, const char *, u_int);
75c05ac53bSDavid E. O'Brien static u_int xdrrec_getpos(XDR *);
76c05ac53bSDavid E. O'Brien static bool_t xdrrec_setpos(XDR *, u_int);
77c05ac53bSDavid E. O'Brien static int32_t *xdrrec_inline(XDR *, u_int);
78c05ac53bSDavid E. O'Brien static void xdrrec_destroy(XDR *);
79eae561b3SGarrett Wollman
808360efbdSAlfred Perlstein static const struct xdr_ops xdrrec_ops = {
81eae561b3SGarrett Wollman xdrrec_getlong,
82eae561b3SGarrett Wollman xdrrec_putlong,
83eae561b3SGarrett Wollman xdrrec_getbytes,
84eae561b3SGarrett Wollman xdrrec_putbytes,
85eae561b3SGarrett Wollman xdrrec_getpos,
86eae561b3SGarrett Wollman xdrrec_setpos,
87eae561b3SGarrett Wollman xdrrec_inline,
88eae561b3SGarrett Wollman xdrrec_destroy
89eae561b3SGarrett Wollman };
90eae561b3SGarrett Wollman
91eae561b3SGarrett Wollman /*
92eae561b3SGarrett Wollman * A record is composed of one or more record fragments.
9308497c02SMartin Blapp * A record fragment is a four-byte header followed by zero to
94eae561b3SGarrett Wollman * 2**32-1 bytes. The header is treated as a long unsigned and is
95eae561b3SGarrett Wollman * encode/decoded to the network via htonl/ntohl. The low order 31 bits
96eae561b3SGarrett Wollman * are a byte count of the fragment. The highest order bit is a boolean:
97eae561b3SGarrett Wollman * 1 => this fragment is the last fragment of the record,
98eae561b3SGarrett Wollman * 0 => this fragment is followed by more fragment(s).
99eae561b3SGarrett Wollman *
100eae561b3SGarrett Wollman * The fragment/record machinery is not general; it is constructed to
101eae561b3SGarrett Wollman * meet the needs of xdr and rpc based on tcp.
102eae561b3SGarrett Wollman */
103eae561b3SGarrett Wollman
1047a22215cSEitan Adler #define LAST_FRAG ((u_int32_t)(1U << 31))
105eae561b3SGarrett Wollman
106eae561b3SGarrett Wollman typedef struct rec_strm {
1078360efbdSAlfred Perlstein char *tcp_handle;
108eae561b3SGarrett Wollman /*
109eae561b3SGarrett Wollman * out-goung bits
110eae561b3SGarrett Wollman */
111f249dbccSDag-Erling Smørgrav int (*writeit)(void *, void *, int);
1128360efbdSAlfred Perlstein char *out_base; /* output buffer (points to frag header) */
1138360efbdSAlfred Perlstein char *out_finger; /* next output position */
1148360efbdSAlfred Perlstein char *out_boundry; /* data cannot up to this address */
11585604f70SGordon Bergling u_int32_t *frag_header; /* beginning of current fragment */
116eae561b3SGarrett Wollman bool_t frag_sent; /* true if buffer sent in middle of record */
117eae561b3SGarrett Wollman /*
118eae561b3SGarrett Wollman * in-coming bits
119eae561b3SGarrett Wollman */
120f249dbccSDag-Erling Smørgrav int (*readit)(void *, void *, int);
121eae561b3SGarrett Wollman u_long in_size; /* fixed size of the input buffer */
1228360efbdSAlfred Perlstein char *in_base;
1238360efbdSAlfred Perlstein char *in_finger; /* location of next byte to be had */
1248360efbdSAlfred Perlstein char *in_boundry; /* can read up to this location */
125eae561b3SGarrett Wollman long fbtbc; /* fragment bytes to be consumed */
126eae561b3SGarrett Wollman bool_t last_frag;
127eae561b3SGarrett Wollman u_int sendsize;
128eae561b3SGarrett Wollman u_int recvsize;
12908497c02SMartin Blapp
13008497c02SMartin Blapp bool_t nonblock;
13108497c02SMartin Blapp bool_t in_haveheader;
13208497c02SMartin Blapp u_int32_t in_header;
13308497c02SMartin Blapp char *in_hdrp;
13408497c02SMartin Blapp int in_hdrlen;
13508497c02SMartin Blapp int in_reclen;
13608497c02SMartin Blapp int in_received;
13708497c02SMartin Blapp int in_maxrec;
138eae561b3SGarrett Wollman } RECSTREAM;
139eae561b3SGarrett Wollman
140c05ac53bSDavid E. O'Brien static u_int fix_buf_size(u_int);
141c05ac53bSDavid E. O'Brien static bool_t flush_out(RECSTREAM *, bool_t);
142c05ac53bSDavid E. O'Brien static bool_t fill_input_buf(RECSTREAM *);
143c05ac53bSDavid E. O'Brien static bool_t get_input_bytes(RECSTREAM *, char *, int);
144c05ac53bSDavid E. O'Brien static bool_t set_input_fragment(RECSTREAM *);
145c05ac53bSDavid E. O'Brien static bool_t skip_input_bytes(RECSTREAM *, long);
14608497c02SMartin Blapp static bool_t realloc_stream(RECSTREAM *, int);
1478360efbdSAlfred Perlstein
148eae561b3SGarrett Wollman
149eae561b3SGarrett Wollman /*
150eae561b3SGarrett Wollman * Create an xdr handle for xdrrec
151eae561b3SGarrett Wollman * xdrrec_create fills in xdrs. Sendsize and recvsize are
152eae561b3SGarrett Wollman * send and recv buffer sizes (0 => use default).
153eae561b3SGarrett Wollman * tcp_handle is an opaque handle that is passed as the first parameter to
154eae561b3SGarrett Wollman * the procedures readit and writeit. Readit and writeit are read and
155eae561b3SGarrett Wollman * write respectively. They are like the system
156eae561b3SGarrett Wollman * calls expect that they take an opaque handle rather than an fd.
157eae561b3SGarrett Wollman */
158eae561b3SGarrett Wollman void
xdrrec_create(XDR * xdrs,u_int sendsize,u_int recvsize,void * tcp_handle,int (* readit)(void *,void *,int),int (* writeit)(void *,void *,int))159d660d38dSCraig Rodrigues xdrrec_create(XDR *xdrs, u_int sendsize, u_int recvsize, void *tcp_handle,
160d660d38dSCraig Rodrigues int (*readit)(void *, void *, int), int (*writeit)(void *, void *, int))
161d660d38dSCraig Rodrigues /*
162d660d38dSCraig Rodrigues * XDR *xdrs;
163d660d38dSCraig Rodrigues * u_int sendsize;
164d660d38dSCraig Rodrigues * u_int recvsize;
165d660d38dSCraig Rodrigues * void *tcp_handle;
166d660d38dSCraig Rodrigues * // like read, but pass it a tcp_handle, not sock
167d660d38dSCraig Rodrigues * int (*readit)(void *, void *, int);
168d660d38dSCraig Rodrigues * // like write, but pass it a tcp_handle, not sock
169d660d38dSCraig Rodrigues * int (*writeit)(void *, void *, int);
170d660d38dSCraig Rodrigues */
171eae561b3SGarrett Wollman {
1728360efbdSAlfred Perlstein RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
173eae561b3SGarrett Wollman
174eae561b3SGarrett Wollman if (rstrm == NULL) {
1758360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory");
176eae561b3SGarrett Wollman /*
177eae561b3SGarrett Wollman * This is bad. Should rework xdrrec_create to
178eae561b3SGarrett Wollman * return a handle, and in this case return NULL
179eae561b3SGarrett Wollman */
180eae561b3SGarrett Wollman return;
181eae561b3SGarrett Wollman }
182eae561b3SGarrett Wollman rstrm->sendsize = sendsize = fix_buf_size(sendsize);
18308497c02SMartin Blapp rstrm->out_base = mem_alloc(rstrm->sendsize);
18408497c02SMartin Blapp if (rstrm->out_base == NULL) {
1858360efbdSAlfred Perlstein warnx("xdrrec_create: out of memory");
18608497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM));
187eae561b3SGarrett Wollman return;
188eae561b3SGarrett Wollman }
18908497c02SMartin Blapp rstrm->recvsize = recvsize = fix_buf_size(recvsize);
19008497c02SMartin Blapp rstrm->in_base = mem_alloc(recvsize);
19108497c02SMartin Blapp if (rstrm->in_base == NULL) {
19208497c02SMartin Blapp warnx("xdrrec_create: out of memory");
19308497c02SMartin Blapp mem_free(rstrm->out_base, sendsize);
19408497c02SMartin Blapp mem_free(rstrm, sizeof(RECSTREAM));
19508497c02SMartin Blapp return;
19608497c02SMartin Blapp }
197eae561b3SGarrett Wollman /*
198eae561b3SGarrett Wollman * now the rest ...
199eae561b3SGarrett Wollman */
200eae561b3SGarrett Wollman xdrs->x_ops = &xdrrec_ops;
2018360efbdSAlfred Perlstein xdrs->x_private = rstrm;
202eae561b3SGarrett Wollman rstrm->tcp_handle = tcp_handle;
203eae561b3SGarrett Wollman rstrm->readit = readit;
204eae561b3SGarrett Wollman rstrm->writeit = writeit;
205eae561b3SGarrett Wollman rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
2068360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
2071ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t);
208eae561b3SGarrett Wollman rstrm->out_boundry += sendsize;
209eae561b3SGarrett Wollman rstrm->frag_sent = FALSE;
210eae561b3SGarrett Wollman rstrm->in_size = recvsize;
211eae561b3SGarrett Wollman rstrm->in_boundry = rstrm->in_base;
212eae561b3SGarrett Wollman rstrm->in_finger = (rstrm->in_boundry += recvsize);
213eae561b3SGarrett Wollman rstrm->fbtbc = 0;
214eae561b3SGarrett Wollman rstrm->last_frag = TRUE;
21508497c02SMartin Blapp rstrm->in_haveheader = FALSE;
21608497c02SMartin Blapp rstrm->in_hdrlen = 0;
21708497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
21808497c02SMartin Blapp rstrm->nonblock = FALSE;
21908497c02SMartin Blapp rstrm->in_reclen = 0;
22008497c02SMartin Blapp rstrm->in_received = 0;
221eae561b3SGarrett Wollman }
222eae561b3SGarrett Wollman
223eae561b3SGarrett Wollman
224eae561b3SGarrett Wollman /*
225577a721dSGordon Bergling * The routines defined below are the xdr ops which will go into the
226eae561b3SGarrett Wollman * xdr handle filled in by xdrrec_create.
227eae561b3SGarrett Wollman */
228eae561b3SGarrett Wollman
229eae561b3SGarrett Wollman static bool_t
xdrrec_getlong(XDR * xdrs,long * lp)230d660d38dSCraig Rodrigues xdrrec_getlong(XDR *xdrs, long *lp)
231eae561b3SGarrett Wollman {
2328360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2338360efbdSAlfred Perlstein int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
2341ad08a09SPeter Wemm int32_t mylong;
235eae561b3SGarrett Wollman
236eae561b3SGarrett Wollman /* first try the inline, fast case */
2371ad08a09SPeter Wemm if ((rstrm->fbtbc >= sizeof(int32_t)) &&
2381ad08a09SPeter Wemm (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) {
2391ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)(*buflp));
2401ad08a09SPeter Wemm rstrm->fbtbc -= sizeof(int32_t);
2411ad08a09SPeter Wemm rstrm->in_finger += sizeof(int32_t);
242eae561b3SGarrett Wollman } else {
2438360efbdSAlfred Perlstein if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
2448360efbdSAlfred Perlstein sizeof(int32_t)))
245eae561b3SGarrett Wollman return (FALSE);
2461ad08a09SPeter Wemm *lp = (long)ntohl((u_int32_t)mylong);
247eae561b3SGarrett Wollman }
248eae561b3SGarrett Wollman return (TRUE);
249eae561b3SGarrett Wollman }
250eae561b3SGarrett Wollman
251eae561b3SGarrett Wollman static bool_t
xdrrec_putlong(XDR * xdrs,const long * lp)252d660d38dSCraig Rodrigues xdrrec_putlong(XDR *xdrs, const long *lp)
253eae561b3SGarrett Wollman {
2548360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2558360efbdSAlfred Perlstein int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
256eae561b3SGarrett Wollman
2571ad08a09SPeter Wemm if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
258eae561b3SGarrett Wollman /*
259eae561b3SGarrett Wollman * this case should almost never happen so the code is
260eae561b3SGarrett Wollman * inefficient
261eae561b3SGarrett Wollman */
2621ad08a09SPeter Wemm rstrm->out_finger -= sizeof(int32_t);
263eae561b3SGarrett Wollman rstrm->frag_sent = TRUE;
264eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE))
265eae561b3SGarrett Wollman return (FALSE);
2668360efbdSAlfred Perlstein dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
2671ad08a09SPeter Wemm rstrm->out_finger += sizeof(int32_t);
268eae561b3SGarrett Wollman }
2691ad08a09SPeter Wemm *dest_lp = (int32_t)htonl((u_int32_t)(*lp));
270eae561b3SGarrett Wollman return (TRUE);
271eae561b3SGarrett Wollman }
272eae561b3SGarrett Wollman
273eae561b3SGarrett Wollman static bool_t /* must manage buffers, fragments, and records */
xdrrec_getbytes(XDR * xdrs,char * addr,u_int len)274d660d38dSCraig Rodrigues xdrrec_getbytes(XDR *xdrs, char *addr, u_int len)
275eae561b3SGarrett Wollman {
2768360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
2778360efbdSAlfred Perlstein int current;
278eae561b3SGarrett Wollman
279eae561b3SGarrett Wollman while (len > 0) {
2808360efbdSAlfred Perlstein current = (int)rstrm->fbtbc;
281eae561b3SGarrett Wollman if (current == 0) {
282eae561b3SGarrett Wollman if (rstrm->last_frag)
283eae561b3SGarrett Wollman return (FALSE);
284eae561b3SGarrett Wollman if (! set_input_fragment(rstrm))
285eae561b3SGarrett Wollman return (FALSE);
286eae561b3SGarrett Wollman continue;
287eae561b3SGarrett Wollman }
288eae561b3SGarrett Wollman current = (len < current) ? len : current;
289eae561b3SGarrett Wollman if (! get_input_bytes(rstrm, addr, current))
290eae561b3SGarrett Wollman return (FALSE);
291eae561b3SGarrett Wollman addr += current;
292eae561b3SGarrett Wollman rstrm->fbtbc -= current;
293eae561b3SGarrett Wollman len -= current;
294eae561b3SGarrett Wollman }
295eae561b3SGarrett Wollman return (TRUE);
296eae561b3SGarrett Wollman }
297eae561b3SGarrett Wollman
298eae561b3SGarrett Wollman static bool_t
xdrrec_putbytes(XDR * xdrs,const char * addr,u_int len)299d660d38dSCraig Rodrigues xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len)
300eae561b3SGarrett Wollman {
3018360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
3028360efbdSAlfred Perlstein size_t current;
303eae561b3SGarrett Wollman
304eae561b3SGarrett Wollman while (len > 0) {
3058360efbdSAlfred Perlstein current = (size_t)((u_long)rstrm->out_boundry -
3068360efbdSAlfred Perlstein (u_long)rstrm->out_finger);
307eae561b3SGarrett Wollman current = (len < current) ? len : current;
3088360efbdSAlfred Perlstein memmove(rstrm->out_finger, addr, current);
309eae561b3SGarrett Wollman rstrm->out_finger += current;
310eae561b3SGarrett Wollman addr += current;
311eae561b3SGarrett Wollman len -= current;
312eae561b3SGarrett Wollman if (rstrm->out_finger == rstrm->out_boundry) {
313eae561b3SGarrett Wollman rstrm->frag_sent = TRUE;
314eae561b3SGarrett Wollman if (! flush_out(rstrm, FALSE))
315eae561b3SGarrett Wollman return (FALSE);
316eae561b3SGarrett Wollman }
317eae561b3SGarrett Wollman }
318eae561b3SGarrett Wollman return (TRUE);
319eae561b3SGarrett Wollman }
320eae561b3SGarrett Wollman
321*7f39f03cSGleb Smirnoff /*
322*7f39f03cSGleb Smirnoff * XXX: xdrrec operates on a TCP stream and doesn't keep record of how many
323*7f39f03cSGleb Smirnoff * bytes were sent/received overall. Thus, the XDR_GETPOS() and XDR_SETPOS()
324*7f39f03cSGleb Smirnoff * can operate only within small internal buffer. So far, the limited set of
325*7f39f03cSGleb Smirnoff * consumers of this xdr are fine with that. It also seems that methods are
326*7f39f03cSGleb Smirnoff * never called in the XDR_DECODE mode.
327*7f39f03cSGleb Smirnoff */
328eae561b3SGarrett Wollman static u_int
xdrrec_getpos(XDR * xdrs)329d660d38dSCraig Rodrigues xdrrec_getpos(XDR *xdrs)
330eae561b3SGarrett Wollman {
3318360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
332*7f39f03cSGleb Smirnoff ptrdiff_t pos;
333eae561b3SGarrett Wollman
334eae561b3SGarrett Wollman switch (xdrs->x_op) {
335eae561b3SGarrett Wollman case XDR_ENCODE:
336*7f39f03cSGleb Smirnoff pos = rstrm->out_finger - rstrm->out_base;
337eae561b3SGarrett Wollman break;
338eae561b3SGarrett Wollman
339eae561b3SGarrett Wollman case XDR_DECODE:
340*7f39f03cSGleb Smirnoff pos = rstrm->in_finger - rstrm->in_base;
341eae561b3SGarrett Wollman break;
342eae561b3SGarrett Wollman
343*7f39f03cSGleb Smirnoff case XDR_FREE:
344*7f39f03cSGleb Smirnoff pos = -1;
345eae561b3SGarrett Wollman break;
346eae561b3SGarrett Wollman }
347eae561b3SGarrett Wollman return ((u_int) pos);
348eae561b3SGarrett Wollman }
349eae561b3SGarrett Wollman
350eae561b3SGarrett Wollman static bool_t
xdrrec_setpos(XDR * xdrs,u_int pos)351d660d38dSCraig Rodrigues xdrrec_setpos(XDR *xdrs, u_int pos)
352eae561b3SGarrett Wollman {
3538360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
354eae561b3SGarrett Wollman u_int currpos = xdrrec_getpos(xdrs);
355eae561b3SGarrett Wollman int delta = currpos - pos;
3568360efbdSAlfred Perlstein char *newpos;
357eae561b3SGarrett Wollman
358eae561b3SGarrett Wollman switch (xdrs->x_op) {
359eae561b3SGarrett Wollman case XDR_ENCODE:
360eae561b3SGarrett Wollman newpos = rstrm->out_finger - delta;
3618360efbdSAlfred Perlstein if ((newpos > (char *)(void *)(rstrm->frag_header)) &&
362eae561b3SGarrett Wollman (newpos < rstrm->out_boundry)) {
363eae561b3SGarrett Wollman rstrm->out_finger = newpos;
364eae561b3SGarrett Wollman return (TRUE);
365eae561b3SGarrett Wollman }
366eae561b3SGarrett Wollman break;
367eae561b3SGarrett Wollman
368eae561b3SGarrett Wollman case XDR_DECODE:
369eae561b3SGarrett Wollman newpos = rstrm->in_finger - delta;
370eae561b3SGarrett Wollman if ((delta < (int)(rstrm->fbtbc)) &&
371eae561b3SGarrett Wollman (newpos <= rstrm->in_boundry) &&
372eae561b3SGarrett Wollman (newpos >= rstrm->in_base)) {
373eae561b3SGarrett Wollman rstrm->in_finger = newpos;
374eae561b3SGarrett Wollman rstrm->fbtbc -= delta;
375eae561b3SGarrett Wollman return (TRUE);
376eae561b3SGarrett Wollman }
377eae561b3SGarrett Wollman break;
3788360efbdSAlfred Perlstein
3798360efbdSAlfred Perlstein case XDR_FREE:
3808360efbdSAlfred Perlstein break;
381eae561b3SGarrett Wollman }
382eae561b3SGarrett Wollman return (FALSE);
383eae561b3SGarrett Wollman }
384eae561b3SGarrett Wollman
3851ad08a09SPeter Wemm static int32_t *
xdrrec_inline(XDR * xdrs,u_int len)386d660d38dSCraig Rodrigues xdrrec_inline(XDR *xdrs, u_int len)
387eae561b3SGarrett Wollman {
3888360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
3891ad08a09SPeter Wemm int32_t *buf = NULL;
390eae561b3SGarrett Wollman
391eae561b3SGarrett Wollman switch (xdrs->x_op) {
392eae561b3SGarrett Wollman
393eae561b3SGarrett Wollman case XDR_ENCODE:
394eae561b3SGarrett Wollman if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
3958360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->out_finger;
396eae561b3SGarrett Wollman rstrm->out_finger += len;
397eae561b3SGarrett Wollman }
398eae561b3SGarrett Wollman break;
399eae561b3SGarrett Wollman
400eae561b3SGarrett Wollman case XDR_DECODE:
401eae561b3SGarrett Wollman if ((len <= rstrm->fbtbc) &&
402eae561b3SGarrett Wollman ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
4038360efbdSAlfred Perlstein buf = (int32_t *)(void *)rstrm->in_finger;
404eae561b3SGarrett Wollman rstrm->fbtbc -= len;
405eae561b3SGarrett Wollman rstrm->in_finger += len;
406eae561b3SGarrett Wollman }
407eae561b3SGarrett Wollman break;
4088360efbdSAlfred Perlstein
4098360efbdSAlfred Perlstein case XDR_FREE:
4108360efbdSAlfred Perlstein break;
411eae561b3SGarrett Wollman }
412eae561b3SGarrett Wollman return (buf);
413eae561b3SGarrett Wollman }
414eae561b3SGarrett Wollman
415eae561b3SGarrett Wollman static void
xdrrec_destroy(XDR * xdrs)416d660d38dSCraig Rodrigues xdrrec_destroy(XDR *xdrs)
417eae561b3SGarrett Wollman {
4188360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
419eae561b3SGarrett Wollman
42008497c02SMartin Blapp mem_free(rstrm->out_base, rstrm->sendsize);
42108497c02SMartin Blapp mem_free(rstrm->in_base, rstrm->recvsize);
4228360efbdSAlfred Perlstein mem_free(rstrm, sizeof(RECSTREAM));
423eae561b3SGarrett Wollman }
424eae561b3SGarrett Wollman
425eae561b3SGarrett Wollman
426eae561b3SGarrett Wollman /*
427eae561b3SGarrett Wollman * Exported routines to manage xdr records
428eae561b3SGarrett Wollman */
429eae561b3SGarrett Wollman
430eae561b3SGarrett Wollman /*
431eae561b3SGarrett Wollman * Before reading (deserializing from the stream, one should always call
432eae561b3SGarrett Wollman * this procedure to guarantee proper record alignment.
433eae561b3SGarrett Wollman */
434eae561b3SGarrett Wollman bool_t
xdrrec_skiprecord(XDR * xdrs)435d660d38dSCraig Rodrigues xdrrec_skiprecord(XDR *xdrs)
436eae561b3SGarrett Wollman {
4378360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
43808497c02SMartin Blapp enum xprt_stat xstat;
43908497c02SMartin Blapp
44008497c02SMartin Blapp if (rstrm->nonblock) {
44108497c02SMartin Blapp if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
44208497c02SMartin Blapp rstrm->fbtbc = 0;
44308497c02SMartin Blapp return TRUE;
44408497c02SMartin Blapp }
44508497c02SMartin Blapp if (rstrm->in_finger == rstrm->in_boundry &&
44608497c02SMartin Blapp xstat == XPRT_MOREREQS) {
44708497c02SMartin Blapp rstrm->fbtbc = 0;
44808497c02SMartin Blapp return TRUE;
44908497c02SMartin Blapp }
45008497c02SMartin Blapp return FALSE;
45108497c02SMartin Blapp }
452eae561b3SGarrett Wollman
453eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
454eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc))
455eae561b3SGarrett Wollman return (FALSE);
456eae561b3SGarrett Wollman rstrm->fbtbc = 0;
457eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
458eae561b3SGarrett Wollman return (FALSE);
459eae561b3SGarrett Wollman }
460eae561b3SGarrett Wollman rstrm->last_frag = FALSE;
461eae561b3SGarrett Wollman return (TRUE);
462eae561b3SGarrett Wollman }
463eae561b3SGarrett Wollman
464eae561b3SGarrett Wollman /*
4658360efbdSAlfred Perlstein * Look ahead function.
466eae561b3SGarrett Wollman * Returns TRUE iff there is no more input in the buffer
467eae561b3SGarrett Wollman * after consuming the rest of the current record.
468eae561b3SGarrett Wollman */
469eae561b3SGarrett Wollman bool_t
xdrrec_eof(XDR * xdrs)470d660d38dSCraig Rodrigues xdrrec_eof(XDR *xdrs)
471eae561b3SGarrett Wollman {
4728360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
473eae561b3SGarrett Wollman
474eae561b3SGarrett Wollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
475eae561b3SGarrett Wollman if (! skip_input_bytes(rstrm, rstrm->fbtbc))
476eae561b3SGarrett Wollman return (TRUE);
477eae561b3SGarrett Wollman rstrm->fbtbc = 0;
478eae561b3SGarrett Wollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
479eae561b3SGarrett Wollman return (TRUE);
480eae561b3SGarrett Wollman }
481eae561b3SGarrett Wollman if (rstrm->in_finger == rstrm->in_boundry)
482eae561b3SGarrett Wollman return (TRUE);
483eae561b3SGarrett Wollman return (FALSE);
484eae561b3SGarrett Wollman }
485eae561b3SGarrett Wollman
486eae561b3SGarrett Wollman /*
487eae561b3SGarrett Wollman * The client must tell the package when an end-of-record has occurred.
488577a721dSGordon Bergling * The second parameters tells whether the record should be flushed to the
489eae561b3SGarrett Wollman * (output) tcp stream. (This let's the package support batched or
49005ad376bSJose Luis Duran * pipelined procedure calls.) TRUE => immediate flush to tcp connection.
491eae561b3SGarrett Wollman */
492eae561b3SGarrett Wollman bool_t
xdrrec_endofrecord(XDR * xdrs,bool_t sendnow)493d660d38dSCraig Rodrigues xdrrec_endofrecord(XDR *xdrs, bool_t sendnow)
494eae561b3SGarrett Wollman {
4958360efbdSAlfred Perlstein RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
4968360efbdSAlfred Perlstein u_long len; /* fragment length */
497eae561b3SGarrett Wollman
498eae561b3SGarrett Wollman if (sendnow || rstrm->frag_sent ||
4991ad08a09SPeter Wemm ((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
500eae561b3SGarrett Wollman (u_long)rstrm->out_boundry)) {
501eae561b3SGarrett Wollman rstrm->frag_sent = FALSE;
502eae561b3SGarrett Wollman return (flush_out(rstrm, TRUE));
503eae561b3SGarrett Wollman }
504eae561b3SGarrett Wollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
5051ad08a09SPeter Wemm sizeof(u_int32_t);
5068360efbdSAlfred Perlstein *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG);
5078360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger;
5081ad08a09SPeter Wemm rstrm->out_finger += sizeof(u_int32_t);
509eae561b3SGarrett Wollman return (TRUE);
510eae561b3SGarrett Wollman }
511eae561b3SGarrett Wollman
51208497c02SMartin Blapp /*
51308497c02SMartin Blapp * Fill the stream buffer with a record for a non-blocking connection.
51408497c02SMartin Blapp * Return true if a record is available in the buffer, false if not.
51508497c02SMartin Blapp */
51608497c02SMartin Blapp bool_t
__xdrrec_getrec(XDR * xdrs,enum xprt_stat * statp,bool_t expectdata)517d660d38dSCraig Rodrigues __xdrrec_getrec(XDR *xdrs, enum xprt_stat *statp, bool_t expectdata)
51808497c02SMartin Blapp {
51908497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
52008497c02SMartin Blapp ssize_t n;
52108497c02SMartin Blapp int fraglen;
52208497c02SMartin Blapp
52308497c02SMartin Blapp if (!rstrm->in_haveheader) {
52408497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
52508497c02SMartin Blapp (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
52608497c02SMartin Blapp if (n == 0) {
52708497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
52808497c02SMartin Blapp return FALSE;
52908497c02SMartin Blapp }
53008497c02SMartin Blapp if (n < 0) {
53108497c02SMartin Blapp *statp = XPRT_DIED;
53208497c02SMartin Blapp return FALSE;
53308497c02SMartin Blapp }
53408497c02SMartin Blapp rstrm->in_hdrp += n;
53508497c02SMartin Blapp rstrm->in_hdrlen += n;
53608497c02SMartin Blapp if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) {
53708497c02SMartin Blapp *statp = XPRT_MOREREQS;
53808497c02SMartin Blapp return FALSE;
53908497c02SMartin Blapp }
54008497c02SMartin Blapp rstrm->in_header = ntohl(rstrm->in_header);
54108497c02SMartin Blapp fraglen = (int)(rstrm->in_header & ~LAST_FRAG);
54208497c02SMartin Blapp if (fraglen == 0 || fraglen > rstrm->in_maxrec ||
54308497c02SMartin Blapp (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) {
54408497c02SMartin Blapp *statp = XPRT_DIED;
54508497c02SMartin Blapp return FALSE;
54608497c02SMartin Blapp }
54708497c02SMartin Blapp rstrm->in_reclen += fraglen;
54808497c02SMartin Blapp if (rstrm->in_reclen > rstrm->recvsize)
54908497c02SMartin Blapp realloc_stream(rstrm, rstrm->in_reclen);
55008497c02SMartin Blapp if (rstrm->in_header & LAST_FRAG) {
55108497c02SMartin Blapp rstrm->in_header &= ~LAST_FRAG;
55208497c02SMartin Blapp rstrm->last_frag = TRUE;
55308497c02SMartin Blapp }
5547ea7cc4bSDoug Rabson /*
5557ea7cc4bSDoug Rabson * We can only reasonably expect to read once from a
5567ea7cc4bSDoug Rabson * non-blocking stream. Reading the fragment header
5577ea7cc4bSDoug Rabson * may have drained the stream.
5587ea7cc4bSDoug Rabson */
5597ea7cc4bSDoug Rabson expectdata = FALSE;
56008497c02SMartin Blapp }
56108497c02SMartin Blapp
56208497c02SMartin Blapp n = rstrm->readit(rstrm->tcp_handle,
56308497c02SMartin Blapp rstrm->in_base + rstrm->in_received,
56408497c02SMartin Blapp (rstrm->in_reclen - rstrm->in_received));
56508497c02SMartin Blapp
56608497c02SMartin Blapp if (n < 0) {
56708497c02SMartin Blapp *statp = XPRT_DIED;
56808497c02SMartin Blapp return FALSE;
56908497c02SMartin Blapp }
57008497c02SMartin Blapp
57108497c02SMartin Blapp if (n == 0) {
57208497c02SMartin Blapp *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
57308497c02SMartin Blapp return FALSE;
57408497c02SMartin Blapp }
57508497c02SMartin Blapp
57608497c02SMartin Blapp rstrm->in_received += n;
57708497c02SMartin Blapp
57808497c02SMartin Blapp if (rstrm->in_received == rstrm->in_reclen) {
57908497c02SMartin Blapp rstrm->in_haveheader = FALSE;
58008497c02SMartin Blapp rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
58108497c02SMartin Blapp rstrm->in_hdrlen = 0;
58208497c02SMartin Blapp if (rstrm->last_frag) {
58308497c02SMartin Blapp rstrm->fbtbc = rstrm->in_reclen;
58408497c02SMartin Blapp rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
58508497c02SMartin Blapp rstrm->in_finger = rstrm->in_base;
58640525d3dSMartin Blapp rstrm->in_reclen = rstrm->in_received = 0;
58708497c02SMartin Blapp *statp = XPRT_MOREREQS;
58808497c02SMartin Blapp return TRUE;
58908497c02SMartin Blapp }
59008497c02SMartin Blapp }
59108497c02SMartin Blapp
59208497c02SMartin Blapp *statp = XPRT_MOREREQS;
59308497c02SMartin Blapp return FALSE;
59408497c02SMartin Blapp }
59508497c02SMartin Blapp
59608497c02SMartin Blapp bool_t
__xdrrec_setnonblock(XDR * xdrs,int maxrec)597d660d38dSCraig Rodrigues __xdrrec_setnonblock(XDR *xdrs, int maxrec)
59808497c02SMartin Blapp {
59908497c02SMartin Blapp RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
60008497c02SMartin Blapp
60108497c02SMartin Blapp rstrm->nonblock = TRUE;
60208497c02SMartin Blapp if (maxrec == 0)
60308497c02SMartin Blapp maxrec = rstrm->recvsize;
60408497c02SMartin Blapp rstrm->in_maxrec = maxrec;
60508497c02SMartin Blapp return TRUE;
60608497c02SMartin Blapp }
607eae561b3SGarrett Wollman
608eae561b3SGarrett Wollman /*
609eae561b3SGarrett Wollman * Internal useful routines
610eae561b3SGarrett Wollman */
611eae561b3SGarrett Wollman static bool_t
flush_out(RECSTREAM * rstrm,bool_t eor)612d660d38dSCraig Rodrigues flush_out(RECSTREAM *rstrm, bool_t eor)
613eae561b3SGarrett Wollman {
6148360efbdSAlfred Perlstein u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
6158360efbdSAlfred Perlstein u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) -
6168360efbdSAlfred Perlstein (u_long)(rstrm->frag_header) - sizeof(u_int32_t));
617eae561b3SGarrett Wollman
618eae561b3SGarrett Wollman *(rstrm->frag_header) = htonl(len | eormask);
6198360efbdSAlfred Perlstein len = (u_int32_t)((u_long)(rstrm->out_finger) -
6208360efbdSAlfred Perlstein (u_long)(rstrm->out_base));
621eae561b3SGarrett Wollman if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
622eae561b3SGarrett Wollman != (int)len)
623eae561b3SGarrett Wollman return (FALSE);
6248360efbdSAlfred Perlstein rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
6258360efbdSAlfred Perlstein rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t);
626eae561b3SGarrett Wollman return (TRUE);
627eae561b3SGarrett Wollman }
628eae561b3SGarrett Wollman
629eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */
fill_input_buf(RECSTREAM * rstrm)630d660d38dSCraig Rodrigues fill_input_buf(RECSTREAM *rstrm)
631eae561b3SGarrett Wollman {
6328360efbdSAlfred Perlstein char *where;
6338360efbdSAlfred Perlstein u_int32_t i;
6348360efbdSAlfred Perlstein int len;
635eae561b3SGarrett Wollman
63608497c02SMartin Blapp if (rstrm->nonblock)
63708497c02SMartin Blapp return FALSE;
63808497c02SMartin Blapp
639eae561b3SGarrett Wollman where = rstrm->in_base;
6408360efbdSAlfred Perlstein i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
641eae561b3SGarrett Wollman where += i;
6428360efbdSAlfred Perlstein len = (u_int32_t)(rstrm->in_size - i);
643eae561b3SGarrett Wollman if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
644eae561b3SGarrett Wollman return (FALSE);
645eae561b3SGarrett Wollman rstrm->in_finger = where;
646eae561b3SGarrett Wollman where += len;
647eae561b3SGarrett Wollman rstrm->in_boundry = where;
648eae561b3SGarrett Wollman return (TRUE);
649eae561b3SGarrett Wollman }
650eae561b3SGarrett Wollman
651eae561b3SGarrett Wollman static bool_t /* knows nothing about records! Only about input buffers */
get_input_bytes(RECSTREAM * rstrm,char * addr,int len)652d660d38dSCraig Rodrigues get_input_bytes(RECSTREAM *rstrm, char *addr, int len)
653eae561b3SGarrett Wollman {
6548360efbdSAlfred Perlstein size_t current;
655eae561b3SGarrett Wollman
65640525d3dSMartin Blapp if (rstrm->nonblock) {
65740525d3dSMartin Blapp if (len > (int)(rstrm->in_boundry - rstrm->in_finger))
65840525d3dSMartin Blapp return FALSE;
65940525d3dSMartin Blapp memcpy(addr, rstrm->in_finger, (size_t)len);
66040525d3dSMartin Blapp rstrm->in_finger += len;
66140525d3dSMartin Blapp return TRUE;
66240525d3dSMartin Blapp }
66340525d3dSMartin Blapp
664eae561b3SGarrett Wollman while (len > 0) {
6658360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry -
6668360efbdSAlfred Perlstein (long)rstrm->in_finger);
667eae561b3SGarrett Wollman if (current == 0) {
668eae561b3SGarrett Wollman if (! fill_input_buf(rstrm))
669eae561b3SGarrett Wollman return (FALSE);
670eae561b3SGarrett Wollman continue;
671eae561b3SGarrett Wollman }
672eae561b3SGarrett Wollman current = (len < current) ? len : current;
6738360efbdSAlfred Perlstein memmove(addr, rstrm->in_finger, current);
674eae561b3SGarrett Wollman rstrm->in_finger += current;
675eae561b3SGarrett Wollman addr += current;
676eae561b3SGarrett Wollman len -= current;
677eae561b3SGarrett Wollman }
678eae561b3SGarrett Wollman return (TRUE);
679eae561b3SGarrett Wollman }
680eae561b3SGarrett Wollman
681eae561b3SGarrett Wollman static bool_t /* next two bytes of the input stream are treated as a header */
set_input_fragment(RECSTREAM * rstrm)682d660d38dSCraig Rodrigues set_input_fragment(RECSTREAM *rstrm)
683eae561b3SGarrett Wollman {
6841ad08a09SPeter Wemm u_int32_t header;
685eae561b3SGarrett Wollman
68622e4d31aSMartin Blapp if (rstrm->nonblock)
68722e4d31aSMartin Blapp return FALSE;
6888360efbdSAlfred Perlstein if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header)))
689eae561b3SGarrett Wollman return (FALSE);
6908360efbdSAlfred Perlstein header = ntohl(header);
691eae561b3SGarrett Wollman rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
692a9352e90SBill Paul /*
693a9352e90SBill Paul * Sanity check. Try not to accept wildly incorrect
6941ce4aec2SBill Paul * record sizes. Unfortunately, the only record size
6951ce4aec2SBill Paul * we can positively identify as being 'wildly incorrect'
6961ce4aec2SBill Paul * is zero. Ridiculously large record sizes may look wrong,
6971ce4aec2SBill Paul * but we don't have any way to be certain that they aren't
6981ce4aec2SBill Paul * what the client actually intended to send us.
699a9352e90SBill Paul */
700c50a9e8fSBill Paul if (header == 0)
701a9352e90SBill Paul return(FALSE);
702eae561b3SGarrett Wollman rstrm->fbtbc = header & (~LAST_FRAG);
703eae561b3SGarrett Wollman return (TRUE);
704eae561b3SGarrett Wollman }
705eae561b3SGarrett Wollman
706eae561b3SGarrett Wollman static bool_t /* consumes input bytes; knows nothing about records! */
skip_input_bytes(RECSTREAM * rstrm,long cnt)707d660d38dSCraig Rodrigues skip_input_bytes(RECSTREAM *rstrm, long cnt)
708eae561b3SGarrett Wollman {
7098360efbdSAlfred Perlstein u_int32_t current;
710eae561b3SGarrett Wollman
711eae561b3SGarrett Wollman while (cnt > 0) {
7128360efbdSAlfred Perlstein current = (size_t)((long)rstrm->in_boundry -
7138360efbdSAlfred Perlstein (long)rstrm->in_finger);
714eae561b3SGarrett Wollman if (current == 0) {
715eae561b3SGarrett Wollman if (! fill_input_buf(rstrm))
716eae561b3SGarrett Wollman return (FALSE);
717eae561b3SGarrett Wollman continue;
718eae561b3SGarrett Wollman }
7198360efbdSAlfred Perlstein current = (u_int32_t)((cnt < current) ? cnt : current);
720eae561b3SGarrett Wollman rstrm->in_finger += current;
721eae561b3SGarrett Wollman cnt -= current;
722eae561b3SGarrett Wollman }
723eae561b3SGarrett Wollman return (TRUE);
724eae561b3SGarrett Wollman }
725eae561b3SGarrett Wollman
726eae561b3SGarrett Wollman static u_int
fix_buf_size(u_int s)727d660d38dSCraig Rodrigues fix_buf_size(u_int s)
728eae561b3SGarrett Wollman {
729eae561b3SGarrett Wollman
730eae561b3SGarrett Wollman if (s < 100)
731eae561b3SGarrett Wollman s = 4000;
732eae561b3SGarrett Wollman return (RNDUP(s));
733eae561b3SGarrett Wollman }
73408497c02SMartin Blapp
73508497c02SMartin Blapp /*
73608497c02SMartin Blapp * Reallocate the input buffer for a non-block stream.
73708497c02SMartin Blapp */
73808497c02SMartin Blapp static bool_t
realloc_stream(RECSTREAM * rstrm,int size)739d660d38dSCraig Rodrigues realloc_stream(RECSTREAM *rstrm, int size)
74008497c02SMartin Blapp {
74108497c02SMartin Blapp ptrdiff_t diff;
74208497c02SMartin Blapp char *buf;
74308497c02SMartin Blapp
74408497c02SMartin Blapp if (size > rstrm->recvsize) {
74508497c02SMartin Blapp buf = realloc(rstrm->in_base, (size_t)size);
74608497c02SMartin Blapp if (buf == NULL)
74708497c02SMartin Blapp return FALSE;
74808497c02SMartin Blapp diff = buf - rstrm->in_base;
74908497c02SMartin Blapp rstrm->in_finger += diff;
75008497c02SMartin Blapp rstrm->in_base = buf;
75108497c02SMartin Blapp rstrm->in_boundry = buf + size;
75208497c02SMartin Blapp rstrm->recvsize = size;
75308497c02SMartin Blapp rstrm->in_size = size;
75408497c02SMartin Blapp }
75508497c02SMartin Blapp
75608497c02SMartin Blapp return TRUE;
75708497c02SMartin Blapp }
758