ripd: fix compiler warnings
[jleu-quagga.git] / lib / stream.c
blob983330ffb4a3b19ac0a6e7a668aebe76b953f197
1 /*
2 * Packet interface
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
10 * later version.
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
20 * 02111-1307, USA.
23 #include <stddef.h>
24 #include <zebra.h>
26 #include "stream.h"
27 #include "memory.h"
28 #include "network.h"
29 #include "prefix.h"
30 #include "log.h"
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)
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", \
56 (S), \
57 (unsigned long) (S)->size, \
58 (unsigned long) (S)->getp, \
59 (unsigned long) (S)->endp)\
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)
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)
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);
88 /* Make stream buffer. */
89 struct stream *
90 stream_new (size_t size)
92 struct stream *s;
94 assert (size > 0);
96 if (size == 0)
98 zlog_warn ("stream_new(): called with 0 size!");
99 return NULL;
102 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
104 if (s == NULL)
105 return s;
107 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
109 XFREE (MTYPE_STREAM, s);
110 return NULL;
113 s->size = size;
114 return s;
117 /* Free it now. */
118 void
119 stream_free (struct stream *s)
121 if (!s)
122 return;
124 XFREE (MTYPE_STREAM_DATA, s->data);
125 XFREE (MTYPE_STREAM, s);
128 struct stream *
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);
141 return new;
144 struct stream *
145 stream_dup (struct stream *s)
147 struct stream *new;
149 STREAM_VERIFY_SANE (s);
151 if ( (new = stream_new (s->endp)) == NULL)
152 return NULL;
154 return (stream_copy (new, s));
157 size_t
158 stream_resize (struct stream *s, size_t newsize)
160 u_char *newdata;
161 STREAM_VERIFY_SANE (s);
163 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
165 if (newdata == NULL)
166 return s->size;
168 s->data = newdata;
169 s->size = newsize;
171 if (s->endp > s->size)
172 s->endp = s->size;
173 if (s->getp > s->endp)
174 s->getp = s->endp;
176 STREAM_VERIFY_SANE (s);
178 return s->size;
181 size_t
182 stream_get_getp (struct stream *s)
184 STREAM_VERIFY_SANE(s);
185 return s->getp;
188 size_t
189 stream_get_endp (struct stream *s)
191 STREAM_VERIFY_SANE(s);
192 return s->endp;
195 size_t
196 stream_get_size (struct stream *s)
198 STREAM_VERIFY_SANE(s);
199 return s->size;
202 /* Stream structre' stream pointer related functions. */
203 void
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");
211 pos = s->endp;
214 s->getp = pos;
217 /* Forward pointer. */
218 void
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");
226 return;
229 s->getp += size;
232 void
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");
240 return;
243 s->endp += size;
246 /* Copy from stream to destination. */
247 void
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");
255 return;
258 memcpy (dst, s->data + s->getp, size);
259 s->getp += size;
262 /* Get next character from the stream. */
263 u_char
264 stream_getc (struct stream *s)
266 u_char c;
268 STREAM_VERIFY_SANE (s);
270 if (STREAM_READABLE(s) < sizeof (u_char))
272 STREAM_BOUND_WARN (s, "get char");
273 return 0;
275 c = s->data[s->getp++];
277 return c;
280 /* Get next character from the stream. */
281 u_char
282 stream_getc_from (struct stream *s, size_t from)
284 u_char c;
286 STREAM_VERIFY_SANE(s);
288 if (!GETP_VALID (s, from + sizeof (u_char)))
290 STREAM_BOUND_WARN (s, "get char");
291 return 0;
294 c = s->data[from];
296 return c;
299 /* Get next word from the stream. */
300 u_int16_t
301 stream_getw (struct stream *s)
303 u_int16_t w;
305 STREAM_VERIFY_SANE (s);
307 if (STREAM_READABLE (s) < sizeof (u_int16_t))
309 STREAM_BOUND_WARN (s, "get ");
310 return 0;
313 w = s->data[s->getp++] << 8;
314 w |= s->data[s->getp++];
316 return w;
319 /* Get next word from the stream. */
320 u_int16_t
321 stream_getw_from (struct stream *s, size_t from)
323 u_int16_t w;
325 STREAM_VERIFY_SANE(s);
327 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
329 STREAM_BOUND_WARN (s, "get ");
330 return 0;
333 w = s->data[from++] << 8;
334 w |= s->data[from];
336 return w;
339 /* Get next long word from the stream. */
340 u_int32_t
341 stream_getl_from (struct stream *s, size_t from)
343 u_int32_t l;
345 STREAM_VERIFY_SANE(s);
347 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
349 STREAM_BOUND_WARN (s, "get long");
350 return 0;
353 l = s->data[from++] << 24;
354 l |= s->data[from++] << 16;
355 l |= s->data[from++] << 8;
356 l |= s->data[from];
358 return l;
361 u_int32_t
362 stream_getl (struct stream *s)
364 u_int32_t l;
366 STREAM_VERIFY_SANE(s);
368 if (STREAM_READABLE (s) < sizeof (u_int32_t))
370 STREAM_BOUND_WARN (s, "get long");
371 return 0;
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++];
379 return l;
382 /* Get next quad word from the stream. */
383 uint64_t
384 stream_getq_from (struct stream *s, size_t from)
386 uint64_t q;
388 STREAM_VERIFY_SANE(s);
390 if (!GETP_VALID (s, from + sizeof (uint64_t)))
392 STREAM_BOUND_WARN (s, "get quad");
393 return 0;
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++]);
405 return q;
408 uint64_t
409 stream_getq (struct stream *s)
411 uint64_t q;
413 STREAM_VERIFY_SANE(s);
415 if (STREAM_READABLE (s) < sizeof (uint64_t))
417 STREAM_BOUND_WARN (s, "get quad");
418 return 0;
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++]);
430 return q;
433 /* Get next long word from the stream. */
434 u_int32_t
435 stream_get_ipv4 (struct stream *s)
437 u_int32_t l;
439 STREAM_VERIFY_SANE(s);
441 if (STREAM_READABLE (s) < sizeof(u_int32_t))
443 STREAM_BOUND_WARN (s, "get ipv4");
444 return 0;
447 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
448 s->getp += sizeof(u_int32_t);
450 return l;
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
460 void
461 stream_put (struct stream *s, const void *src, size_t size)
464 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
465 CHECK_SIZE(s, size);
467 STREAM_VERIFY_SANE(s);
469 if (STREAM_WRITEABLE (s) < size)
471 STREAM_BOUND_WARN (s, "put");
472 return;
475 if (src)
476 memcpy (s->data + s->endp, src, size);
477 else
478 memset (s->data + s->endp, 0, size);
480 s->endp += 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");
492 return 0;
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");
508 return 0;
511 s->data[s->endp++] = (u_char)(w >> 8);
512 s->data[s->endp++] = (u_char) w;
514 return 2;
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");
526 return 0;
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;
534 return 4;
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");
546 return 0;
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;
558 return 8;
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");
569 return 0;
572 s->data[putp] = c;
574 return 1;
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");
585 return 0;
588 s->data[putp] = (u_char)(w >> 8);
589 s->data[putp + 1] = (u_char) w;
591 return 2;
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");
602 return 0;
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;
609 return 4;
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");
620 return 0;
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;
631 return 8;
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");
643 return 0;
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");
660 return 0;
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)
673 size_t psize;
675 STREAM_VERIFY_SANE(s);
677 psize = PSIZE (p->prefixlen);
679 if (STREAM_WRITEABLE (s) < psize)
681 STREAM_BOUND_WARN (s, "put");
682 return 0;
685 stream_putc (s, p->prefixlen);
686 memcpy (s->data + s->endp, &p->u.prefix, psize);
687 s->endp += psize;
689 return psize;
692 /* Read size from fd. */
694 stream_read (struct stream *s, int fd, size_t size)
696 int nbytes;
698 STREAM_VERIFY_SANE(s);
700 if (STREAM_WRITEABLE (s) < size)
702 STREAM_BOUND_WARN (s, "put");
703 return 0;
706 nbytes = readn (fd, s->data + s->endp, size);
708 if (nbytes > 0)
709 s->endp += nbytes;
711 return nbytes;
714 /* Read size from fd. */
716 stream_read_unblock (struct stream *s, int fd, size_t size)
718 int nbytes;
719 int val;
721 STREAM_VERIFY_SANE(s);
723 if (STREAM_WRITEABLE (s) < size)
725 STREAM_BOUND_WARN (s, "put");
726 return 0;
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);
734 if (nbytes > 0)
735 s->endp += nbytes;
737 return nbytes;
740 ssize_t
741 stream_read_try(struct stream *s, int fd, size_t size)
743 ssize_t nbytes;
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). */
752 return -1;
755 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
757 s->endp += nbytes;
758 return nbytes;
760 /* Error: was it transient (return -2) or fatal (return -1)? */
761 if (ERRNO_IO_RETRY(errno))
762 return -2;
763 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
764 return -1;
767 /* Read up to size bytes into the stream from the fd, using recvmsgfrom
768 * whose arguments match the remaining arguments to this function
770 ssize_t
771 stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
772 struct sockaddr *from, socklen_t *fromlen)
774 ssize_t nbytes;
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). */
783 return -1;
786 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
787 flags, from, fromlen)) >= 0)
789 s->endp += nbytes;
790 return nbytes;
792 /* Error: was it transient (return -2) or fatal (return -1)? */
793 if (ERRNO_IO_RETRY(errno))
794 return -2;
795 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
796 return -1;
799 /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
800 * from endp.
801 * First iovec will be used to receive the data.
802 * Stream need not be empty.
804 ssize_t
805 stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
806 size_t size)
808 int nbytes;
809 struct iovec *iov;
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! */
819 return -1;
822 iov = &(msgh->msg_iov[0]);
823 iov->iov_base = (s->data + s->endp);
824 iov->iov_len = size;
826 nbytes = recvmsg (fd, msgh, flags);
828 if (nbytes > 0)
829 s->endp += nbytes;
831 return nbytes;
834 /* Write data to buffer. */
835 size_t
836 stream_write (struct stream *s, const void *ptr, size_t size)
839 CHECK_SIZE(s, size);
841 STREAM_VERIFY_SANE(s);
843 if (STREAM_WRITEABLE (s) < size)
845 STREAM_BOUND_WARN (s, "put");
846 return 0;
849 memcpy (s->data + s->endp, ptr, size);
850 s->endp += size;
852 return size;
855 /* Return current read pointer.
856 * DEPRECATED!
857 * Use stream_get_pnt_to if you must, but decoding streams properly
858 * is preferred
860 u_char *
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);
876 /* Reset stream. */
877 void
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)
889 int nbytes;
891 STREAM_VERIFY_SANE(s);
893 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
895 return nbytes;
898 /* Stream first in first out queue. */
900 struct stream_fifo *
901 stream_fifo_new (void)
903 struct stream_fifo *new;
905 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
906 return new;
909 /* Add new stream to fifo. */
910 void
911 stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
913 if (fifo->tail)
914 fifo->tail->next = s;
915 else
916 fifo->head = s;
918 fifo->tail = s;
920 fifo->count++;
923 /* Delete first stream from fifo. */
924 struct stream *
925 stream_fifo_pop (struct stream_fifo *fifo)
927 struct stream *s;
929 s = fifo->head;
931 if (s)
933 fifo->head = s->next;
935 if (fifo->head == NULL)
936 fifo->tail = NULL;
939 fifo->count--;
941 return s;
944 /* Return first fifo entry. */
945 struct stream *
946 stream_fifo_head (struct stream_fifo *fifo)
948 return fifo->head;
951 void
952 stream_fifo_clean (struct stream_fifo *fifo)
954 struct stream *s;
955 struct stream *next;
957 for (s = fifo->head; s; s = next)
959 next = s->next;
960 stream_free (s);
962 fifo->head = fifo->tail = NULL;
963 fifo->count = 0;
966 void
967 stream_fifo_free (struct stream_fifo *fifo)
969 stream_fifo_clean (fifo);
970 XFREE (MTYPE_STREAM_FIFO, fifo);