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, endp: %lu, getp: %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_resize (struct stream
*s
, size_t newsize
)
161 STREAM_VERIFY_SANE (s
);
163 newdata
= XREALLOC (MTYPE_STREAM_DATA
, s
->data
, newsize
);
171 if (s
->endp
> s
->size
)
173 if (s
->getp
> s
->endp
)
176 STREAM_VERIFY_SANE (s
);
182 stream_get_getp (struct stream
*s
)
184 STREAM_VERIFY_SANE(s
);
189 stream_get_endp (struct stream
*s
)
191 STREAM_VERIFY_SANE(s
);
196 stream_get_size (struct stream
*s
)
198 STREAM_VERIFY_SANE(s
);
202 /* Stream structre' stream pointer related functions. */
204 stream_set_getp (struct stream
*s
, size_t pos
)
206 STREAM_VERIFY_SANE(s
);
208 if (!GETP_VALID (s
, pos
))
210 STREAM_BOUND_WARN (s
, "set getp");
217 /* Forward pointer. */
219 stream_forward_getp (struct stream
*s
, size_t size
)
221 STREAM_VERIFY_SANE(s
);
223 if (!GETP_VALID (s
, s
->getp
+ size
))
225 STREAM_BOUND_WARN (s
, "seek getp");
233 stream_forward_endp (struct stream
*s
, size_t size
)
235 STREAM_VERIFY_SANE(s
);
237 if (!ENDP_VALID (s
, s
->endp
+ size
))
239 STREAM_BOUND_WARN (s
, "seek endp");
246 /* Copy from stream to destination. */
248 stream_get (void *dst
, struct stream
*s
, size_t size
)
250 STREAM_VERIFY_SANE(s
);
252 if (STREAM_READABLE(s
) < size
)
254 STREAM_BOUND_WARN (s
, "get");
258 memcpy (dst
, s
->data
+ s
->getp
, size
);
262 /* Get next character from the stream. */
264 stream_getc (struct stream
*s
)
268 STREAM_VERIFY_SANE (s
);
270 if (STREAM_READABLE(s
) < sizeof (u_char
))
272 STREAM_BOUND_WARN (s
, "get char");
275 c
= s
->data
[s
->getp
++];
280 /* Get next character from the stream. */
282 stream_getc_from (struct stream
*s
, size_t from
)
286 STREAM_VERIFY_SANE(s
);
288 if (!GETP_VALID (s
, from
+ sizeof (u_char
)))
290 STREAM_BOUND_WARN (s
, "get char");
299 /* Get next word from the stream. */
301 stream_getw (struct stream
*s
)
305 STREAM_VERIFY_SANE (s
);
307 if (STREAM_READABLE (s
) < sizeof (u_int16_t
))
309 STREAM_BOUND_WARN (s
, "get ");
313 w
= s
->data
[s
->getp
++] << 8;
314 w
|= s
->data
[s
->getp
++];
319 /* Get next word from the stream. */
321 stream_getw_from (struct stream
*s
, size_t from
)
325 STREAM_VERIFY_SANE(s
);
327 if (!GETP_VALID (s
, from
+ sizeof (u_int16_t
)))
329 STREAM_BOUND_WARN (s
, "get ");
333 w
= s
->data
[from
++] << 8;
339 /* Get next long word from the stream. */
341 stream_getl_from (struct stream
*s
, size_t from
)
345 STREAM_VERIFY_SANE(s
);
347 if (!GETP_VALID (s
, from
+ sizeof (u_int32_t
)))
349 STREAM_BOUND_WARN (s
, "get long");
353 l
= s
->data
[from
++] << 24;
354 l
|= s
->data
[from
++] << 16;
355 l
|= s
->data
[from
++] << 8;
362 stream_getl (struct stream
*s
)
366 STREAM_VERIFY_SANE(s
);
368 if (STREAM_READABLE (s
) < sizeof (u_int32_t
))
370 STREAM_BOUND_WARN (s
, "get long");
374 l
= s
->data
[s
->getp
++] << 24;
375 l
|= s
->data
[s
->getp
++] << 16;
376 l
|= s
->data
[s
->getp
++] << 8;
377 l
|= s
->data
[s
->getp
++];
382 /* Get next quad word from the stream. */
384 stream_getq_from (struct stream
*s
, size_t from
)
388 STREAM_VERIFY_SANE(s
);
390 if (!GETP_VALID (s
, from
+ sizeof (uint64_t)))
392 STREAM_BOUND_WARN (s
, "get quad");
396 q
= ((uint64_t) s
->data
[from
++]) << 56;
397 q
|= ((uint64_t) s
->data
[from
++]) << 48;
398 q
|= ((uint64_t) s
->data
[from
++]) << 40;
399 q
|= ((uint64_t) s
->data
[from
++]) << 32;
400 q
|= ((uint64_t) s
->data
[from
++]) << 24;
401 q
|= ((uint64_t) s
->data
[from
++]) << 16;
402 q
|= ((uint64_t) s
->data
[from
++]) << 8;
403 q
|= ((uint64_t) s
->data
[from
++]);
409 stream_getq (struct stream
*s
)
413 STREAM_VERIFY_SANE(s
);
415 if (STREAM_READABLE (s
) < sizeof (uint64_t))
417 STREAM_BOUND_WARN (s
, "get quad");
421 q
= ((uint64_t) s
->data
[s
->getp
++]) << 56;
422 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 48;
423 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 40;
424 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 32;
425 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 24;
426 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 16;
427 q
|= ((uint64_t) s
->data
[s
->getp
++]) << 8;
428 q
|= ((uint64_t) s
->data
[s
->getp
++]);
433 /* Get next long word from the stream. */
435 stream_get_ipv4 (struct stream
*s
)
439 STREAM_VERIFY_SANE(s
);
441 if (STREAM_READABLE (s
) < sizeof(u_int32_t
))
443 STREAM_BOUND_WARN (s
, "get ipv4");
447 memcpy (&l
, s
->data
+ s
->getp
, sizeof(u_int32_t
));
448 s
->getp
+= sizeof(u_int32_t
);
453 /* Copy to source to stream.
455 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
456 * around. This should be fixed once the stream updates are working.
458 * stream_write() is saner
461 stream_put (struct stream
*s
, void *src
, size_t size
)
464 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
467 STREAM_VERIFY_SANE(s
);
469 if (STREAM_WRITEABLE (s
) < size
)
471 STREAM_BOUND_WARN (s
, "put");
476 memcpy (s
->data
+ s
->endp
, src
, size
);
478 memset (s
->data
+ s
->endp
, 0, size
);
483 /* Put character to the stream. */
485 stream_putc (struct stream
*s
, u_char c
)
487 STREAM_VERIFY_SANE(s
);
489 if (STREAM_WRITEABLE (s
) < sizeof(u_char
))
491 STREAM_BOUND_WARN (s
, "put");
495 s
->data
[s
->endp
++] = c
;
496 return sizeof (u_char
);
499 /* Put word to the stream. */
501 stream_putw (struct stream
*s
, u_int16_t w
)
503 STREAM_VERIFY_SANE (s
);
505 if (STREAM_WRITEABLE (s
) < sizeof (u_int16_t
))
507 STREAM_BOUND_WARN (s
, "put");
511 s
->data
[s
->endp
++] = (u_char
)(w
>> 8);
512 s
->data
[s
->endp
++] = (u_char
) w
;
517 /* Put long word to the stream. */
519 stream_putl (struct stream
*s
, u_int32_t l
)
521 STREAM_VERIFY_SANE (s
);
523 if (STREAM_WRITEABLE (s
) < sizeof (u_int32_t
))
525 STREAM_BOUND_WARN (s
, "put");
529 s
->data
[s
->endp
++] = (u_char
)(l
>> 24);
530 s
->data
[s
->endp
++] = (u_char
)(l
>> 16);
531 s
->data
[s
->endp
++] = (u_char
)(l
>> 8);
532 s
->data
[s
->endp
++] = (u_char
)l
;
537 /* Put quad word to the stream. */
539 stream_putq (struct stream
*s
, uint64_t q
)
541 STREAM_VERIFY_SANE (s
);
543 if (STREAM_WRITEABLE (s
) < sizeof (uint64_t))
545 STREAM_BOUND_WARN (s
, "put quad");
549 s
->data
[s
->endp
++] = (u_char
)(q
>> 56);
550 s
->data
[s
->endp
++] = (u_char
)(q
>> 48);
551 s
->data
[s
->endp
++] = (u_char
)(q
>> 40);
552 s
->data
[s
->endp
++] = (u_char
)(q
>> 32);
553 s
->data
[s
->endp
++] = (u_char
)(q
>> 24);
554 s
->data
[s
->endp
++] = (u_char
)(q
>> 16);
555 s
->data
[s
->endp
++] = (u_char
)(q
>> 8);
556 s
->data
[s
->endp
++] = (u_char
)q
;
562 stream_putc_at (struct stream
*s
, size_t putp
, u_char c
)
564 STREAM_VERIFY_SANE(s
);
566 if (!PUT_AT_VALID (s
, putp
+ sizeof (u_char
)))
568 STREAM_BOUND_WARN (s
, "put");
578 stream_putw_at (struct stream
*s
, size_t putp
, u_int16_t w
)
580 STREAM_VERIFY_SANE(s
);
582 if (!PUT_AT_VALID (s
, putp
+ sizeof (u_int16_t
)))
584 STREAM_BOUND_WARN (s
, "put");
588 s
->data
[putp
] = (u_char
)(w
>> 8);
589 s
->data
[putp
+ 1] = (u_char
) w
;
595 stream_putl_at (struct stream
*s
, size_t putp
, u_int32_t l
)
597 STREAM_VERIFY_SANE(s
);
599 if (!PUT_AT_VALID (s
, putp
+ sizeof (u_int32_t
)))
601 STREAM_BOUND_WARN (s
, "put");
604 s
->data
[putp
] = (u_char
)(l
>> 24);
605 s
->data
[putp
+ 1] = (u_char
)(l
>> 16);
606 s
->data
[putp
+ 2] = (u_char
)(l
>> 8);
607 s
->data
[putp
+ 3] = (u_char
)l
;
613 stream_putq_at (struct stream
*s
, size_t putp
, uint64_t q
)
615 STREAM_VERIFY_SANE(s
);
617 if (!PUT_AT_VALID (s
, putp
+ sizeof (uint64_t)))
619 STREAM_BOUND_WARN (s
, "put");
622 s
->data
[putp
] = (u_char
)(q
>> 56);
623 s
->data
[putp
+ 1] = (u_char
)(q
>> 48);
624 s
->data
[putp
+ 2] = (u_char
)(q
>> 40);
625 s
->data
[putp
+ 3] = (u_char
)(q
>> 32);
626 s
->data
[putp
+ 4] = (u_char
)(q
>> 24);
627 s
->data
[putp
+ 5] = (u_char
)(q
>> 16);
628 s
->data
[putp
+ 6] = (u_char
)(q
>> 8);
629 s
->data
[putp
+ 7] = (u_char
)q
;
634 /* Put long word to the stream. */
636 stream_put_ipv4 (struct stream
*s
, u_int32_t l
)
638 STREAM_VERIFY_SANE(s
);
640 if (STREAM_WRITEABLE (s
) < sizeof (u_int32_t
))
642 STREAM_BOUND_WARN (s
, "put");
645 memcpy (s
->data
+ s
->endp
, &l
, sizeof (u_int32_t
));
646 s
->endp
+= sizeof (u_int32_t
);
648 return sizeof (u_int32_t
);
651 /* Put long word to the stream. */
653 stream_put_in_addr (struct stream
*s
, struct in_addr
*addr
)
655 STREAM_VERIFY_SANE(s
);
657 if (STREAM_WRITEABLE (s
) < sizeof (u_int32_t
))
659 STREAM_BOUND_WARN (s
, "put");
663 memcpy (s
->data
+ s
->endp
, addr
, sizeof (u_int32_t
));
664 s
->endp
+= sizeof (u_int32_t
);
666 return sizeof (u_int32_t
);
669 /* Put prefix by nlri type format. */
671 stream_put_prefix (struct stream
*s
, struct prefix
*p
)
675 STREAM_VERIFY_SANE(s
);
677 psize
= PSIZE (p
->prefixlen
);
679 if (STREAM_WRITEABLE (s
) < psize
)
681 STREAM_BOUND_WARN (s
, "put");
685 stream_putc (s
, p
->prefixlen
);
686 memcpy (s
->data
+ s
->endp
, &p
->u
.prefix
, psize
);
692 /* Read size from fd. */
694 stream_read (struct stream
*s
, int fd
, size_t size
)
698 STREAM_VERIFY_SANE(s
);
700 if (STREAM_WRITEABLE (s
) < size
)
702 STREAM_BOUND_WARN (s
, "put");
706 nbytes
= readn (fd
, s
->data
+ s
->endp
, size
);
714 /* Read size from fd. */
716 stream_read_unblock (struct stream
*s
, int fd
, size_t size
)
721 STREAM_VERIFY_SANE(s
);
723 if (STREAM_WRITEABLE (s
) < size
)
725 STREAM_BOUND_WARN (s
, "put");
729 val
= fcntl (fd
, F_GETFL
, 0);
730 fcntl (fd
, F_SETFL
, val
|O_NONBLOCK
);
731 nbytes
= read (fd
, s
->data
+ s
->endp
, size
);
732 fcntl (fd
, F_SETFL
, val
);
741 stream_read_try(struct stream
*s
, int fd
, size_t size
)
745 STREAM_VERIFY_SANE(s
);
747 if (STREAM_WRITEABLE(s
) < size
)
749 STREAM_BOUND_WARN (s
, "put");
750 /* Fatal (not transient) error, since retrying will not help
751 (stream is too small to contain the desired data). */
755 if ((nbytes
= read(fd
, s
->data
+ s
->endp
, size
)) >= 0)
760 /* Error: was it transient (return -2) or fatal (return -1)? */
761 if (ERRNO_IO_RETRY(errno
))
763 zlog_warn("%s: read failed on fd %d: %s", __func__
, fd
, safe_strerror(errno
));
767 /* Read up to size bytes into the stream from the fd, using recvmsgfrom
768 * whose arguments match the remaining arguments to this function
771 stream_recvfrom (struct stream
*s
, int fd
, size_t size
, int flags
,
772 struct sockaddr
*from
, socklen_t
*fromlen
)
776 STREAM_VERIFY_SANE(s
);
778 if (STREAM_WRITEABLE(s
) < size
)
780 STREAM_BOUND_WARN (s
, "put");
781 /* Fatal (not transient) error, since retrying will not help
782 (stream is too small to contain the desired data). */
786 if ((nbytes
= recvfrom (fd
, s
->data
+ s
->endp
, size
,
787 flags
, from
, fromlen
)) >= 0)
792 /* Error: was it transient (return -2) or fatal (return -1)? */
793 if (ERRNO_IO_RETRY(errno
))
795 zlog_warn("%s: read failed on fd %d: %s", __func__
, fd
, safe_strerror(errno
));
799 /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
801 * First iovec will be used to receive the data.
802 * Stream need not be empty.
805 stream_recvmsg (struct stream
*s
, int fd
, struct msghdr
*msgh
, int flags
,
811 STREAM_VERIFY_SANE(s
);
812 assert (msgh
->msg_iovlen
> 0);
814 if (STREAM_WRITEABLE (s
) < size
)
816 STREAM_BOUND_WARN (s
, "put");
817 /* This is a logic error in the calling code: the stream is too small
818 to hold the desired data! */
822 iov
= &(msgh
->msg_iov
[0]);
823 iov
->iov_base
= (s
->data
+ s
->endp
);
826 nbytes
= recvmsg (fd
, msgh
, flags
);
834 /* Write data to buffer. */
836 stream_write (struct stream
*s
, u_char
*ptr
, size_t size
)
841 STREAM_VERIFY_SANE(s
);
843 if (STREAM_WRITEABLE (s
) < size
)
845 STREAM_BOUND_WARN (s
, "put");
849 memcpy (s
->data
+ s
->endp
, ptr
, size
);
855 /* Return current read pointer.
857 * Use stream_get_pnt_to if you must, but decoding streams properly
861 stream_pnt (struct stream
*s
)
863 STREAM_VERIFY_SANE(s
);
864 return s
->data
+ s
->getp
;
867 /* Check does this stream empty? */
869 stream_empty (struct stream
*s
)
871 STREAM_VERIFY_SANE(s
);
873 return (s
->endp
== 0);
878 stream_reset (struct stream
*s
)
880 STREAM_VERIFY_SANE (s
);
882 s
->getp
= s
->endp
= 0;
885 /* Write stream contens to the file discriptor. */
887 stream_flush (struct stream
*s
, int fd
)
891 STREAM_VERIFY_SANE(s
);
893 nbytes
= write (fd
, s
->data
+ s
->getp
, s
->endp
- s
->getp
);
898 /* Stream first in first out queue. */
901 stream_fifo_new (void)
903 struct stream_fifo
*new;
905 new = XCALLOC (MTYPE_STREAM_FIFO
, sizeof (struct stream_fifo
));
909 /* Add new stream to fifo. */
911 stream_fifo_push (struct stream_fifo
*fifo
, struct stream
*s
)
914 fifo
->tail
->next
= s
;
923 /* Delete first stream from fifo. */
925 stream_fifo_pop (struct stream_fifo
*fifo
)
933 fifo
->head
= s
->next
;
935 if (fifo
->head
== NULL
)
944 /* Return first fifo entry. */
946 stream_fifo_head (struct stream_fifo
*fifo
)
952 stream_fifo_clean (struct stream_fifo
*fifo
)
957 for (s
= fifo
->head
; s
; s
= next
)
962 fifo
->head
= fifo
->tail
= NULL
;
967 stream_fifo_free (struct stream_fifo
*fifo
)
969 stream_fifo_clean (fifo
);
970 XFREE (MTYPE_STREAM_FIFO
, fifo
);