xdr_rec.c (8f55a568f69c5b2fadaa020a452c2043a7dcf65f) xdr_rec.c (eae561b30ec984ce171d99b1fd182575acc2c639)
1/* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */
2
3/*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
10 *
8 *
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 *
12 *
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
18 *
16 *
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
22 *
20 *
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
26 *
24 *
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California 94043
30 */
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California 94043
28 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
29#if defined(LIBC_SCCS) && !defined(lint)
33static char *sccsid2 = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
34static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";
30/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
31/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
32static char *rcsid = "$Id: xdr_rec.c,v 1.1 1993/10/27 05:41:12 paul Exp $";
35#endif
33#endif
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD$");
38
39/*
40 * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
41 * layer above tcp (for rpc's use).
42 *
43 * Copyright (C) 1984, Sun Microsystems, Inc.
44 *
45 * These routines interface XDRSTREAMS to a tcp/ip connection.
46 * There is a record marking layer between the xdr stream
47 * and the tcp transport level. A record is composed on one or more
48 * record fragments. A record fragment is a thirty-two bit header followed
49 * by n bytes of data, where n is contained in the header. The header
50 * is represented as a htonl(u_long). Thegh order bit encodes
51 * whether or not the fragment is the last fragment of the record
52 * (1 => fragment is last, 0 => more fragments to follow.
53 * The other 31 bits encode the byte length of the fragment.
54 */
55
34
35/*
36 * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
37 * layer above tcp (for rpc's use).
38 *
39 * Copyright (C) 1984, Sun Microsystems, Inc.
40 *
41 * These routines interface XDRSTREAMS to a tcp/ip connection.
42 * There is a record marking layer between the xdr stream
43 * and the tcp transport level. A record is composed on one or more
44 * record fragments. A record fragment is a thirty-two bit header followed
45 * by n bytes of data, where n is contained in the header. The header
46 * is represented as a htonl(u_long). Thegh order bit encodes
47 * whether or not the fragment is the last fragment of the record
48 * (1 => fragment is last, 0 => more fragments to follow.
49 * The other 31 bits encode the byte length of the fragment.
50 */
51
56#include "namespace.h"
57#include <sys/types.h>
58
59#include <netinet/in.h>
60
61#include <err.h>
62#include <stdio.h>
63#include <stdlib.h>
52#include <stdio.h>
53#include <stdlib.h>
64#include <string.h>
65
66#include <rpc/types.h>
67#include <rpc/xdr.h>
54#include <rpc/types.h>
55#include <rpc/xdr.h>
68#include <rpc/auth.h>
69#include <rpc/svc.h>
70#include <rpc/clnt.h>
71#include <sys/stddef.h>
72#include "un-namespace.h"
73#include "rpc_com.h"
56#include <netinet/in.h>
74
57
75static bool_t xdrrec_getlong(XDR *, long *);
76static bool_t xdrrec_putlong(XDR *, const long *);
77static bool_t xdrrec_getbytes(XDR *, char *, u_int);
58extern long lseek();
78
59
79static bool_t xdrrec_putbytes(XDR *, const char *, u_int);
80static u_int xdrrec_getpos(XDR *);
81static bool_t xdrrec_setpos(XDR *, u_int);
82static int32_t *xdrrec_inline(XDR *, u_int);
83static void xdrrec_destroy(XDR *);
60static u_int fix_buf_size();
61static bool_t flush_out();
62static bool_t get_input_bytes();
63static bool_t set_input_fragment();
64static bool_t skip_input_bytes();
84
65
85static const struct xdr_ops xdrrec_ops = {
66static bool_t xdrrec_getlong();
67static bool_t xdrrec_putlong();
68static bool_t xdrrec_getbytes();
69static bool_t xdrrec_putbytes();
70static u_int xdrrec_getpos();
71static bool_t xdrrec_setpos();
72static long * xdrrec_inline();
73static void xdrrec_destroy();
74
75static struct xdr_ops xdrrec_ops = {
86 xdrrec_getlong,
87 xdrrec_putlong,
88 xdrrec_getbytes,
89 xdrrec_putbytes,
90 xdrrec_getpos,
91 xdrrec_setpos,
92 xdrrec_inline,
93 xdrrec_destroy
94};
95
96/*
97 * A record is composed of one or more record fragments.
76 xdrrec_getlong,
77 xdrrec_putlong,
78 xdrrec_getbytes,
79 xdrrec_putbytes,
80 xdrrec_getpos,
81 xdrrec_setpos,
82 xdrrec_inline,
83 xdrrec_destroy
84};
85
86/*
87 * A record is composed of one or more record fragments.
98 * A record fragment is a four-byte header followed by zero to
88 * A record fragment is a two-byte header followed by zero to
99 * 2**32-1 bytes. The header is treated as a long unsigned and is
100 * encode/decoded to the network via htonl/ntohl. The low order 31 bits
101 * are a byte count of the fragment. The highest order bit is a boolean:
102 * 1 => this fragment is the last fragment of the record,
103 * 0 => this fragment is followed by more fragment(s).
104 *
105 * The fragment/record machinery is not general; it is constructed to
106 * meet the needs of xdr and rpc based on tcp.
107 */
108
89 * 2**32-1 bytes. The header is treated as a long unsigned and is
90 * encode/decoded to the network via htonl/ntohl. The low order 31 bits
91 * are a byte count of the fragment. The highest order bit is a boolean:
92 * 1 => this fragment is the last fragment of the record,
93 * 0 => this fragment is followed by more fragment(s).
94 *
95 * The fragment/record machinery is not general; it is constructed to
96 * meet the needs of xdr and rpc based on tcp.
97 */
98
109#define LAST_FRAG ((u_int32_t)(1 << 31))
99#define LAST_FRAG ((u_long)(1 << 31))
110
111typedef struct rec_strm {
100
101typedef struct rec_strm {
112 char *tcp_handle;
102 caddr_t tcp_handle;
103 caddr_t the_buffer;
113 /*
114 * out-goung bits
115 */
104 /*
105 * out-goung bits
106 */
116 int (*writeit)(void *, void *, int);
117 char *out_base; /* output buffer (points to frag header) */
118 char *out_finger; /* next output position */
119 char *out_boundry; /* data cannot up to this address */
120 u_int32_t *frag_header; /* beginning of curren fragment */
107 int (*writeit)();
108 caddr_t out_base; /* output buffer (points to frag header) */
109 caddr_t out_finger; /* next output position */
110 caddr_t out_boundry; /* data cannot up to this address */
111 u_long *frag_header; /* beginning of curren fragment */
121 bool_t frag_sent; /* true if buffer sent in middle of record */
122 /*
123 * in-coming bits
124 */
112 bool_t frag_sent; /* true if buffer sent in middle of record */
113 /*
114 * in-coming bits
115 */
125 int (*readit)(void *, void *, int);
116 int (*readit)();
126 u_long in_size; /* fixed size of the input buffer */
117 u_long in_size; /* fixed size of the input buffer */
127 char *in_base;
128 char *in_finger; /* location of next byte to be had */
129 char *in_boundry; /* can read up to this location */
118 caddr_t in_base;
119 caddr_t in_finger; /* location of next byte to be had */
120 caddr_t in_boundry; /* can read up to this location */
130 long fbtbc; /* fragment bytes to be consumed */
131 bool_t last_frag;
132 u_int sendsize;
133 u_int recvsize;
121 long fbtbc; /* fragment bytes to be consumed */
122 bool_t last_frag;
123 u_int sendsize;
124 u_int recvsize;
134
135 bool_t nonblock;
136 bool_t in_haveheader;
137 u_int32_t in_header;
138 char *in_hdrp;
139 int in_hdrlen;
140 int in_reclen;
141 int in_received;
142 int in_maxrec;
143} RECSTREAM;
144
125} RECSTREAM;
126
145static u_int fix_buf_size(u_int);
146static bool_t flush_out(RECSTREAM *, bool_t);
147static bool_t fill_input_buf(RECSTREAM *);
148static bool_t get_input_bytes(RECSTREAM *, char *, int);
149static bool_t set_input_fragment(RECSTREAM *);
150static bool_t skip_input_bytes(RECSTREAM *, long);
151static bool_t realloc_stream(RECSTREAM *, int);
152
127
153
154/*
155 * Create an xdr handle for xdrrec
156 * xdrrec_create fills in xdrs. Sendsize and recvsize are
157 * send and recv buffer sizes (0 => use default).
158 * tcp_handle is an opaque handle that is passed as the first parameter to
159 * the procedures readit and writeit. Readit and writeit are read and
160 * write respectively. They are like the system
161 * calls expect that they take an opaque handle rather than an fd.
162 */
163void
164xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
128/*
129 * Create an xdr handle for xdrrec
130 * xdrrec_create fills in xdrs. Sendsize and recvsize are
131 * send and recv buffer sizes (0 => use default).
132 * tcp_handle is an opaque handle that is passed as the first parameter to
133 * the procedures readit and writeit. Readit and writeit are read and
134 * write respectively. They are like the system
135 * calls expect that they take an opaque handle rather than an fd.
136 */
137void
138xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
165 XDR *xdrs;
166 u_int sendsize;
167 u_int recvsize;
168 void *tcp_handle;
169 /* like read, but pass it a tcp_handle, not sock */
170 int (*readit)(void *, void *, int);
171 /* like write, but pass it a tcp_handle, not sock */
172 int (*writeit)(void *, void *, int);
139 register XDR *xdrs;
140 register u_int sendsize;
141 register u_int recvsize;
142 caddr_t tcp_handle;
143 int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
144 int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
173{
145{
174 RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
146 register RECSTREAM *rstrm =
147 (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
175
176 if (rstrm == NULL) {
148
149 if (rstrm == NULL) {
177 warnx("xdrrec_create: out of memory");
150 (void)fprintf(stderr, "xdrrec_create: out of memory\n");
178 /*
179 * This is bad. Should rework xdrrec_create to
180 * return a handle, and in this case return NULL
181 */
182 return;
183 }
151 /*
152 * This is bad. Should rework xdrrec_create to
153 * return a handle, and in this case return NULL
154 */
155 return;
156 }
157 /*
158 * adjust sizes and allocate buffer quad byte aligned
159 */
184 rstrm->sendsize = sendsize = fix_buf_size(sendsize);
160 rstrm->sendsize = sendsize = fix_buf_size(sendsize);
185 rstrm->out_base = mem_alloc(rstrm->sendsize);
186 if (rstrm->out_base == NULL) {
187 warnx("xdrrec_create: out of memory");
188 mem_free(rstrm, sizeof(RECSTREAM));
189 return;
190 }
191 rstrm->recvsize = recvsize = fix_buf_size(recvsize);
161 rstrm->recvsize = recvsize = fix_buf_size(recvsize);
192 rstrm->in_base = mem_alloc(recvsize);
193 if (rstrm->in_base == NULL) {
194 warnx("xdrrec_create: out of memory");
195 mem_free(rstrm->out_base, sendsize);
196 mem_free(rstrm, sizeof(RECSTREAM));
162 rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
163 if (rstrm->the_buffer == NULL) {
164 (void)fprintf(stderr, "xdrrec_create: out of memory\n");
197 return;
198 }
165 return;
166 }
167 for (rstrm->out_base = rstrm->the_buffer;
168 (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
169 rstrm->out_base++);
170 rstrm->in_base = rstrm->out_base + sendsize;
199 /*
200 * now the rest ...
201 */
202 xdrs->x_ops = &xdrrec_ops;
171 /*
172 * now the rest ...
173 */
174 xdrs->x_ops = &xdrrec_ops;
203 xdrs->x_private = rstrm;
175 xdrs->x_private = (caddr_t)rstrm;
204 rstrm->tcp_handle = tcp_handle;
205 rstrm->readit = readit;
206 rstrm->writeit = writeit;
207 rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
176 rstrm->tcp_handle = tcp_handle;
177 rstrm->readit = readit;
178 rstrm->writeit = writeit;
179 rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
208 rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
209 rstrm->out_finger += sizeof(u_int32_t);
180 rstrm->frag_header = (u_long *)rstrm->out_base;
181 rstrm->out_finger += sizeof(u_long);
210 rstrm->out_boundry += sendsize;
211 rstrm->frag_sent = FALSE;
212 rstrm->in_size = recvsize;
213 rstrm->in_boundry = rstrm->in_base;
214 rstrm->in_finger = (rstrm->in_boundry += recvsize);
215 rstrm->fbtbc = 0;
216 rstrm->last_frag = TRUE;
182 rstrm->out_boundry += sendsize;
183 rstrm->frag_sent = FALSE;
184 rstrm->in_size = recvsize;
185 rstrm->in_boundry = rstrm->in_base;
186 rstrm->in_finger = (rstrm->in_boundry += recvsize);
187 rstrm->fbtbc = 0;
188 rstrm->last_frag = TRUE;
217 rstrm->in_haveheader = FALSE;
218 rstrm->in_hdrlen = 0;
219 rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
220 rstrm->nonblock = FALSE;
221 rstrm->in_reclen = 0;
222 rstrm->in_received = 0;
223}
224
225
226/*
227 * The reoutines defined below are the xdr ops which will go into the
228 * xdr handle filled in by xdrrec_create.
229 */
230
231static bool_t
232xdrrec_getlong(xdrs, lp)
233 XDR *xdrs;
234 long *lp;
235{
189}
190
191
192/*
193 * The reoutines defined below are the xdr ops which will go into the
194 * xdr handle filled in by xdrrec_create.
195 */
196
197static bool_t
198xdrrec_getlong(xdrs, lp)
199 XDR *xdrs;
200 long *lp;
201{
236 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
237 int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
238 int32_t mylong;
202 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
203 register long *buflp = (long *)(rstrm->in_finger);
204 long mylong;
239
240 /* first try the inline, fast case */
205
206 /* first try the inline, fast case */
241 if ((rstrm->fbtbc >= sizeof(int32_t)) &&
242 (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) {
243 *lp = (long)ntohl((u_int32_t)(*buflp));
244 rstrm->fbtbc -= sizeof(int32_t);
245 rstrm->in_finger += sizeof(int32_t);
207 if ((rstrm->fbtbc >= sizeof(long)) &&
208 (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
209 *lp = (long)ntohl((u_long)(*buflp));
210 rstrm->fbtbc -= sizeof(long);
211 rstrm->in_finger += sizeof(long);
246 } else {
212 } else {
247 if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
248 sizeof(int32_t)))
213 if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
249 return (FALSE);
214 return (FALSE);
250 *lp = (long)ntohl((u_int32_t)mylong);
215 *lp = (long)ntohl((u_long)mylong);
251 }
252 return (TRUE);
253}
254
255static bool_t
256xdrrec_putlong(xdrs, lp)
257 XDR *xdrs;
216 }
217 return (TRUE);
218}
219
220static bool_t
221xdrrec_putlong(xdrs, lp)
222 XDR *xdrs;
258 const long *lp;
223 long *lp;
259{
224{
260 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
261 int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
225 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
226 register long *dest_lp = ((long *)(rstrm->out_finger));
262
227
263 if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
228 if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
264 /*
265 * this case should almost never happen so the code is
266 * inefficient
267 */
229 /*
230 * this case should almost never happen so the code is
231 * inefficient
232 */
268 rstrm->out_finger -= sizeof(int32_t);
233 rstrm->out_finger -= sizeof(long);
269 rstrm->frag_sent = TRUE;
270 if (! flush_out(rstrm, FALSE))
271 return (FALSE);
234 rstrm->frag_sent = TRUE;
235 if (! flush_out(rstrm, FALSE))
236 return (FALSE);
272 dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
273 rstrm->out_finger += sizeof(int32_t);
237 dest_lp = ((long *)(rstrm->out_finger));
238 rstrm->out_finger += sizeof(long);
274 }
239 }
275 *dest_lp = (int32_t)htonl((u_int32_t)(*lp));
240 *dest_lp = (long)htonl((u_long)(*lp));
276 return (TRUE);
277}
278
279static bool_t /* must manage buffers, fragments, and records */
280xdrrec_getbytes(xdrs, addr, len)
281 XDR *xdrs;
241 return (TRUE);
242}
243
244static bool_t /* must manage buffers, fragments, and records */
245xdrrec_getbytes(xdrs, addr, len)
246 XDR *xdrs;
282 char *addr;
283 u_int len;
247 register caddr_t addr;
248 register u_int len;
284{
249{
285 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
286 int current;
250 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
251 register int current;
287
288 while (len > 0) {
252
253 while (len > 0) {
289 current = (int)rstrm->fbtbc;
254 current = rstrm->fbtbc;
290 if (current == 0) {
291 if (rstrm->last_frag)
292 return (FALSE);
293 if (! set_input_fragment(rstrm))
294 return (FALSE);
295 continue;
296 }
297 current = (len < current) ? len : current;

--- 4 unchanged lines hidden (view full) ---

302 len -= current;
303 }
304 return (TRUE);
305}
306
307static bool_t
308xdrrec_putbytes(xdrs, addr, len)
309 XDR *xdrs;
255 if (current == 0) {
256 if (rstrm->last_frag)
257 return (FALSE);
258 if (! set_input_fragment(rstrm))
259 return (FALSE);
260 continue;
261 }
262 current = (len < current) ? len : current;

--- 4 unchanged lines hidden (view full) ---

267 len -= current;
268 }
269 return (TRUE);
270}
271
272static bool_t
273xdrrec_putbytes(xdrs, addr, len)
274 XDR *xdrs;
310 const char *addr;
311 u_int len;
275 register caddr_t addr;
276 register u_int len;
312{
277{
313 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
314 size_t current;
278 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
279 register int current;
315
316 while (len > 0) {
280
281 while (len > 0) {
317 current = (size_t)((u_long)rstrm->out_boundry -
318 (u_long)rstrm->out_finger);
282 current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
319 current = (len < current) ? len : current;
283 current = (len < current) ? len : current;
320 memmove(rstrm->out_finger, addr, current);
284 bcopy(addr, rstrm->out_finger, current);
321 rstrm->out_finger += current;
322 addr += current;
323 len -= current;
324 if (rstrm->out_finger == rstrm->out_boundry) {
325 rstrm->frag_sent = TRUE;
326 if (! flush_out(rstrm, FALSE))
327 return (FALSE);
328 }
329 }
330 return (TRUE);
331}
332
333static u_int
334xdrrec_getpos(xdrs)
285 rstrm->out_finger += current;
286 addr += current;
287 len -= current;
288 if (rstrm->out_finger == rstrm->out_boundry) {
289 rstrm->frag_sent = TRUE;
290 if (! flush_out(rstrm, FALSE))
291 return (FALSE);
292 }
293 }
294 return (TRUE);
295}
296
297static u_int
298xdrrec_getpos(xdrs)
335 XDR *xdrs;
299 register XDR *xdrs;
336{
300{
337 RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
338 off_t pos;
301 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
302 register long pos;
339
303
340 pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1);
341 if (pos == -1)
342 pos = 0;
343 switch (xdrs->x_op) {
304 pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
305 if (pos != -1)
306 switch (xdrs->x_op) {
344
307
345 case XDR_ENCODE:
346 pos += rstrm->out_finger - rstrm->out_base;
347 break;
308 case XDR_ENCODE:
309 pos += rstrm->out_finger - rstrm->out_base;
310 break;
348
311
349 case XDR_DECODE:
350 pos -= rstrm->in_boundry - rstrm->in_finger;
351 break;
312 case XDR_DECODE:
313 pos -= rstrm->in_boundry - rstrm->in_finger;
314 break;
352
315
353 default:
354 pos = (off_t) -1;
355 break;
356 }
316 default:
317 pos = (u_int) -1;
318 break;
319 }
357 return ((u_int) pos);
358}
359
360static bool_t
361xdrrec_setpos(xdrs, pos)
320 return ((u_int) pos);
321}
322
323static bool_t
324xdrrec_setpos(xdrs, pos)
362 XDR *xdrs;
325 register XDR *xdrs;
363 u_int pos;
364{
326 u_int pos;
327{
365 RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
328 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
366 u_int currpos = xdrrec_getpos(xdrs);
367 int delta = currpos - pos;
329 u_int currpos = xdrrec_getpos(xdrs);
330 int delta = currpos - pos;
368 char *newpos;
331 caddr_t newpos;
369
370 if ((int)currpos != -1)
371 switch (xdrs->x_op) {
372
373 case XDR_ENCODE:
374 newpos = rstrm->out_finger - delta;
332
333 if ((int)currpos != -1)
334 switch (xdrs->x_op) {
335
336 case XDR_ENCODE:
337 newpos = rstrm->out_finger - delta;
375 if ((newpos > (char *)(void *)(rstrm->frag_header)) &&
338 if ((newpos > (caddr_t)(rstrm->frag_header)) &&
376 (newpos < rstrm->out_boundry)) {
377 rstrm->out_finger = newpos;
378 return (TRUE);
379 }
380 break;
381
382 case XDR_DECODE:
383 newpos = rstrm->in_finger - delta;
384 if ((delta < (int)(rstrm->fbtbc)) &&
385 (newpos <= rstrm->in_boundry) &&
386 (newpos >= rstrm->in_base)) {
387 rstrm->in_finger = newpos;
388 rstrm->fbtbc -= delta;
389 return (TRUE);
390 }
391 break;
339 (newpos < rstrm->out_boundry)) {
340 rstrm->out_finger = newpos;
341 return (TRUE);
342 }
343 break;
344
345 case XDR_DECODE:
346 newpos = rstrm->in_finger - delta;
347 if ((delta < (int)(rstrm->fbtbc)) &&
348 (newpos <= rstrm->in_boundry) &&
349 (newpos >= rstrm->in_base)) {
350 rstrm->in_finger = newpos;
351 rstrm->fbtbc -= delta;
352 return (TRUE);
353 }
354 break;
392
393 case XDR_FREE:
394 break;
395 }
396 return (FALSE);
397}
398
355 }
356 return (FALSE);
357}
358
399static int32_t *
359static long *
400xdrrec_inline(xdrs, len)
360xdrrec_inline(xdrs, len)
401 XDR *xdrs;
402 u_int len;
361 register XDR *xdrs;
362 int len;
403{
363{
404 RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
405 int32_t *buf = NULL;
364 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
365 long * buf = NULL;
406
407 switch (xdrs->x_op) {
408
409 case XDR_ENCODE:
410 if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
366
367 switch (xdrs->x_op) {
368
369 case XDR_ENCODE:
370 if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
411 buf = (int32_t *)(void *)rstrm->out_finger;
371 buf = (long *) rstrm->out_finger;
412 rstrm->out_finger += len;
413 }
414 break;
415
416 case XDR_DECODE:
417 if ((len <= rstrm->fbtbc) &&
418 ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
372 rstrm->out_finger += len;
373 }
374 break;
375
376 case XDR_DECODE:
377 if ((len <= rstrm->fbtbc) &&
378 ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
419 buf = (int32_t *)(void *)rstrm->in_finger;
379 buf = (long *) rstrm->in_finger;
420 rstrm->fbtbc -= len;
421 rstrm->in_finger += len;
422 }
423 break;
380 rstrm->fbtbc -= len;
381 rstrm->in_finger += len;
382 }
383 break;
424
425 case XDR_FREE:
426 break;
427 }
428 return (buf);
429}
430
431static void
432xdrrec_destroy(xdrs)
384 }
385 return (buf);
386}
387
388static void
389xdrrec_destroy(xdrs)
433 XDR *xdrs;
390 register XDR *xdrs;
434{
391{
435 RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
392 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
436
393
437 mem_free(rstrm->out_base, rstrm->sendsize);
438 mem_free(rstrm->in_base, rstrm->recvsize);
439 mem_free(rstrm, sizeof(RECSTREAM));
394 mem_free(rstrm->the_buffer,
395 rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
396 mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
440}
441
442
443/*
444 * Exported routines to manage xdr records
445 */
446
447/*
448 * Before reading (deserializing from the stream, one should always call
449 * this procedure to guarantee proper record alignment.
450 */
451bool_t
452xdrrec_skiprecord(xdrs)
453 XDR *xdrs;
454{
397}
398
399
400/*
401 * Exported routines to manage xdr records
402 */
403
404/*
405 * Before reading (deserializing from the stream, one should always call
406 * this procedure to guarantee proper record alignment.
407 */
408bool_t
409xdrrec_skiprecord(xdrs)
410 XDR *xdrs;
411{
455 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
456 enum xprt_stat xstat;
412 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
457
413
458 if (rstrm->nonblock) {
459 if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
460 rstrm->fbtbc = 0;
461 return TRUE;
462 }
463 if (rstrm->in_finger == rstrm->in_boundry &&
464 xstat == XPRT_MOREREQS) {
465 rstrm->fbtbc = 0;
466 return TRUE;
467 }
468 return FALSE;
469 }
470
471 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
472 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
473 return (FALSE);
474 rstrm->fbtbc = 0;
475 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
476 return (FALSE);
477 }
478 rstrm->last_frag = FALSE;
479 return (TRUE);
480}
481
482/*
414 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
415 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
416 return (FALSE);
417 rstrm->fbtbc = 0;
418 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
419 return (FALSE);
420 }
421 rstrm->last_frag = FALSE;
422 return (TRUE);
423}
424
425/*
483 * Look ahead function.
484 * Returns TRUE iff there is no more input in the buffer
426 * Look ahead fuction.
427 * Returns TRUE iff there is no more input in the buffer
485 * after consuming the rest of the current record.
486 */
487bool_t
488xdrrec_eof(xdrs)
489 XDR *xdrs;
490{
428 * after consuming the rest of the current record.
429 */
430bool_t
431xdrrec_eof(xdrs)
432 XDR *xdrs;
433{
491 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
434 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
492
493 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
494 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
495 return (TRUE);
496 rstrm->fbtbc = 0;
497 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
498 return (TRUE);
499 }

--- 8 unchanged lines hidden (view full) ---

508 * (output) tcp stream. (This let's the package support batched or
509 * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
510 */
511bool_t
512xdrrec_endofrecord(xdrs, sendnow)
513 XDR *xdrs;
514 bool_t sendnow;
515{
435
436 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
437 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
438 return (TRUE);
439 rstrm->fbtbc = 0;
440 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
441 return (TRUE);
442 }

--- 8 unchanged lines hidden (view full) ---

451 * (output) tcp stream. (This let's the package support batched or
452 * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
453 */
454bool_t
455xdrrec_endofrecord(xdrs, sendnow)
456 XDR *xdrs;
457 bool_t sendnow;
458{
516 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
517 u_long len; /* fragment length */
459 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
460 register u_long len; /* fragment length */
518
519 if (sendnow || rstrm->frag_sent ||
461
462 if (sendnow || rstrm->frag_sent ||
520 ((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
463 ((u_long)rstrm->out_finger + sizeof(u_long) >=
521 (u_long)rstrm->out_boundry)) {
522 rstrm->frag_sent = FALSE;
523 return (flush_out(rstrm, TRUE));
524 }
525 len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
464 (u_long)rstrm->out_boundry)) {
465 rstrm->frag_sent = FALSE;
466 return (flush_out(rstrm, TRUE));
467 }
468 len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
526 sizeof(u_int32_t);
527 *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG);
528 rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger;
529 rstrm->out_finger += sizeof(u_int32_t);
469 sizeof(u_long);
470 *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
471 rstrm->frag_header = (u_long *)rstrm->out_finger;
472 rstrm->out_finger += sizeof(u_long);
530 return (TRUE);
531}
532
473 return (TRUE);
474}
475
533/*
534 * Fill the stream buffer with a record for a non-blocking connection.
535 * Return true if a record is available in the buffer, false if not.
536 */
537bool_t
538__xdrrec_getrec(xdrs, statp, expectdata)
539 XDR *xdrs;
540 enum xprt_stat *statp;
541 bool_t expectdata;
542{
543 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
544 ssize_t n;
545 int fraglen;
546
476
547 if (!rstrm->in_haveheader) {
548 n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
549 (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
550 if (n == 0) {
551 *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
552 return FALSE;
553 }
554 if (n < 0) {
555 *statp = XPRT_DIED;
556 return FALSE;
557 }
558 rstrm->in_hdrp += n;
559 rstrm->in_hdrlen += n;
560 if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) {
561 *statp = XPRT_MOREREQS;
562 return FALSE;
563 }
564 rstrm->in_header = ntohl(rstrm->in_header);
565 fraglen = (int)(rstrm->in_header & ~LAST_FRAG);
566 if (fraglen == 0 || fraglen > rstrm->in_maxrec ||
567 (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) {
568 *statp = XPRT_DIED;
569 return FALSE;
570 }
571 rstrm->in_reclen += fraglen;
572 if (rstrm->in_reclen > rstrm->recvsize)
573 realloc_stream(rstrm, rstrm->in_reclen);
574 if (rstrm->in_header & LAST_FRAG) {
575 rstrm->in_header &= ~LAST_FRAG;
576 rstrm->last_frag = TRUE;
577 }
578 /*
579 * We can only reasonably expect to read once from a
580 * non-blocking stream. Reading the fragment header
581 * may have drained the stream.
582 */
583 expectdata = FALSE;
584 }
585
586 n = rstrm->readit(rstrm->tcp_handle,
587 rstrm->in_base + rstrm->in_received,
588 (rstrm->in_reclen - rstrm->in_received));
589
590 if (n < 0) {
591 *statp = XPRT_DIED;
592 return FALSE;
593 }
594
595 if (n == 0) {
596 *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
597 return FALSE;
598 }
599
600 rstrm->in_received += n;
601
602 if (rstrm->in_received == rstrm->in_reclen) {
603 rstrm->in_haveheader = FALSE;
604 rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
605 rstrm->in_hdrlen = 0;
606 if (rstrm->last_frag) {
607 rstrm->fbtbc = rstrm->in_reclen;
608 rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
609 rstrm->in_finger = rstrm->in_base;
610 rstrm->in_reclen = rstrm->in_received = 0;
611 *statp = XPRT_MOREREQS;
612 return TRUE;
613 }
614 }
615
616 *statp = XPRT_MOREREQS;
617 return FALSE;
618}
619
620bool_t
621__xdrrec_setnonblock(xdrs, maxrec)
622 XDR *xdrs;
623 int maxrec;
624{
625 RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
626
627 rstrm->nonblock = TRUE;
628 if (maxrec == 0)
629 maxrec = rstrm->recvsize;
630 rstrm->in_maxrec = maxrec;
631 return TRUE;
632}
633
634/*
635 * Internal useful routines
636 */
637static bool_t
638flush_out(rstrm, eor)
477/*
478 * Internal useful routines
479 */
480static bool_t
481flush_out(rstrm, eor)
639 RECSTREAM *rstrm;
482 register RECSTREAM *rstrm;
640 bool_t eor;
641{
483 bool_t eor;
484{
642 u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
643 u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) -
644 (u_long)(rstrm->frag_header) - sizeof(u_int32_t));
485 register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
486 register u_long len = (u_long)(rstrm->out_finger) -
487 (u_long)(rstrm->frag_header) - sizeof(u_long);
645
646 *(rstrm->frag_header) = htonl(len | eormask);
488
489 *(rstrm->frag_header) = htonl(len | eormask);
647 len = (u_int32_t)((u_long)(rstrm->out_finger) -
648 (u_long)(rstrm->out_base));
490 len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
649 if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
650 != (int)len)
651 return (FALSE);
491 if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
492 != (int)len)
493 return (FALSE);
652 rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
653 rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t);
494 rstrm->frag_header = (u_long *)rstrm->out_base;
495 rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
654 return (TRUE);
655}
656
657static bool_t /* knows nothing about records! Only about input buffers */
658fill_input_buf(rstrm)
496 return (TRUE);
497}
498
499static bool_t /* knows nothing about records! Only about input buffers */
500fill_input_buf(rstrm)
659 RECSTREAM *rstrm;
501 register RECSTREAM *rstrm;
660{
502{
661 char *where;
662 u_int32_t i;
663 int len;
503 register caddr_t where;
504 u_int i;
505 register int len;
664
506
665 if (rstrm->nonblock)
666 return FALSE;
667
668 where = rstrm->in_base;
507 where = rstrm->in_base;
669 i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
508 i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
670 where += i;
509 where += i;
671 len = (u_int32_t)(rstrm->in_size - i);
510 len = rstrm->in_size - i;
672 if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
673 return (FALSE);
674 rstrm->in_finger = where;
675 where += len;
676 rstrm->in_boundry = where;
677 return (TRUE);
678}
679
680static bool_t /* knows nothing about records! Only about input buffers */
681get_input_bytes(rstrm, addr, len)
511 if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
512 return (FALSE);
513 rstrm->in_finger = where;
514 where += len;
515 rstrm->in_boundry = where;
516 return (TRUE);
517}
518
519static bool_t /* knows nothing about records! Only about input buffers */
520get_input_bytes(rstrm, addr, len)
682 RECSTREAM *rstrm;
683 char *addr;
684 int len;
521 register RECSTREAM *rstrm;
522 register caddr_t addr;
523 register int len;
685{
524{
686 size_t current;
525 register int current;
687
526
688 if (rstrm->nonblock) {
689 if (len > (int)(rstrm->in_boundry - rstrm->in_finger))
690 return FALSE;
691 memcpy(addr, rstrm->in_finger, (size_t)len);
692 rstrm->in_finger += len;
693 return TRUE;
694 }
695
696 while (len > 0) {
527 while (len > 0) {
697 current = (size_t)((long)rstrm->in_boundry -
698 (long)rstrm->in_finger);
528 current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
699 if (current == 0) {
700 if (! fill_input_buf(rstrm))
701 return (FALSE);
702 continue;
703 }
704 current = (len < current) ? len : current;
529 if (current == 0) {
530 if (! fill_input_buf(rstrm))
531 return (FALSE);
532 continue;
533 }
534 current = (len < current) ? len : current;
705 memmove(addr, rstrm->in_finger, current);
535 bcopy(rstrm->in_finger, addr, current);
706 rstrm->in_finger += current;
707 addr += current;
708 len -= current;
709 }
710 return (TRUE);
711}
712
713static bool_t /* next two bytes of the input stream are treated as a header */
714set_input_fragment(rstrm)
536 rstrm->in_finger += current;
537 addr += current;
538 len -= current;
539 }
540 return (TRUE);
541}
542
543static bool_t /* next two bytes of the input stream are treated as a header */
544set_input_fragment(rstrm)
715 RECSTREAM *rstrm;
545 register RECSTREAM *rstrm;
716{
546{
717 u_int32_t header;
547 u_long header;
718
548
719 if (rstrm->nonblock)
720 return FALSE;
721 if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header)))
549 if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
722 return (FALSE);
550 return (FALSE);
723 header = ntohl(header);
551 header = (long)ntohl(header);
724 rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
552 rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
725 /*
726 * Sanity check. Try not to accept wildly incorrect
727 * record sizes. Unfortunately, the only record size
728 * we can positively identify as being 'wildly incorrect'
729 * is zero. Ridiculously large record sizes may look wrong,
730 * but we don't have any way to be certain that they aren't
731 * what the client actually intended to send us.
732 */
733 if (header == 0)
734 return(FALSE);
735 rstrm->fbtbc = header & (~LAST_FRAG);
736 return (TRUE);
737}
738
739static bool_t /* consumes input bytes; knows nothing about records! */
740skip_input_bytes(rstrm, cnt)
553 rstrm->fbtbc = header & (~LAST_FRAG);
554 return (TRUE);
555}
556
557static bool_t /* consumes input bytes; knows nothing about records! */
558skip_input_bytes(rstrm, cnt)
741 RECSTREAM *rstrm;
559 register RECSTREAM *rstrm;
742 long cnt;
743{
560 long cnt;
561{
744 u_int32_t current;
562 register int current;
745
746 while (cnt > 0) {
563
564 while (cnt > 0) {
747 current = (size_t)((long)rstrm->in_boundry -
748 (long)rstrm->in_finger);
565 current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
749 if (current == 0) {
750 if (! fill_input_buf(rstrm))
751 return (FALSE);
752 continue;
753 }
566 if (current == 0) {
567 if (! fill_input_buf(rstrm))
568 return (FALSE);
569 continue;
570 }
754 current = (u_int32_t)((cnt < current) ? cnt : current);
571 current = (cnt < current) ? cnt : current;
755 rstrm->in_finger += current;
756 cnt -= current;
757 }
758 return (TRUE);
759}
760
761static u_int
762fix_buf_size(s)
572 rstrm->in_finger += current;
573 cnt -= current;
574 }
575 return (TRUE);
576}
577
578static u_int
579fix_buf_size(s)
763 u_int s;
580 register u_int s;
764{
765
766 if (s < 100)
767 s = 4000;
768 return (RNDUP(s));
769}
581{
582
583 if (s < 100)
584 s = 4000;
585 return (RNDUP(s));
586}
770
771/*
772 * Reallocate the input buffer for a non-block stream.
773 */
774static bool_t
775realloc_stream(rstrm, size)
776 RECSTREAM *rstrm;
777 int size;
778{
779 ptrdiff_t diff;
780 char *buf;
781
782 if (size > rstrm->recvsize) {
783 buf = realloc(rstrm->in_base, (size_t)size);
784 if (buf == NULL)
785 return FALSE;
786 diff = buf - rstrm->in_base;
787 rstrm->in_finger += diff;
788 rstrm->in_base = buf;
789 rstrm->in_boundry = buf + size;
790 rstrm->recvsize = size;
791 rstrm->in_size = size;
792 }
793
794 return TRUE;
795}