1  /*
2 * Packet interface
3 * Copyright (C) 1999 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <stddef.h>
24#include <zebra.h>
25
26#include "stream.h"
27#include "memory.h"
28#include "network.h"
29#include "prefix.h"
30#include "log.h"
31
32/* Tests whether a position is valid */
33#define GETP_VALID(S,G) \
34  ((G) <= (S)->endp)
35#define PUT_AT_VALID(S,G) GETP_VALID(S,G)
36#define ENDP_VALID(S,E) \
37  ((E) <= (S)->size)
38
39/* asserting sanity checks. Following must be true before
40 * stream functions are called:
41 *
42 * Following must always be true of stream elements
43 * before and after calls to stream functions:
44 *
45 * getp <= endp <= size
46 *
47 * Note that after a stream function is called following may be true:
48 * if (getp == endp) then stream is no longer readable
49 * if (endp == size) then stream is no longer writeable
50 *
51 * It is valid to put to anywhere within the size of the stream, but only
52 * using stream_put..._at() functions.
53 */
54#define STREAM_WARN_OFFSETS(S) \
55  zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
56             (S), \
57             (unsigned long) (S)->size, \
58             (unsigned long) (S)->getp, \
59             (unsigned long) (S)->endp)\
60
61#define STREAM_VERIFY_SANE(S) \
62  do { \
63    if ( !(GETP_VALID(S, (S)->getp)) && ENDP_VALID(S, (S)->endp) ) \
64      STREAM_WARN_OFFSETS(S); \
65    assert ( GETP_VALID(S, (S)->getp) ); \
66    assert ( ENDP_VALID(S, (S)->endp) ); \
67  } while (0)
68
69#define STREAM_BOUND_WARN(S, WHAT) \
70  do { \
71    zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \
72    STREAM_WARN_OFFSETS(S); \
73    assert (0); \
74  } while (0)
75
76/* XXX: Deprecated macro: do not use */
77#define CHECK_SIZE(S, Z) \
78  do { \
79    if (((S)->endp + (Z)) > (S)->size) \
80      { \
81        zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \
82                   (unsigned long) (Z)); \
83        STREAM_WARN_OFFSETS(S); \
84        (Z) = (S)->size - (S)->endp; \
85      } \
86  } while (0);
87
88/* Make stream buffer. */
89struct stream *
90stream_new (size_t size)
91{
92  struct stream *s;
93
94  assert (size > 0);
95
96  if (size == 0)
97    {
98      zlog_warn ("stream_new(): called with 0 size!");
99      return NULL;
100    }
101
102  s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
103
104  if (s == NULL)
105    return s;
106
107  if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
108    {
109      XFREE (MTYPE_STREAM, s);
110      return NULL;
111    }
112
113  s->size = size;
114  return s;
115}
116
117/* Free it now. */
118void
119stream_free (struct stream *s)
120{
121  if (!s)
122    return;
123
124  XFREE (MTYPE_STREAM_DATA, s->data);
125  XFREE (MTYPE_STREAM, s);
126}
127
128struct stream *
129stream_copy (struct stream *new, struct stream *src)
130{
131  STREAM_VERIFY_SANE (src);
132
133  assert (new != NULL);
134  assert (STREAM_SIZE(new) >= src->endp);
135
136  new->endp = src->endp;
137  new->getp = src->getp;
138
139  memcpy (new->data, src->data, src->endp);
140
141  return new;
142}
143
144struct stream *
145stream_dup (struct stream *s)
146{
147  struct stream *new;
148
149  STREAM_VERIFY_SANE (s);
150
151  if ( (new = stream_new (s->endp)) == NULL)
152    return NULL;
153
154  return (stream_copy (new, s));
155}
156
157struct stream *
158stream_dupcat (struct stream *s1, struct stream *s2, size_t offset)
159{
160  struct stream *new;
161
162  STREAM_VERIFY_SANE (s1);
163  STREAM_VERIFY_SANE (s2);
164
165  if ( (new = stream_new (s1->endp + s2->endp)) == NULL)
166    return NULL;
167
168  memcpy (new->data, s1->data, offset);
169  memcpy (new->data + offset, s2->data, s2->endp);
170  memcpy (new->data + offset + s2->endp, s1->data + offset,
171	  (s1->endp - offset));
172  new->endp = s1->endp + s2->endp;
173  return new;
174}
175
176size_t
177stream_resize (struct stream *s, size_t newsize)
178{
179  u_char *newdata;
180  STREAM_VERIFY_SANE (s);
181
182  newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
183
184  if (newdata == NULL)
185    return s->size;
186
187  s->data = newdata;
188  s->size = newsize;
189
190  if (s->endp > s->size)
191    s->endp = s->size;
192  if (s->getp > s->endp)
193    s->getp = s->endp;
194
195  STREAM_VERIFY_SANE (s);
196
197  return s->size;
198}
199
200size_t
201stream_get_getp (struct stream *s)
202{
203  STREAM_VERIFY_SANE(s);
204  return s->getp;
205}
206
207size_t
208stream_get_endp (struct stream *s)
209{
210  STREAM_VERIFY_SANE(s);
211  return s->endp;
212}
213
214size_t
215stream_get_size (struct stream *s)
216{
217  STREAM_VERIFY_SANE(s);
218  return s->size;
219}
220
221/* Stream structre' stream pointer related functions.  */
222void
223stream_set_getp (struct stream *s, size_t pos)
224{
225  STREAM_VERIFY_SANE(s);
226
227  if (!GETP_VALID (s, pos))
228    {
229      STREAM_BOUND_WARN (s, "set getp");
230      pos = s->endp;
231    }
232
233  s->getp = pos;
234}
235
236void
237stream_set_endp (struct stream *s, size_t pos)
238{
239  STREAM_VERIFY_SANE(s);
240
241  if (!ENDP_VALID(s, pos))
242    {
243      STREAM_BOUND_WARN (s, "set endp");
244      return;
245    }
246
247  /*
248   * Make sure the current read pointer is not beyond the new endp.
249   */
250  if (s->getp > pos)
251    {
252      STREAM_BOUND_WARN(s, "set endp");
253      return;
254    }
255
256  s->endp = pos;
257  STREAM_VERIFY_SANE(s);
258}
259
260/* Forward pointer. */
261void
262stream_forward_getp (struct stream *s, size_t size)
263{
264  STREAM_VERIFY_SANE(s);
265
266  if (!GETP_VALID (s, s->getp + size))
267    {
268      STREAM_BOUND_WARN (s, "seek getp");
269      return;
270    }
271
272  s->getp += size;
273}
274
275void
276stream_forward_endp (struct stream *s, size_t size)
277{
278  STREAM_VERIFY_SANE(s);
279
280  if (!ENDP_VALID (s, s->endp + size))
281    {
282      STREAM_BOUND_WARN (s, "seek endp");
283      return;
284    }
285
286  s->endp += size;
287}
288
289/* Copy from stream to destination. */
290void
291stream_get (void *dst, struct stream *s, size_t size)
292{
293  STREAM_VERIFY_SANE(s);
294
295  if (STREAM_READABLE(s) < size)
296    {
297      STREAM_BOUND_WARN (s, "get");
298      return;
299    }
300
301  memcpy (dst, s->data + s->getp, size);
302  s->getp += size;
303}
304
305/* Get next character from the stream. */
306u_char
307stream_getc (struct stream *s)
308{
309  u_char c;
310
311  STREAM_VERIFY_SANE (s);
312
313  if (STREAM_READABLE(s) < sizeof (u_char))
314    {
315      STREAM_BOUND_WARN (s, "get char");
316      return 0;
317    }
318  c = s->data[s->getp++];
319
320  return c;
321}
322
323/* Get next character from the stream. */
324u_char
325stream_getc_from (struct stream *s, size_t from)
326{
327  u_char c;
328
329  STREAM_VERIFY_SANE(s);
330
331  if (!GETP_VALID (s, from + sizeof (u_char)))
332    {
333      STREAM_BOUND_WARN (s, "get char");
334      return 0;
335    }
336
337  c = s->data[from];
338
339  return c;
340}
341
342/* Get next word from the stream. */
343u_int16_t
344stream_getw (struct stream *s)
345{
346  u_int16_t w;
347
348  STREAM_VERIFY_SANE (s);
349
350  if (STREAM_READABLE (s) < sizeof (u_int16_t))
351    {
352      STREAM_BOUND_WARN (s, "get ");
353      return 0;
354    }
355
356  w = s->data[s->getp++] << 8;
357  w |= s->data[s->getp++];
358
359  return w;
360}
361
362/* Get next word from the stream. */
363u_int16_t
364stream_getw_from (struct stream *s, size_t from)
365{
366  u_int16_t w;
367
368  STREAM_VERIFY_SANE(s);
369
370  if (!GETP_VALID (s, from + sizeof (u_int16_t)))
371    {
372      STREAM_BOUND_WARN (s, "get ");
373      return 0;
374    }
375
376  w = s->data[from++] << 8;
377  w |= s->data[from];
378
379  return w;
380}
381
382/* Get next long word from the stream. */
383u_int32_t
384stream_getl_from (struct stream *s, size_t from)
385{
386  u_int32_t l;
387
388  STREAM_VERIFY_SANE(s);
389
390  if (!GETP_VALID (s, from + sizeof (u_int32_t)))
391    {
392      STREAM_BOUND_WARN (s, "get long");
393      return 0;
394    }
395
396  l  = s->data[from++] << 24;
397  l |= s->data[from++] << 16;
398  l |= s->data[from++] << 8;
399  l |= s->data[from];
400
401  return l;
402}
403
404u_int32_t
405stream_getl (struct stream *s)
406{
407  u_int32_t l;
408
409  STREAM_VERIFY_SANE(s);
410
411  if (STREAM_READABLE (s) < sizeof (u_int32_t))
412    {
413      STREAM_BOUND_WARN (s, "get long");
414      return 0;
415    }
416
417  l  = s->data[s->getp++] << 24;
418  l |= s->data[s->getp++] << 16;
419  l |= s->data[s->getp++] << 8;
420  l |= s->data[s->getp++];
421
422  return l;
423}
424
425/* Get next quad word from the stream. */
426uint64_t
427stream_getq_from (struct stream *s, size_t from)
428{
429  uint64_t q;
430
431  STREAM_VERIFY_SANE(s);
432
433  if (!GETP_VALID (s, from + sizeof (uint64_t)))
434    {
435      STREAM_BOUND_WARN (s, "get quad");
436      return 0;
437    }
438
439  q  = ((uint64_t) s->data[from++]) << 56;
440  q |= ((uint64_t) s->data[from++]) << 48;
441  q |= ((uint64_t) s->data[from++]) << 40;
442  q |= ((uint64_t) s->data[from++]) << 32;
443  q |= ((uint64_t) s->data[from++]) << 24;
444  q |= ((uint64_t) s->data[from++]) << 16;
445  q |= ((uint64_t) s->data[from++]) << 8;
446  q |= ((uint64_t) s->data[from++]);
447
448  return q;
449}
450
451uint64_t
452stream_getq (struct stream *s)
453{
454  uint64_t q;
455
456  STREAM_VERIFY_SANE(s);
457
458  if (STREAM_READABLE (s) < sizeof (uint64_t))
459    {
460      STREAM_BOUND_WARN (s, "get quad");
461      return 0;
462    }
463
464  q  = ((uint64_t) s->data[s->getp++]) << 56;
465  q |= ((uint64_t) s->data[s->getp++]) << 48;
466  q |= ((uint64_t) s->data[s->getp++]) << 40;
467  q |= ((uint64_t) s->data[s->getp++]) << 32;
468  q |= ((uint64_t) s->data[s->getp++]) << 24;
469  q |= ((uint64_t) s->data[s->getp++]) << 16;
470  q |= ((uint64_t) s->data[s->getp++]) << 8;
471  q |= ((uint64_t) s->data[s->getp++]);
472
473  return q;
474}
475
476/* Get next long word from the stream. */
477u_int32_t
478stream_get_ipv4 (struct stream *s)
479{
480  u_int32_t l;
481
482  STREAM_VERIFY_SANE(s);
483
484  if (STREAM_READABLE (s) < sizeof(u_int32_t))
485    {
486      STREAM_BOUND_WARN (s, "get ipv4");
487      return 0;
488    }
489
490  memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
491  s->getp += sizeof(u_int32_t);
492
493  return l;
494}
495
496/* Copy to source to stream.
497 *
498 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
499 * around. This should be fixed once the stream updates are working.
500 *
501 * stream_write() is saner
502 */
503void
504stream_put (struct stream *s, const void *src, size_t size)
505{
506
507  /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
508  CHECK_SIZE(s, size);
509
510  STREAM_VERIFY_SANE(s);
511
512  if (STREAM_WRITEABLE (s) < size)
513    {
514      STREAM_BOUND_WARN (s, "put");
515      return;
516    }
517
518  if (src)
519    memcpy (s->data + s->endp, src, size);
520  else
521    memset (s->data + s->endp, 0, size);
522
523  s->endp += size;
524}
525
526/* Put character to the stream. */
527int
528stream_putc (struct stream *s, u_char c)
529{
530  STREAM_VERIFY_SANE(s);
531
532  if (STREAM_WRITEABLE (s) < sizeof(u_char))
533    {
534      STREAM_BOUND_WARN (s, "put");
535      return 0;
536    }
537
538  s->data[s->endp++] = c;
539  return sizeof (u_char);
540}
541
542/* Put word to the stream. */
543int
544stream_putw (struct stream *s, u_int16_t w)
545{
546  STREAM_VERIFY_SANE (s);
547
548  if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
549    {
550      STREAM_BOUND_WARN (s, "put");
551      return 0;
552    }
553
554  s->data[s->endp++] = (u_char)(w >>  8);
555  s->data[s->endp++] = (u_char) w;
556
557  return 2;
558}
559
560/* Put long word to the stream. */
561int
562stream_putl (struct stream *s, u_int32_t l)
563{
564  STREAM_VERIFY_SANE (s);
565
566  if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
567    {
568      STREAM_BOUND_WARN (s, "put");
569      return 0;
570    }
571
572  s->data[s->endp++] = (u_char)(l >> 24);
573  s->data[s->endp++] = (u_char)(l >> 16);
574  s->data[s->endp++] = (u_char)(l >>  8);
575  s->data[s->endp++] = (u_char)l;
576
577  return 4;
578}
579
580/* Put quad word to the stream. */
581int
582stream_putq (struct stream *s, uint64_t q)
583{
584  STREAM_VERIFY_SANE (s);
585
586  if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
587    {
588      STREAM_BOUND_WARN (s, "put quad");
589      return 0;
590    }
591
592  s->data[s->endp++] = (u_char)(q >> 56);
593  s->data[s->endp++] = (u_char)(q >> 48);
594  s->data[s->endp++] = (u_char)(q >> 40);
595  s->data[s->endp++] = (u_char)(q >> 32);
596  s->data[s->endp++] = (u_char)(q >> 24);
597  s->data[s->endp++] = (u_char)(q >> 16);
598  s->data[s->endp++] = (u_char)(q >>  8);
599  s->data[s->endp++] = (u_char)q;
600
601  return 8;
602}
603
604int
605stream_putc_at (struct stream *s, size_t putp, u_char c)
606{
607  STREAM_VERIFY_SANE(s);
608
609  if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
610    {
611      STREAM_BOUND_WARN (s, "put");
612      return 0;
613    }
614
615  s->data[putp] = c;
616
617  return 1;
618}
619
620int
621stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
622{
623  STREAM_VERIFY_SANE(s);
624
625  if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
626    {
627      STREAM_BOUND_WARN (s, "put");
628      return 0;
629    }
630
631  s->data[putp] = (u_char)(w >>  8);
632  s->data[putp + 1] = (u_char) w;
633
634  return 2;
635}
636
637int
638stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
639{
640  STREAM_VERIFY_SANE(s);
641
642  if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
643    {
644      STREAM_BOUND_WARN (s, "put");
645      return 0;
646    }
647  s->data[putp] = (u_char)(l >> 24);
648  s->data[putp + 1] = (u_char)(l >> 16);
649  s->data[putp + 2] = (u_char)(l >>  8);
650  s->data[putp + 3] = (u_char)l;
651
652  return 4;
653}
654
655int
656stream_putq_at (struct stream *s, size_t putp, uint64_t q)
657{
658  STREAM_VERIFY_SANE(s);
659
660  if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
661    {
662      STREAM_BOUND_WARN (s, "put");
663      return 0;
664    }
665  s->data[putp] =     (u_char)(q >> 56);
666  s->data[putp + 1] = (u_char)(q >> 48);
667  s->data[putp + 2] = (u_char)(q >> 40);
668  s->data[putp + 3] = (u_char)(q >> 32);
669  s->data[putp + 4] = (u_char)(q >> 24);
670  s->data[putp + 5] = (u_char)(q >> 16);
671  s->data[putp + 6] = (u_char)(q >>  8);
672  s->data[putp + 7] = (u_char)q;
673
674  return 8;
675}
676
677/* Put long word to the stream. */
678int
679stream_put_ipv4 (struct stream *s, u_int32_t l)
680{
681  STREAM_VERIFY_SANE(s);
682
683  if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
684    {
685      STREAM_BOUND_WARN (s, "put");
686      return 0;
687    }
688  memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
689  s->endp += sizeof (u_int32_t);
690
691  return sizeof (u_int32_t);
692}
693
694/* Put long word to the stream. */
695int
696stream_put_in_addr (struct stream *s, struct in_addr *addr)
697{
698  STREAM_VERIFY_SANE(s);
699
700  if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
701    {
702      STREAM_BOUND_WARN (s, "put");
703      return 0;
704    }
705
706  memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
707  s->endp += sizeof (u_int32_t);
708
709  return sizeof (u_int32_t);
710}
711
712/* Put prefix by nlri type format. */
713int
714stream_put_prefix (struct stream *s, struct prefix *p)
715{
716  size_t psize;
717
718  STREAM_VERIFY_SANE(s);
719
720  psize = PSIZE (p->prefixlen);
721
722  if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
723    {
724      STREAM_BOUND_WARN (s, "put");
725      return 0;
726    }
727
728  s->data[s->endp++] = p->prefixlen;
729  memcpy (s->data + s->endp, &p->u.prefix, psize);
730  s->endp += psize;
731
732  return psize;
733}
734
735/* Read size from fd. */
736int
737stream_read (struct stream *s, int fd, size_t size)
738{
739  int nbytes;
740
741  STREAM_VERIFY_SANE(s);
742
743  if (STREAM_WRITEABLE (s) < size)
744    {
745      STREAM_BOUND_WARN (s, "put");
746      return 0;
747    }
748
749  nbytes = readn (fd, s->data + s->endp, size);
750
751  if (nbytes > 0)
752    s->endp += nbytes;
753
754  return nbytes;
755}
756
757ssize_t
758stream_read_try(struct stream *s, int fd, size_t size)
759{
760  ssize_t nbytes;
761
762  STREAM_VERIFY_SANE(s);
763
764  if (STREAM_WRITEABLE(s) < size)
765    {
766      STREAM_BOUND_WARN (s, "put");
767      /* Fatal (not transient) error, since retrying will not help
768         (stream is too small to contain the desired data). */
769      return -1;
770    }
771
772  if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
773    {
774      s->endp += nbytes;
775      return nbytes;
776    }
777  /* Error: was it transient (return -2) or fatal (return -1)? */
778  if (ERRNO_IO_RETRY(errno))
779    return -2;
780  zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
781  return -1;
782}
783
784/* Read up to size bytes into the stream from the fd, using recvmsgfrom
785 * whose arguments match the remaining arguments to this function
786 */
787ssize_t
788stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
789                 struct sockaddr *from, socklen_t *fromlen)
790{
791  ssize_t nbytes;
792
793  STREAM_VERIFY_SANE(s);
794
795  if (STREAM_WRITEABLE(s) < size)
796    {
797      STREAM_BOUND_WARN (s, "put");
798      /* Fatal (not transient) error, since retrying will not help
799         (stream is too small to contain the desired data). */
800      return -1;
801    }
802
803  if ((nbytes = recvfrom (fd, s->data + s->endp, size,
804                          flags, from, fromlen)) >= 0)
805    {
806      s->endp += nbytes;
807      return nbytes;
808    }
809  /* Error: was it transient (return -2) or fatal (return -1)? */
810  if (ERRNO_IO_RETRY(errno))
811    return -2;
812  zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
813  return -1;
814}
815
816/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
817 * from endp.
818 * First iovec will be used to receive the data.
819 * Stream need not be empty.
820 */
821ssize_t
822stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
823                size_t size)
824{
825  int nbytes;
826  struct iovec *iov;
827
828  STREAM_VERIFY_SANE(s);
829  assert (msgh->msg_iovlen > 0);
830
831  if (STREAM_WRITEABLE (s) < size)
832    {
833      STREAM_BOUND_WARN (s, "put");
834      /* This is a logic error in the calling code: the stream is too small
835         to hold the desired data! */
836      return -1;
837    }
838
839  iov = &(msgh->msg_iov[0]);
840  iov->iov_base = (s->data + s->endp);
841  iov->iov_len = size;
842
843  nbytes = recvmsg (fd, msgh, flags);
844
845  if (nbytes > 0)
846    s->endp += nbytes;
847
848  return nbytes;
849}
850
851/* Write data to buffer. */
852size_t
853stream_write (struct stream *s, const void *ptr, size_t size)
854{
855
856  CHECK_SIZE(s, size);
857
858  STREAM_VERIFY_SANE(s);
859
860  if (STREAM_WRITEABLE (s) < size)
861    {
862      STREAM_BOUND_WARN (s, "put");
863      return 0;
864    }
865
866  memcpy (s->data + s->endp, ptr, size);
867  s->endp += size;
868
869  return size;
870}
871
872/* Return current read pointer.
873 * DEPRECATED!
874 * Use stream_get_pnt_to if you must, but decoding streams properly
875 * is preferred
876 */
877u_char *
878stream_pnt (struct stream *s)
879{
880  STREAM_VERIFY_SANE(s);
881  return s->data + s->getp;
882}
883
884/* Check does this stream empty? */
885int
886stream_empty (struct stream *s)
887{
888  STREAM_VERIFY_SANE(s);
889
890  return (s->endp == 0);
891}
892
893/* Reset stream. */
894void
895stream_reset (struct stream *s)
896{
897  STREAM_VERIFY_SANE (s);
898
899  s->getp = s->endp = 0;
900}
901
902/* Write stream contens to the file discriptor. */
903int
904stream_flush (struct stream *s, int fd)
905{
906  int nbytes;
907
908  STREAM_VERIFY_SANE(s);
909
910  nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
911
912  return nbytes;
913}
914
915/* Stream first in first out queue. */
916
917struct stream_fifo *
918stream_fifo_new (void)
919{
920  struct stream_fifo *new;
921
922  new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
923  return new;
924}
925
926/* Add new stream to fifo. */
927void
928stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
929{
930  if (fifo->tail)
931    fifo->tail->next = s;
932  else
933    fifo->head = s;
934
935  fifo->tail = s;
936
937  fifo->count++;
938}
939
940/* Delete first stream from fifo. */
941struct stream *
942stream_fifo_pop (struct stream_fifo *fifo)
943{
944  struct stream *s;
945
946  s = fifo->head;
947
948  if (s)
949    {
950      fifo->head = s->next;
951
952      if (fifo->head == NULL)
953	fifo->tail = NULL;
954
955      fifo->count--;
956    }
957
958  return s;
959}
960
961/* Return first fifo entry. */
962struct stream *
963stream_fifo_head (struct stream_fifo *fifo)
964{
965  return fifo->head;
966}
967
968void
969stream_fifo_clean (struct stream_fifo *fifo)
970{
971  struct stream *s;
972  struct stream *next;
973
974  for (s = fifo->head; s; s = next)
975    {
976      next = s->next;
977      stream_free (s);
978    }
979  fifo->head = fifo->tail = NULL;
980  fifo->count = 0;
981}
982
983void
984stream_fifo_free (struct stream_fifo *fifo)
985{
986  stream_fifo_clean (fifo);
987  XFREE (MTYPE_STREAM_FIFO, fifo);
988}
989