xdr_rec.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /*
  2. * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
  3. * layer above tcp (for rpc's use).
  4. *
  5. * Copyright (c) 2010, Oracle America, Inc.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials
  16. * provided with the distribution.
  17. * * Neither the name of the "Oracle America, Inc." nor the names of its
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  26. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  28. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. * These routines interface XDRSTREAMS to a tcp/ip connection.
  35. * There is a record marking layer between the xdr stream
  36. * and the tcp transport level. A record is composed on one or more
  37. * record fragments. A record fragment is a thirty-two bit header followed
  38. * by n bytes of data, where n is contained in the header. The header
  39. * is represented as a htonl(u_long). The high order bit encodes
  40. * whether or not the fragment is the last fragment of the record
  41. * (1 => fragment is last, 0 => more fragments to follow.
  42. * The other 31 bits encode the byte length of the fragment.
  43. */
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47. #include <stdint.h>
  48. #include <rpc/rpc.h>
  49. #include <libintl.h>
  50. #include <wchar.h>
  51. #include <libio/iolibio.h>
  52. #include <shlib-compat.h>
  53. static bool_t xdrrec_getlong (XDR *, long *);
  54. static bool_t xdrrec_putlong (XDR *, const long *);
  55. static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int);
  56. static bool_t xdrrec_putbytes (XDR *, const char *, u_int);
  57. static u_int xdrrec_getpos (const XDR *);
  58. static bool_t xdrrec_setpos (XDR *, u_int);
  59. static int32_t *xdrrec_inline (XDR *, u_int);
  60. static void xdrrec_destroy (XDR *);
  61. static bool_t xdrrec_getint32 (XDR *, int32_t *);
  62. static bool_t xdrrec_putint32 (XDR *, const int32_t *);
  63. static const struct xdr_ops xdrrec_ops = {
  64. xdrrec_getlong,
  65. xdrrec_putlong,
  66. xdrrec_getbytes,
  67. xdrrec_putbytes,
  68. xdrrec_getpos,
  69. xdrrec_setpos,
  70. xdrrec_inline,
  71. xdrrec_destroy,
  72. xdrrec_getint32,
  73. xdrrec_putint32
  74. };
  75. /*
  76. * A record is composed of one or more record fragments.
  77. * A record fragment is a two-byte header followed by zero to
  78. * 2**32-1 bytes. The header is treated as a long unsigned and is
  79. * encode/decoded to the network via htonl/ntohl. The low order 31 bits
  80. * are a byte count of the fragment. The highest order bit is a boolean:
  81. * 1 => this fragment is the last fragment of the record,
  82. * 0 => this fragment is followed by more fragment(s).
  83. *
  84. * The fragment/record machinery is not general; it is constructed to
  85. * meet the needs of xdr and rpc based on tcp.
  86. */
  87. #define LAST_FRAG (1UL << 31)
  88. typedef struct rec_strm
  89. {
  90. caddr_t tcp_handle;
  91. caddr_t the_buffer;
  92. /*
  93. * out-going bits
  94. */
  95. int (*writeit) (char *, char *, int);
  96. caddr_t out_base; /* output buffer (points to frag header) */
  97. caddr_t out_finger; /* next output position */
  98. caddr_t out_boundry; /* data cannot up to this address */
  99. uint32_t *frag_header; /* beginning of curren fragment */
  100. bool_t frag_sent; /* true if buffer sent in middle of record */
  101. /*
  102. * in-coming bits
  103. */
  104. int (*readit) (char *, char *, int);
  105. u_long in_size; /* fixed size of the input buffer */
  106. caddr_t in_base;
  107. caddr_t in_finger; /* location of next byte to be had */
  108. caddr_t in_boundry; /* can read up to this location */
  109. long fbtbc; /* fragment bytes to be consumed */
  110. bool_t last_frag;
  111. u_int sendsize;
  112. u_int recvsize;
  113. }
  114. RECSTREAM;
  115. static u_int fix_buf_size (u_int);
  116. static bool_t skip_input_bytes (RECSTREAM *, long);
  117. static bool_t flush_out (RECSTREAM *, bool_t);
  118. static bool_t set_input_fragment (RECSTREAM *);
  119. static bool_t get_input_bytes (RECSTREAM *, caddr_t, int);
  120. /*
  121. * Create an xdr handle for xdrrec
  122. * xdrrec_create fills in xdrs. Sendsize and recvsize are
  123. * send and recv buffer sizes (0 => use default).
  124. * tcp_handle is an opaque handle that is passed as the first parameter to
  125. * the procedures readit and writeit. Readit and writeit are read and
  126. * write respectively. They are like the system
  127. * calls expect that they take an opaque handle rather than an fd.
  128. */
  129. void
  130. xdrrec_create (XDR *xdrs, u_int sendsize,
  131. u_int recvsize, caddr_t tcp_handle,
  132. int (*readit) (char *, char *, int),
  133. int (*writeit) (char *, char *, int))
  134. {
  135. RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM));
  136. caddr_t tmp;
  137. char *buf;
  138. sendsize = fix_buf_size (sendsize);
  139. recvsize = fix_buf_size (recvsize);
  140. buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
  141. if (rstrm == NULL || buf == NULL)
  142. {
  143. (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
  144. mem_free (rstrm, sizeof (RECSTREAM));
  145. mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT);
  146. /*
  147. * This is bad. Should rework xdrrec_create to
  148. * return a handle, and in this case return NULL
  149. */
  150. return;
  151. }
  152. /*
  153. * adjust sizes and allocate buffer quad byte aligned
  154. */
  155. rstrm->sendsize = sendsize;
  156. rstrm->recvsize = recvsize;
  157. rstrm->the_buffer = buf;
  158. tmp = rstrm->the_buffer;
  159. if ((size_t)tmp % BYTES_PER_XDR_UNIT)
  160. tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT;
  161. rstrm->out_base = tmp;
  162. rstrm->in_base = tmp + sendsize;
  163. /*
  164. * now the rest ...
  165. */
  166. /* We have to add the cast since the `struct xdr_ops' in `struct XDR'
  167. is not `const'. */
  168. xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops;
  169. xdrs->x_private = (caddr_t) rstrm;
  170. rstrm->tcp_handle = tcp_handle;
  171. rstrm->readit = readit;
  172. rstrm->writeit = writeit;
  173. rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
  174. rstrm->frag_header = (uint32_t *) rstrm->out_base;
  175. rstrm->out_finger += 4;
  176. rstrm->out_boundry += sendsize;
  177. rstrm->frag_sent = FALSE;
  178. rstrm->in_size = recvsize;
  179. rstrm->in_boundry = rstrm->in_base;
  180. rstrm->in_finger = (rstrm->in_boundry += recvsize);
  181. rstrm->fbtbc = 0;
  182. rstrm->last_frag = TRUE;
  183. }
  184. libc_hidden_nolink_sunrpc (xdrrec_create, GLIBC_2_0)
  185. /*
  186. * The routines defined below are the xdr ops which will go into the
  187. * xdr handle filled in by xdrrec_create.
  188. */
  189. static bool_t
  190. xdrrec_getlong (XDR *xdrs, long *lp)
  191. {
  192. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  193. int32_t *buflp = (int32_t *) rstrm->in_finger;
  194. int32_t mylong;
  195. /* first try the inline, fast case */
  196. if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
  197. rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT)
  198. {
  199. *lp = (int32_t) ntohl (*buflp);
  200. rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
  201. rstrm->in_finger += BYTES_PER_XDR_UNIT;
  202. }
  203. else
  204. {
  205. if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong,
  206. BYTES_PER_XDR_UNIT))
  207. return FALSE;
  208. *lp = (int32_t) ntohl (mylong);
  209. }
  210. return TRUE;
  211. }
  212. static bool_t
  213. xdrrec_putlong (XDR *xdrs, const long *lp)
  214. {
  215. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  216. int32_t *dest_lp = (int32_t *) rstrm->out_finger;
  217. if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
  218. {
  219. /*
  220. * this case should almost never happen so the code is
  221. * inefficient
  222. */
  223. rstrm->out_finger -= BYTES_PER_XDR_UNIT;
  224. rstrm->frag_sent = TRUE;
  225. if (!flush_out (rstrm, FALSE))
  226. return FALSE;
  227. dest_lp = (int32_t *) rstrm->out_finger;
  228. rstrm->out_finger += BYTES_PER_XDR_UNIT;
  229. }
  230. *dest_lp = htonl (*lp);
  231. return TRUE;
  232. }
  233. static bool_t /* must manage buffers, fragments, and records */
  234. xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len)
  235. {
  236. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  237. u_int current;
  238. while (len > 0)
  239. {
  240. current = rstrm->fbtbc;
  241. if (current == 0)
  242. {
  243. if (rstrm->last_frag)
  244. return FALSE;
  245. if (!set_input_fragment (rstrm))
  246. return FALSE;
  247. continue;
  248. }
  249. current = (len < current) ? len : current;
  250. if (!get_input_bytes (rstrm, addr, current))
  251. return FALSE;
  252. addr += current;
  253. rstrm->fbtbc -= current;
  254. len -= current;
  255. }
  256. return TRUE;
  257. }
  258. static bool_t
  259. xdrrec_putbytes (XDR *xdrs, const char *addr, u_int len)
  260. {
  261. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  262. u_int current;
  263. while (len > 0)
  264. {
  265. current = rstrm->out_boundry - rstrm->out_finger;
  266. current = (len < current) ? len : current;
  267. memcpy (rstrm->out_finger, addr, current);
  268. rstrm->out_finger += current;
  269. addr += current;
  270. len -= current;
  271. if (rstrm->out_finger == rstrm->out_boundry && len > 0)
  272. {
  273. rstrm->frag_sent = TRUE;
  274. if (!flush_out (rstrm, FALSE))
  275. return FALSE;
  276. }
  277. }
  278. return TRUE;
  279. }
  280. static u_int
  281. xdrrec_getpos (const XDR *xdrs)
  282. {
  283. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  284. long pos;
  285. pos = __lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1);
  286. if (pos != -1)
  287. switch (xdrs->x_op)
  288. {
  289. case XDR_ENCODE:
  290. pos += rstrm->out_finger - rstrm->out_base;
  291. break;
  292. case XDR_DECODE:
  293. pos -= rstrm->in_boundry - rstrm->in_finger;
  294. break;
  295. default:
  296. pos = (u_int) - 1;
  297. break;
  298. }
  299. return (u_int) pos;
  300. }
  301. static bool_t
  302. xdrrec_setpos (XDR *xdrs, u_int pos)
  303. {
  304. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  305. u_int currpos = xdrrec_getpos (xdrs);
  306. int delta = currpos - pos;
  307. caddr_t newpos;
  308. if ((int) currpos != -1)
  309. switch (xdrs->x_op)
  310. {
  311. case XDR_ENCODE:
  312. newpos = rstrm->out_finger - delta;
  313. if (newpos > (caddr_t) rstrm->frag_header &&
  314. newpos < rstrm->out_boundry)
  315. {
  316. rstrm->out_finger = newpos;
  317. return TRUE;
  318. }
  319. break;
  320. case XDR_DECODE:
  321. newpos = rstrm->in_finger - delta;
  322. if ((delta < (int) (rstrm->fbtbc)) &&
  323. (newpos <= rstrm->in_boundry) &&
  324. (newpos >= rstrm->in_base))
  325. {
  326. rstrm->in_finger = newpos;
  327. rstrm->fbtbc -= delta;
  328. return TRUE;
  329. }
  330. break;
  331. default:
  332. break;
  333. }
  334. return FALSE;
  335. }
  336. static int32_t *
  337. xdrrec_inline (XDR *xdrs, u_int len)
  338. {
  339. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  340. int32_t *buf = NULL;
  341. switch (xdrs->x_op)
  342. {
  343. case XDR_ENCODE:
  344. if ((rstrm->out_finger + len) <= rstrm->out_boundry)
  345. {
  346. buf = (int32_t *) rstrm->out_finger;
  347. rstrm->out_finger += len;
  348. }
  349. break;
  350. case XDR_DECODE:
  351. if ((len <= rstrm->fbtbc) &&
  352. ((rstrm->in_finger + len) <= rstrm->in_boundry))
  353. {
  354. buf = (int32_t *) rstrm->in_finger;
  355. rstrm->fbtbc -= len;
  356. rstrm->in_finger += len;
  357. }
  358. break;
  359. default:
  360. break;
  361. }
  362. return buf;
  363. }
  364. static void
  365. xdrrec_destroy (XDR *xdrs)
  366. {
  367. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  368. mem_free (rstrm->the_buffer,
  369. rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
  370. mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
  371. }
  372. static bool_t
  373. xdrrec_getint32 (XDR *xdrs, int32_t *ip)
  374. {
  375. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  376. int32_t *bufip = (int32_t *) rstrm->in_finger;
  377. int32_t mylong;
  378. /* first try the inline, fast case */
  379. if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
  380. rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT)
  381. {
  382. *ip = ntohl (*bufip);
  383. rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
  384. rstrm->in_finger += BYTES_PER_XDR_UNIT;
  385. }
  386. else
  387. {
  388. if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong,
  389. BYTES_PER_XDR_UNIT))
  390. return FALSE;
  391. *ip = ntohl (mylong);
  392. }
  393. return TRUE;
  394. }
  395. static bool_t
  396. xdrrec_putint32 (XDR *xdrs, const int32_t *ip)
  397. {
  398. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  399. int32_t *dest_ip = (int32_t *) rstrm->out_finger;
  400. if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
  401. {
  402. /*
  403. * this case should almost never happen so the code is
  404. * inefficient
  405. */
  406. rstrm->out_finger -= BYTES_PER_XDR_UNIT;
  407. rstrm->frag_sent = TRUE;
  408. if (!flush_out (rstrm, FALSE))
  409. return FALSE;
  410. dest_ip = (int32_t *) rstrm->out_finger;
  411. rstrm->out_finger += BYTES_PER_XDR_UNIT;
  412. }
  413. *dest_ip = htonl (*ip);
  414. return TRUE;
  415. }
  416. /*
  417. * Exported routines to manage xdr records
  418. */
  419. /*
  420. * Before reading (deserializing from the stream, one should always call
  421. * this procedure to guarantee proper record alignment.
  422. */
  423. bool_t
  424. xdrrec_skiprecord (XDR *xdrs)
  425. {
  426. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  427. while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
  428. {
  429. if (!skip_input_bytes (rstrm, rstrm->fbtbc))
  430. return FALSE;
  431. rstrm->fbtbc = 0;
  432. if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
  433. return FALSE;
  434. }
  435. rstrm->last_frag = FALSE;
  436. return TRUE;
  437. }
  438. libc_hidden_nolink_sunrpc (xdrrec_skiprecord, GLIBC_2_0)
  439. /*
  440. * Lookahead function.
  441. * Returns TRUE iff there is no more input in the buffer
  442. * after consuming the rest of the current record.
  443. */
  444. bool_t
  445. xdrrec_eof (XDR *xdrs)
  446. {
  447. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  448. while (rstrm->fbtbc > 0 || (!rstrm->last_frag))
  449. {
  450. if (!skip_input_bytes (rstrm, rstrm->fbtbc))
  451. return TRUE;
  452. rstrm->fbtbc = 0;
  453. if ((!rstrm->last_frag) && (!set_input_fragment (rstrm)))
  454. return TRUE;
  455. }
  456. if (rstrm->in_finger == rstrm->in_boundry)
  457. return TRUE;
  458. return FALSE;
  459. }
  460. libc_hidden_nolink_sunrpc (xdrrec_eof, GLIBC_2_0)
  461. /*
  462. * The client must tell the package when an end-of-record has occurred.
  463. * The second parameter tells whether the record should be flushed to the
  464. * (output) tcp stream. (This lets the package support batched or
  465. * pipelined procedure calls.) TRUE => immediate flush to tcp connection.
  466. */
  467. bool_t
  468. xdrrec_endofrecord (XDR *xdrs, bool_t sendnow)
  469. {
  470. RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
  471. u_long len; /* fragment length */
  472. if (sendnow || rstrm->frag_sent
  473. || rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry)
  474. {
  475. rstrm->frag_sent = FALSE;
  476. return flush_out (rstrm, TRUE);
  477. }
  478. len = (rstrm->out_finger - (char *) rstrm->frag_header
  479. - BYTES_PER_XDR_UNIT);
  480. *rstrm->frag_header = htonl ((u_long) len | LAST_FRAG);
  481. rstrm->frag_header = (uint32_t *) rstrm->out_finger;
  482. rstrm->out_finger += BYTES_PER_XDR_UNIT;
  483. return TRUE;
  484. }
  485. libc_hidden_nolink_sunrpc (xdrrec_endofrecord, GLIBC_2_0)
  486. /*
  487. * Internal useful routines
  488. */
  489. static bool_t
  490. flush_out (RECSTREAM *rstrm, bool_t eor)
  491. {
  492. u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
  493. u_long len = (rstrm->out_finger - (char *) rstrm->frag_header
  494. - BYTES_PER_XDR_UNIT);
  495. *rstrm->frag_header = htonl (len | eormask);
  496. len = rstrm->out_finger - rstrm->out_base;
  497. if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len)
  498. != (int) len)
  499. return FALSE;
  500. rstrm->frag_header = (uint32_t *) rstrm->out_base;
  501. rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT;
  502. return TRUE;
  503. }
  504. static bool_t /* knows nothing about records! Only about input buffers */
  505. fill_input_buf (RECSTREAM *rstrm)
  506. {
  507. caddr_t where;
  508. size_t i;
  509. int len;
  510. where = rstrm->in_base;
  511. i = (size_t) rstrm->in_boundry % BYTES_PER_XDR_UNIT;
  512. where += i;
  513. len = rstrm->in_size - i;
  514. if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1)
  515. return FALSE;
  516. rstrm->in_finger = where;
  517. where += len;
  518. rstrm->in_boundry = where;
  519. return TRUE;
  520. }
  521. static bool_t /* knows nothing about records! Only about input buffers */
  522. get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len)
  523. {
  524. int current;
  525. while (len > 0)
  526. {
  527. current = rstrm->in_boundry - rstrm->in_finger;
  528. if (current == 0)
  529. {
  530. if (!fill_input_buf (rstrm))
  531. return FALSE;
  532. continue;
  533. }
  534. current = (len < current) ? len : current;
  535. memcpy (addr, rstrm->in_finger, current);
  536. rstrm->in_finger += current;
  537. addr += current;
  538. len -= current;
  539. }
  540. return TRUE;
  541. }
  542. static bool_t /* next two bytes of the input stream are treated as a header */
  543. set_input_fragment (RECSTREAM *rstrm)
  544. {
  545. uint32_t header;
  546. if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT))
  547. return FALSE;
  548. header = ntohl (header);
  549. rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
  550. /*
  551. * Sanity check. Try not to accept wildly incorrect fragment
  552. * sizes. Unfortunately, only a size of zero can be identified as
  553. * 'wildely incorrect', and this only, if it is not the last
  554. * fragment of a message. Ridiculously large fragment sizes may look
  555. * wrong, but we don't have any way to be certain that they aren't
  556. * what the client actually intended to send us. Many existing RPC
  557. * implementations may sent a fragment of size zero as the last
  558. * fragment of a message.
  559. */
  560. if (header == 0)
  561. return FALSE;
  562. rstrm->fbtbc = header & ~LAST_FRAG;
  563. return TRUE;
  564. }
  565. static bool_t /* consumes input bytes; knows nothing about records! */
  566. skip_input_bytes (RECSTREAM *rstrm, long cnt)
  567. {
  568. int current;
  569. while (cnt > 0)
  570. {
  571. current = rstrm->in_boundry - rstrm->in_finger;
  572. if (current == 0)
  573. {
  574. if (!fill_input_buf (rstrm))
  575. return FALSE;
  576. continue;
  577. }
  578. current = (cnt < current) ? cnt : current;
  579. rstrm->in_finger += current;
  580. cnt -= current;
  581. }
  582. return TRUE;
  583. }
  584. static u_int
  585. fix_buf_size (u_int s)
  586. {
  587. if (s < 100)
  588. s = 4000;
  589. return RNDUP (s);
  590. }