3 * Copyright (C) 1999 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
32 /* Tests whether a position is valid */
33 #define GETP_VALID(S,G) \
35 #define PUT_AT_VALID(S,G) GETP_VALID(S,G)
36 #define ENDP_VALID(S,E) \
39 /* asserting sanity checks. Following must be true before
40 * stream functions are called:
42 * Following must always be true of stream elements
43 * before and after calls to stream functions:
45 * getp <= endp <= size
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
51 * It is valid to put to anywhere within the size of the stream, but only
52 * using stream_put..._at() functions.
54 #define STREAM_WARN_OFFSETS(S) \
55 zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
57 (unsigned long) (S)->size, \
58 (unsigned long) (S)->getp, \
59 (unsigned long) (S)->endp)\
61 #define STREAM_VERIFY_SANE(S) \
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) ); \
69 #define STREAM_BOUND_WARN(S, WHAT) \
71 zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \
72 STREAM_WARN_OFFSETS(S); \
76 /* XXX: Deprecated macro: do not use */
77 #define CHECK_SIZE(S, Z) \
79 if (((S)->endp + (Z)) > (S)->size) \
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; \
88 /* Make stream buffer. */
90 stream_new (size_t size)
98 zlog_warn ("stream_new(): called with 0 size!");
102 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
107 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
109 XFREE (MTYPE_STREAM, s);
119 stream_free (struct stream *s)
124 XFREE (MTYPE_STREAM_DATA, s->data);
125 XFREE (MTYPE_STREAM, s);
129 stream_copy (struct stream *new, struct stream *src)
131 STREAM_VERIFY_SANE (src);
133 assert (new != NULL);
134 assert (STREAM_SIZE(new) >= src->endp);
136 new->endp = src->endp;
137 new->getp = src->getp;
139 memcpy (new->data, src->data, src->endp);
145 stream_dup (struct stream *s)
149 STREAM_VERIFY_SANE (s);
151 if ( (new = stream_new (s->endp)) == NULL)
154 return (stream_copy (new, s));
158 stream_dupcat (struct stream *s1, struct stream *s2, size_t offset)
162 STREAM_VERIFY_SANE (s1);
163 STREAM_VERIFY_SANE (s2);
165 if ( (new = stream_new (s1->endp + s2->endp)) == NULL)
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;
177 stream_resize (struct stream *s, size_t newsize)
180 STREAM_VERIFY_SANE (s);
182 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
190 if (s->endp > s->size)
192 if (s->getp > s->endp)
195 STREAM_VERIFY_SANE (s);
201 stream_get_getp (struct stream *s)
203 STREAM_VERIFY_SANE(s);
208 stream_get_endp (struct stream *s)
210 STREAM_VERIFY_SANE(s);
215 stream_get_size (struct stream *s)
217 STREAM_VERIFY_SANE(s);
221 /* Stream structre' stream pointer related functions. */
223 stream_set_getp (struct stream *s, size_t pos)
225 STREAM_VERIFY_SANE(s);
227 if (!GETP_VALID (s, pos))
229 STREAM_BOUND_WARN (s, "set getp");
237 stream_set_endp (struct stream *s, size_t pos)
239 STREAM_VERIFY_SANE(s);
241 if (!ENDP_VALID(s, pos))
243 STREAM_BOUND_WARN (s, "set endp");
248 * Make sure the current read pointer is not beyond the new endp.
252 STREAM_BOUND_WARN(s, "set endp");
257 STREAM_VERIFY_SANE(s);
260 /* Forward pointer. */
262 stream_forward_getp (struct stream *s, size_t size)
264 STREAM_VERIFY_SANE(s);
266 if (!GETP_VALID (s, s->getp + size))
268 STREAM_BOUND_WARN (s, "seek getp");
276 stream_forward_endp (struct stream *s, size_t size)
278 STREAM_VERIFY_SANE(s);
280 if (!ENDP_VALID (s, s->endp + size))
282 STREAM_BOUND_WARN (s, "seek endp");
289 /* Copy from stream to destination. */
291 stream_get (void *dst, struct stream *s, size_t size)
293 STREAM_VERIFY_SANE(s);
295 if (STREAM_READABLE(s) < size)
297 STREAM_BOUND_WARN (s, "get");
301 memcpy (dst, s->data + s->getp, size);
305 /* Get next character from the stream. */
307 stream_getc (struct stream *s)
311 STREAM_VERIFY_SANE (s);
313 if (STREAM_READABLE(s) < sizeof (u_char))
315 STREAM_BOUND_WARN (s, "get char");
318 c = s->data[s->getp++];
323 /* Get next character from the stream. */
325 stream_getc_from (struct stream *s, size_t from)
329 STREAM_VERIFY_SANE(s);
331 if (!GETP_VALID (s, from + sizeof (u_char)))
333 STREAM_BOUND_WARN (s, "get char");
342 /* Get next word from the stream. */
344 stream_getw (struct stream *s)
348 STREAM_VERIFY_SANE (s);
350 if (STREAM_READABLE (s) < sizeof (u_int16_t))
352 STREAM_BOUND_WARN (s, "get ");
356 w = s->data[s->getp++] << 8;
357 w |= s->data[s->getp++];
362 /* Get next word from the stream. */
364 stream_getw_from (struct stream *s, size_t from)
368 STREAM_VERIFY_SANE(s);
370 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
372 STREAM_BOUND_WARN (s, "get ");
376 w = s->data[from++] << 8;
382 /* Get next long word from the stream. */
384 stream_getl_from (struct stream *s, size_t from)
388 STREAM_VERIFY_SANE(s);
390 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
392 STREAM_BOUND_WARN (s, "get long");
396 l = s->data[from++] << 24;
397 l |= s->data[from++] << 16;
398 l |= s->data[from++] << 8;
405 stream_getl (struct stream *s)
409 STREAM_VERIFY_SANE(s);
411 if (STREAM_READABLE (s) < sizeof (u_int32_t))
413 STREAM_BOUND_WARN (s, "get long");
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++];
425 /* Get next quad word from the stream. */
427 stream_getq_from (struct stream *s, size_t from)
431 STREAM_VERIFY_SANE(s);
433 if (!GETP_VALID (s, from + sizeof (uint64_t)))
435 STREAM_BOUND_WARN (s, "get quad");
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++]);
452 stream_getq (struct stream *s)
456 STREAM_VERIFY_SANE(s);
458 if (STREAM_READABLE (s) < sizeof (uint64_t))
460 STREAM_BOUND_WARN (s, "get quad");
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++]);
476 /* Get next long word from the stream. */
478 stream_get_ipv4 (struct stream *s)
482 STREAM_VERIFY_SANE(s);
484 if (STREAM_READABLE (s) < sizeof(u_int32_t))
486 STREAM_BOUND_WARN (s, "get ipv4");
490 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
491 s->getp += sizeof(u_int32_t);
497 stream_getf (struct stream *s)
499 #if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
500 #warning "Unknown floating-point format, __func__ may be wrong"
502 /* we assume 'float' is in the single precision IEC 60559 binary
503 format, in host byte order */
508 u.d = stream_getl (s);
513 stream_getd (struct stream *s)
515 #if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
516 #warning "Unknown floating-point format, __func__ may be wrong"
522 u.d = stream_getq (s);
526 /* Copy to source to stream.
528 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
529 * around. This should be fixed once the stream updates are working.
531 * stream_write() is saner
534 stream_put (struct stream *s, const void *src, size_t size)
537 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
540 STREAM_VERIFY_SANE(s);
542 if (STREAM_WRITEABLE (s) < size)
544 STREAM_BOUND_WARN (s, "put");
549 memcpy (s->data + s->endp, src, size);
551 memset (s->data + s->endp, 0, size);
556 /* Put character to the stream. */
558 stream_putc (struct stream *s, u_char c)
560 STREAM_VERIFY_SANE(s);
562 if (STREAM_WRITEABLE (s) < sizeof(u_char))
564 STREAM_BOUND_WARN (s, "put");
568 s->data[s->endp++] = c;
569 return sizeof (u_char);
572 /* Put word to the stream. */
574 stream_putw (struct stream *s, u_int16_t w)
576 STREAM_VERIFY_SANE (s);
578 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
580 STREAM_BOUND_WARN (s, "put");
584 s->data[s->endp++] = (u_char)(w >> 8);
585 s->data[s->endp++] = (u_char) w;
590 /* Put long word to the stream. */
592 stream_putl (struct stream *s, u_int32_t l)
594 STREAM_VERIFY_SANE (s);
596 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
598 STREAM_BOUND_WARN (s, "put");
602 s->data[s->endp++] = (u_char)(l >> 24);
603 s->data[s->endp++] = (u_char)(l >> 16);
604 s->data[s->endp++] = (u_char)(l >> 8);
605 s->data[s->endp++] = (u_char)l;
610 /* Put quad word to the stream. */
612 stream_putq (struct stream *s, uint64_t q)
614 STREAM_VERIFY_SANE (s);
616 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
618 STREAM_BOUND_WARN (s, "put quad");
622 s->data[s->endp++] = (u_char)(q >> 56);
623 s->data[s->endp++] = (u_char)(q >> 48);
624 s->data[s->endp++] = (u_char)(q >> 40);
625 s->data[s->endp++] = (u_char)(q >> 32);
626 s->data[s->endp++] = (u_char)(q >> 24);
627 s->data[s->endp++] = (u_char)(q >> 16);
628 s->data[s->endp++] = (u_char)(q >> 8);
629 s->data[s->endp++] = (u_char)q;
635 stream_putf (struct stream *s, float f)
637 #if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
638 #warning "Unknown floating-point format, __func__ may be wrong"
641 /* we can safely assume 'float' is in the single precision
642 IEC 60559 binary format in host order */
648 return stream_putl (s, u.o);
652 stream_putd (struct stream *s, double d)
654 #if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
655 #warning "Unknown floating-point format, __func__ may be wrong"
662 return stream_putq (s, u.o);
666 stream_putc_at (struct stream *s, size_t putp, u_char c)
668 STREAM_VERIFY_SANE(s);
670 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
672 STREAM_BOUND_WARN (s, "put");
682 stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
684 STREAM_VERIFY_SANE(s);
686 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
688 STREAM_BOUND_WARN (s, "put");
692 s->data[putp] = (u_char)(w >> 8);
693 s->data[putp + 1] = (u_char) w;
699 stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
701 STREAM_VERIFY_SANE(s);
703 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
705 STREAM_BOUND_WARN (s, "put");
708 s->data[putp] = (u_char)(l >> 24);
709 s->data[putp + 1] = (u_char)(l >> 16);
710 s->data[putp + 2] = (u_char)(l >> 8);
711 s->data[putp + 3] = (u_char)l;
717 stream_putq_at (struct stream *s, size_t putp, uint64_t q)
719 STREAM_VERIFY_SANE(s);
721 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
723 STREAM_BOUND_WARN (s, "put");
726 s->data[putp] = (u_char)(q >> 56);
727 s->data[putp + 1] = (u_char)(q >> 48);
728 s->data[putp + 2] = (u_char)(q >> 40);
729 s->data[putp + 3] = (u_char)(q >> 32);
730 s->data[putp + 4] = (u_char)(q >> 24);
731 s->data[putp + 5] = (u_char)(q >> 16);
732 s->data[putp + 6] = (u_char)(q >> 8);
733 s->data[putp + 7] = (u_char)q;
738 /* Put long word to the stream. */
740 stream_put_ipv4 (struct stream *s, u_int32_t l)
742 STREAM_VERIFY_SANE(s);
744 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
746 STREAM_BOUND_WARN (s, "put");
749 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
750 s->endp += sizeof (u_int32_t);
752 return sizeof (u_int32_t);
755 /* Put long word to the stream. */
757 stream_put_in_addr (struct stream *s, struct in_addr *addr)
759 STREAM_VERIFY_SANE(s);
761 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
763 STREAM_BOUND_WARN (s, "put");
767 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
768 s->endp += sizeof (u_int32_t);
770 return sizeof (u_int32_t);
773 /* Put prefix by nlri type format. */
775 stream_put_prefix (struct stream *s, struct prefix *p)
779 STREAM_VERIFY_SANE(s);
781 psize = PSIZE (p->prefixlen);
783 if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
785 STREAM_BOUND_WARN (s, "put");
789 s->data[s->endp++] = p->prefixlen;
790 memcpy (s->data + s->endp, &p->u.prefix, psize);
796 /* Read size from fd. */
798 stream_read (struct stream *s, int fd, size_t size)
802 STREAM_VERIFY_SANE(s);
804 if (STREAM_WRITEABLE (s) < size)
806 STREAM_BOUND_WARN (s, "put");
810 nbytes = readn (fd, s->data + s->endp, size);
819 stream_read_try(struct stream *s, int fd, size_t size)
823 STREAM_VERIFY_SANE(s);
825 if (STREAM_WRITEABLE(s) < size)
827 STREAM_BOUND_WARN (s, "put");
828 /* Fatal (not transient) error, since retrying will not help
829 (stream is too small to contain the desired data). */
833 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
838 /* Error: was it transient (return -2) or fatal (return -1)? */
839 if (ERRNO_IO_RETRY(errno))
841 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
845 /* Read up to size bytes into the stream from the fd, using recvmsgfrom
846 * whose arguments match the remaining arguments to this function
849 stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
850 struct sockaddr *from, socklen_t *fromlen)
854 STREAM_VERIFY_SANE(s);
856 if (STREAM_WRITEABLE(s) < size)
858 STREAM_BOUND_WARN (s, "put");
859 /* Fatal (not transient) error, since retrying will not help
860 (stream is too small to contain the desired data). */
864 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
865 flags, from, fromlen)) >= 0)
870 /* Error: was it transient (return -2) or fatal (return -1)? */
871 if (ERRNO_IO_RETRY(errno))
873 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
877 /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
879 * First iovec will be used to receive the data.
880 * Stream need not be empty.
883 stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
889 STREAM_VERIFY_SANE(s);
890 assert (msgh->msg_iovlen > 0);
892 if (STREAM_WRITEABLE (s) < size)
894 STREAM_BOUND_WARN (s, "put");
895 /* This is a logic error in the calling code: the stream is too small
896 to hold the desired data! */
900 iov = &(msgh->msg_iov[0]);
901 iov->iov_base = (s->data + s->endp);
904 nbytes = recvmsg (fd, msgh, flags);
912 /* Write data to buffer. */
914 stream_write (struct stream *s, const void *ptr, size_t size)
919 STREAM_VERIFY_SANE(s);
921 if (STREAM_WRITEABLE (s) < size)
923 STREAM_BOUND_WARN (s, "put");
927 memcpy (s->data + s->endp, ptr, size);
933 /* Return current read pointer.
935 * Use stream_get_pnt_to if you must, but decoding streams properly
939 stream_pnt (struct stream *s)
941 STREAM_VERIFY_SANE(s);
942 return s->data + s->getp;
945 /* Check does this stream empty? */
947 stream_empty (struct stream *s)
949 STREAM_VERIFY_SANE(s);
951 return (s->endp == 0);
956 stream_reset (struct stream *s)
958 STREAM_VERIFY_SANE (s);
960 s->getp = s->endp = 0;
963 /* Discard read data (prior to the getp), and move the unread data
964 * to the beginning of the stream.
966 * See also stream_fifo_* functions, for another approach to managing
970 stream_discard (struct stream *s)
972 STREAM_VERIFY_SANE (s);
977 if (s->getp == s->endp)
983 s->data = memmove (s->data, s->data + s->getp, s->endp - s->getp);
988 /* Write stream contens to the file discriptor. */
990 stream_flush (struct stream *s, int fd)
994 STREAM_VERIFY_SANE(s);
996 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
1001 /* Stream first in first out queue. */
1003 struct stream_fifo *
1004 stream_fifo_new (void)
1006 struct stream_fifo *new;
1008 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
1012 /* Add new stream to fifo. */
1014 stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
1017 fifo->tail->next = s;
1026 /* Delete first stream from fifo. */
1028 stream_fifo_pop (struct stream_fifo *fifo)
1036 fifo->head = s->next;
1038 if (fifo->head == NULL)
1047 /* Return first fifo entry. */
1049 stream_fifo_head (struct stream_fifo *fifo)
1055 stream_fifo_clean (struct stream_fifo *fifo)
1058 struct stream *next;
1060 for (s = fifo->head; s; s = next)
1065 fifo->head = fifo->tail = NULL;
1070 stream_fifo_free (struct stream_fifo *fifo)
1072 stream_fifo_clean (fifo);
1073 XFREE (MTYPE_STREAM_FIFO, fifo);