]> git.proxmox.com Git - mirror_frr.git/blob - lib/stream.c
Merge pull request #409 from donaldsharp/EIGRP
[mirror_frr.git] / lib / stream.c
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 <zebra.h>
24 #include <stddef.h>
25
26 #include "stream.h"
27 #include "memory.h"
28 #include "network.h"
29 #include "prefix.h"
30 #include "log.h"
31
32 DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
33 DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data")
34 DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
35
36 /* Tests whether a position is valid */
37 #define GETP_VALID(S,G) \
38 ((G) <= (S)->endp)
39 #define PUT_AT_VALID(S,G) GETP_VALID(S,G)
40 #define ENDP_VALID(S,E) \
41 ((E) <= (S)->size)
42
43 /* asserting sanity checks. Following must be true before
44 * stream functions are called:
45 *
46 * Following must always be true of stream elements
47 * before and after calls to stream functions:
48 *
49 * getp <= endp <= size
50 *
51 * Note that after a stream function is called following may be true:
52 * if (getp == endp) then stream is no longer readable
53 * if (endp == size) then stream is no longer writeable
54 *
55 * It is valid to put to anywhere within the size of the stream, but only
56 * using stream_put..._at() functions.
57 */
58 #define STREAM_WARN_OFFSETS(S) \
59 zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
60 (void *)(S), \
61 (unsigned long) (S)->size, \
62 (unsigned long) (S)->getp, \
63 (unsigned long) (S)->endp)\
64
65 #define STREAM_VERIFY_SANE(S) \
66 do { \
67 if ( !(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp)) ) \
68 STREAM_WARN_OFFSETS(S); \
69 assert ( GETP_VALID(S, (S)->getp) ); \
70 assert ( ENDP_VALID(S, (S)->endp) ); \
71 } while (0)
72
73 #define STREAM_BOUND_WARN(S, WHAT) \
74 do { \
75 zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \
76 STREAM_WARN_OFFSETS(S); \
77 assert (0); \
78 } while (0)
79
80 /* XXX: Deprecated macro: do not use */
81 #define CHECK_SIZE(S, Z) \
82 do { \
83 if (((S)->endp + (Z)) > (S)->size) \
84 { \
85 zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \
86 (unsigned long) (Z)); \
87 STREAM_WARN_OFFSETS(S); \
88 (Z) = (S)->size - (S)->endp; \
89 } \
90 } while (0);
91
92 /* Make stream buffer. */
93 struct stream *
94 stream_new (size_t size)
95 {
96 struct stream *s;
97
98 assert (size > 0);
99
100 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
101
102 if (s == NULL)
103 return s;
104
105 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
106 {
107 XFREE (MTYPE_STREAM, s);
108 return NULL;
109 }
110
111 s->size = size;
112 return s;
113 }
114
115 /* Free it now. */
116 void
117 stream_free (struct stream *s)
118 {
119 if (!s)
120 return;
121
122 XFREE (MTYPE_STREAM_DATA, s->data);
123 XFREE (MTYPE_STREAM, s);
124 }
125
126 struct stream *
127 stream_copy (struct stream *new, struct stream *src)
128 {
129 STREAM_VERIFY_SANE (src);
130
131 assert (new != NULL);
132 assert (STREAM_SIZE(new) >= src->endp);
133
134 new->endp = src->endp;
135 new->getp = src->getp;
136
137 memcpy (new->data, src->data, src->endp);
138
139 return new;
140 }
141
142 struct stream *
143 stream_dup (struct stream *s)
144 {
145 struct stream *new;
146
147 STREAM_VERIFY_SANE (s);
148
149 if ( (new = stream_new (s->endp)) == NULL)
150 return NULL;
151
152 return (stream_copy (new, s));
153 }
154
155 struct stream *
156 stream_dupcat (struct stream *s1, struct stream *s2, size_t offset)
157 {
158 struct stream *new;
159
160 STREAM_VERIFY_SANE (s1);
161 STREAM_VERIFY_SANE (s2);
162
163 if ( (new = stream_new (s1->endp + s2->endp)) == NULL)
164 return NULL;
165
166 memcpy (new->data, s1->data, offset);
167 memcpy (new->data + offset, s2->data, s2->endp);
168 memcpy (new->data + offset + s2->endp, s1->data + offset,
169 (s1->endp - offset));
170 new->endp = s1->endp + s2->endp;
171 return new;
172 }
173
174 size_t
175 stream_resize (struct stream *s, size_t newsize)
176 {
177 u_char *newdata;
178 STREAM_VERIFY_SANE (s);
179
180 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
181
182 if (newdata == NULL)
183 return s->size;
184
185 s->data = newdata;
186 s->size = newsize;
187
188 if (s->endp > s->size)
189 s->endp = s->size;
190 if (s->getp > s->endp)
191 s->getp = s->endp;
192
193 STREAM_VERIFY_SANE (s);
194
195 return s->size;
196 }
197
198 size_t
199 stream_get_getp (struct stream *s)
200 {
201 STREAM_VERIFY_SANE(s);
202 return s->getp;
203 }
204
205 size_t
206 stream_get_endp (struct stream *s)
207 {
208 STREAM_VERIFY_SANE(s);
209 return s->endp;
210 }
211
212 size_t
213 stream_get_size (struct stream *s)
214 {
215 STREAM_VERIFY_SANE(s);
216 return s->size;
217 }
218
219 /* Stream structre' stream pointer related functions. */
220 void
221 stream_set_getp (struct stream *s, size_t pos)
222 {
223 STREAM_VERIFY_SANE(s);
224
225 if (!GETP_VALID (s, pos))
226 {
227 STREAM_BOUND_WARN (s, "set getp");
228 pos = s->endp;
229 }
230
231 s->getp = pos;
232 }
233
234 void
235 stream_set_endp (struct stream *s, size_t pos)
236 {
237 STREAM_VERIFY_SANE(s);
238
239 if (!ENDP_VALID(s, pos))
240 {
241 STREAM_BOUND_WARN (s, "set endp");
242 return;
243 }
244
245 /*
246 * Make sure the current read pointer is not beyond the new endp.
247 */
248 if (s->getp > pos)
249 {
250 STREAM_BOUND_WARN(s, "set endp");
251 return;
252 }
253
254 s->endp = pos;
255 STREAM_VERIFY_SANE(s);
256 }
257
258 /* Forward pointer. */
259 void
260 stream_forward_getp (struct stream *s, size_t size)
261 {
262 STREAM_VERIFY_SANE(s);
263
264 if (!GETP_VALID (s, s->getp + size))
265 {
266 STREAM_BOUND_WARN (s, "seek getp");
267 return;
268 }
269
270 s->getp += size;
271 }
272
273 void
274 stream_forward_endp (struct stream *s, size_t size)
275 {
276 STREAM_VERIFY_SANE(s);
277
278 if (!ENDP_VALID (s, s->endp + size))
279 {
280 STREAM_BOUND_WARN (s, "seek endp");
281 return;
282 }
283
284 s->endp += size;
285 }
286
287 /* Copy from stream to destination. */
288 void
289 stream_get (void *dst, struct stream *s, size_t size)
290 {
291 STREAM_VERIFY_SANE(s);
292
293 if (STREAM_READABLE(s) < size)
294 {
295 STREAM_BOUND_WARN (s, "get");
296 return;
297 }
298
299 memcpy (dst, s->data + s->getp, size);
300 s->getp += size;
301 }
302
303 /* Get next character from the stream. */
304 u_char
305 stream_getc (struct stream *s)
306 {
307 u_char c;
308
309 STREAM_VERIFY_SANE (s);
310
311 if (STREAM_READABLE(s) < sizeof (u_char))
312 {
313 STREAM_BOUND_WARN (s, "get char");
314 return 0;
315 }
316 c = s->data[s->getp++];
317
318 return c;
319 }
320
321 /* Get next character from the stream. */
322 u_char
323 stream_getc_from (struct stream *s, size_t from)
324 {
325 u_char c;
326
327 STREAM_VERIFY_SANE(s);
328
329 if (!GETP_VALID (s, from + sizeof (u_char)))
330 {
331 STREAM_BOUND_WARN (s, "get char");
332 return 0;
333 }
334
335 c = s->data[from];
336
337 return c;
338 }
339
340 /* Get next word from the stream. */
341 u_int16_t
342 stream_getw (struct stream *s)
343 {
344 u_int16_t w;
345
346 STREAM_VERIFY_SANE (s);
347
348 if (STREAM_READABLE (s) < sizeof (u_int16_t))
349 {
350 STREAM_BOUND_WARN (s, "get ");
351 return 0;
352 }
353
354 w = s->data[s->getp++] << 8;
355 w |= s->data[s->getp++];
356
357 return w;
358 }
359
360 /* Get next word from the stream. */
361 u_int16_t
362 stream_getw_from (struct stream *s, size_t from)
363 {
364 u_int16_t w;
365
366 STREAM_VERIFY_SANE(s);
367
368 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
369 {
370 STREAM_BOUND_WARN (s, "get ");
371 return 0;
372 }
373
374 w = s->data[from++] << 8;
375 w |= s->data[from];
376
377 return w;
378 }
379
380 /* Get next 3-byte from the stream. */
381 u_int32_t
382 stream_get3_from (struct stream *s, size_t from)
383 {
384 u_int32_t l;
385
386 STREAM_VERIFY_SANE(s);
387
388 if (!GETP_VALID (s, from + 3))
389 {
390 STREAM_BOUND_WARN (s, "get 3byte");
391 return 0;
392 }
393
394 l = s->data[from++] << 16;
395 l |= s->data[from++] << 8;
396 l |= s->data[from];
397
398 return l;
399 }
400
401 u_int32_t
402 stream_get3 (struct stream *s)
403 {
404 u_int32_t l;
405
406 STREAM_VERIFY_SANE(s);
407
408 if (STREAM_READABLE (s) < 3)
409 {
410 STREAM_BOUND_WARN (s, "get 3byte");
411 return 0;
412 }
413
414 l = s->data[s->getp++] << 16;
415 l |= s->data[s->getp++] << 8;
416 l |= s->data[s->getp++];
417
418 return l;
419 }
420
421 /* Get next long word from the stream. */
422 u_int32_t
423 stream_getl_from (struct stream *s, size_t from)
424 {
425 u_int32_t l;
426
427 STREAM_VERIFY_SANE(s);
428
429 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
430 {
431 STREAM_BOUND_WARN (s, "get long");
432 return 0;
433 }
434
435 l = s->data[from++] << 24;
436 l |= s->data[from++] << 16;
437 l |= s->data[from++] << 8;
438 l |= s->data[from];
439
440 return l;
441 }
442
443 /* Copy from stream at specific location to destination. */
444 void
445 stream_get_from (void *dst, struct stream *s, size_t from, size_t size)
446 {
447 STREAM_VERIFY_SANE(s);
448
449 if (!GETP_VALID (s, from + size))
450 {
451 STREAM_BOUND_WARN (s, "get from");
452 return;
453 }
454
455 memcpy (dst, s->data + from, size);
456 }
457
458 u_int32_t
459 stream_getl (struct stream *s)
460 {
461 u_int32_t l;
462
463 STREAM_VERIFY_SANE(s);
464
465 if (STREAM_READABLE (s) < sizeof (u_int32_t))
466 {
467 STREAM_BOUND_WARN (s, "get long");
468 return 0;
469 }
470
471 l = s->data[s->getp++] << 24;
472 l |= s->data[s->getp++] << 16;
473 l |= s->data[s->getp++] << 8;
474 l |= s->data[s->getp++];
475
476 return l;
477 }
478
479 /* Get next quad word from the stream. */
480 uint64_t
481 stream_getq_from (struct stream *s, size_t from)
482 {
483 uint64_t q;
484
485 STREAM_VERIFY_SANE(s);
486
487 if (!GETP_VALID (s, from + sizeof (uint64_t)))
488 {
489 STREAM_BOUND_WARN (s, "get quad");
490 return 0;
491 }
492
493 q = ((uint64_t) s->data[from++]) << 56;
494 q |= ((uint64_t) s->data[from++]) << 48;
495 q |= ((uint64_t) s->data[from++]) << 40;
496 q |= ((uint64_t) s->data[from++]) << 32;
497 q |= ((uint64_t) s->data[from++]) << 24;
498 q |= ((uint64_t) s->data[from++]) << 16;
499 q |= ((uint64_t) s->data[from++]) << 8;
500 q |= ((uint64_t) s->data[from++]);
501
502 return q;
503 }
504
505 uint64_t
506 stream_getq (struct stream *s)
507 {
508 uint64_t q;
509
510 STREAM_VERIFY_SANE(s);
511
512 if (STREAM_READABLE (s) < sizeof (uint64_t))
513 {
514 STREAM_BOUND_WARN (s, "get quad");
515 return 0;
516 }
517
518 q = ((uint64_t) s->data[s->getp++]) << 56;
519 q |= ((uint64_t) s->data[s->getp++]) << 48;
520 q |= ((uint64_t) s->data[s->getp++]) << 40;
521 q |= ((uint64_t) s->data[s->getp++]) << 32;
522 q |= ((uint64_t) s->data[s->getp++]) << 24;
523 q |= ((uint64_t) s->data[s->getp++]) << 16;
524 q |= ((uint64_t) s->data[s->getp++]) << 8;
525 q |= ((uint64_t) s->data[s->getp++]);
526
527 return q;
528 }
529
530 /* Get next long word from the stream. */
531 u_int32_t
532 stream_get_ipv4 (struct stream *s)
533 {
534 u_int32_t l;
535
536 STREAM_VERIFY_SANE(s);
537
538 if (STREAM_READABLE (s) < sizeof(u_int32_t))
539 {
540 STREAM_BOUND_WARN (s, "get ipv4");
541 return 0;
542 }
543
544 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
545 s->getp += sizeof(u_int32_t);
546
547 return l;
548 }
549
550 float
551 stream_getf (struct stream *s)
552 {
553 union {
554 float r;
555 uint32_t d;
556 } u;
557 u.d = stream_getl (s);
558 return u.r;
559 }
560
561 double
562 stream_getd (struct stream *s)
563 {
564 union {
565 double r;
566 uint64_t d;
567 } u;
568 u.d = stream_getq (s);
569 return u.r;
570 }
571
572 /* Copy to source to stream.
573 *
574 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
575 * around. This should be fixed once the stream updates are working.
576 *
577 * stream_write() is saner
578 */
579 void
580 stream_put (struct stream *s, const void *src, size_t size)
581 {
582
583 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
584 CHECK_SIZE(s, size);
585
586 STREAM_VERIFY_SANE(s);
587
588 if (STREAM_WRITEABLE (s) < size)
589 {
590 STREAM_BOUND_WARN (s, "put");
591 return;
592 }
593
594 if (src)
595 memcpy (s->data + s->endp, src, size);
596 else
597 memset (s->data + s->endp, 0, size);
598
599 s->endp += size;
600 }
601
602 /* Put character to the stream. */
603 int
604 stream_putc (struct stream *s, u_char c)
605 {
606 STREAM_VERIFY_SANE(s);
607
608 if (STREAM_WRITEABLE (s) < sizeof(u_char))
609 {
610 STREAM_BOUND_WARN (s, "put");
611 return 0;
612 }
613
614 s->data[s->endp++] = c;
615 return sizeof (u_char);
616 }
617
618 /* Put word to the stream. */
619 int
620 stream_putw (struct stream *s, u_int16_t w)
621 {
622 STREAM_VERIFY_SANE (s);
623
624 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
625 {
626 STREAM_BOUND_WARN (s, "put");
627 return 0;
628 }
629
630 s->data[s->endp++] = (u_char)(w >> 8);
631 s->data[s->endp++] = (u_char) w;
632
633 return 2;
634 }
635
636 /* Put long word to the stream. */
637 int
638 stream_put3 (struct stream *s, u_int32_t l)
639 {
640 STREAM_VERIFY_SANE (s);
641
642 if (STREAM_WRITEABLE (s) < 3)
643 {
644 STREAM_BOUND_WARN (s, "put");
645 return 0;
646 }
647
648 s->data[s->endp++] = (u_char)(l >> 16);
649 s->data[s->endp++] = (u_char)(l >> 8);
650 s->data[s->endp++] = (u_char)l;
651
652 return 3;
653 }
654
655 /* Put long word to the stream. */
656 int
657 stream_putl (struct stream *s, u_int32_t l)
658 {
659 STREAM_VERIFY_SANE (s);
660
661 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
662 {
663 STREAM_BOUND_WARN (s, "put");
664 return 0;
665 }
666
667 s->data[s->endp++] = (u_char)(l >> 24);
668 s->data[s->endp++] = (u_char)(l >> 16);
669 s->data[s->endp++] = (u_char)(l >> 8);
670 s->data[s->endp++] = (u_char)l;
671
672 return 4;
673 }
674
675 /* Put quad word to the stream. */
676 int
677 stream_putq (struct stream *s, uint64_t q)
678 {
679 STREAM_VERIFY_SANE (s);
680
681 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
682 {
683 STREAM_BOUND_WARN (s, "put quad");
684 return 0;
685 }
686
687 s->data[s->endp++] = (u_char)(q >> 56);
688 s->data[s->endp++] = (u_char)(q >> 48);
689 s->data[s->endp++] = (u_char)(q >> 40);
690 s->data[s->endp++] = (u_char)(q >> 32);
691 s->data[s->endp++] = (u_char)(q >> 24);
692 s->data[s->endp++] = (u_char)(q >> 16);
693 s->data[s->endp++] = (u_char)(q >> 8);
694 s->data[s->endp++] = (u_char)q;
695
696 return 8;
697 }
698
699 int
700 stream_putf (struct stream *s, float f)
701 {
702 union {
703 float i;
704 uint32_t o;
705 } u;
706 u.i = f;
707 return stream_putl (s, u.o);
708 }
709
710 int
711 stream_putd (struct stream *s, double d)
712 {
713 union {
714 double i;
715 uint64_t o;
716 } u;
717 u.i = d;
718 return stream_putq (s, u.o);
719 }
720
721 int
722 stream_putc_at (struct stream *s, size_t putp, u_char c)
723 {
724 STREAM_VERIFY_SANE(s);
725
726 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
727 {
728 STREAM_BOUND_WARN (s, "put");
729 return 0;
730 }
731
732 s->data[putp] = c;
733
734 return 1;
735 }
736
737 int
738 stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
739 {
740 STREAM_VERIFY_SANE(s);
741
742 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
743 {
744 STREAM_BOUND_WARN (s, "put");
745 return 0;
746 }
747
748 s->data[putp] = (u_char)(w >> 8);
749 s->data[putp + 1] = (u_char) w;
750
751 return 2;
752 }
753
754 int
755 stream_put3_at (struct stream *s, size_t putp, u_int32_t l)
756 {
757 STREAM_VERIFY_SANE(s);
758
759 if (!PUT_AT_VALID (s, putp + 3))
760 {
761 STREAM_BOUND_WARN (s, "put");
762 return 0;
763 }
764 s->data[putp] = (u_char)(l >> 16);
765 s->data[putp + 1] = (u_char)(l >> 8);
766 s->data[putp + 2] = (u_char)l;
767
768 return 3;
769 }
770
771 int
772 stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
773 {
774 STREAM_VERIFY_SANE(s);
775
776 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
777 {
778 STREAM_BOUND_WARN (s, "put");
779 return 0;
780 }
781 s->data[putp] = (u_char)(l >> 24);
782 s->data[putp + 1] = (u_char)(l >> 16);
783 s->data[putp + 2] = (u_char)(l >> 8);
784 s->data[putp + 3] = (u_char)l;
785
786 return 4;
787 }
788
789 int
790 stream_putq_at (struct stream *s, size_t putp, uint64_t q)
791 {
792 STREAM_VERIFY_SANE(s);
793
794 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
795 {
796 STREAM_BOUND_WARN (s, "put");
797 return 0;
798 }
799 s->data[putp] = (u_char)(q >> 56);
800 s->data[putp + 1] = (u_char)(q >> 48);
801 s->data[putp + 2] = (u_char)(q >> 40);
802 s->data[putp + 3] = (u_char)(q >> 32);
803 s->data[putp + 4] = (u_char)(q >> 24);
804 s->data[putp + 5] = (u_char)(q >> 16);
805 s->data[putp + 6] = (u_char)(q >> 8);
806 s->data[putp + 7] = (u_char)q;
807
808 return 8;
809 }
810
811 /* Put long word to the stream. */
812 int
813 stream_put_ipv4 (struct stream *s, u_int32_t l)
814 {
815 STREAM_VERIFY_SANE(s);
816
817 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
818 {
819 STREAM_BOUND_WARN (s, "put");
820 return 0;
821 }
822 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
823 s->endp += sizeof (u_int32_t);
824
825 return sizeof (u_int32_t);
826 }
827
828 /* Put long word to the stream. */
829 int
830 stream_put_in_addr (struct stream *s, struct in_addr *addr)
831 {
832 STREAM_VERIFY_SANE(s);
833
834 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
835 {
836 STREAM_BOUND_WARN (s, "put");
837 return 0;
838 }
839
840 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
841 s->endp += sizeof (u_int32_t);
842
843 return sizeof (u_int32_t);
844 }
845
846 /* Put in_addr at location in the stream. */
847 int
848 stream_put_in_addr_at (struct stream *s, size_t putp, struct in_addr *addr)
849 {
850 STREAM_VERIFY_SANE(s);
851
852 if (!PUT_AT_VALID (s, putp + 4))
853 {
854 STREAM_BOUND_WARN (s, "put");
855 return 0;
856 }
857
858 memcpy (&s->data[putp], addr, 4);
859 return 4;
860 }
861
862 /* Put in6_addr at location in the stream. */
863 int
864 stream_put_in6_addr_at (struct stream *s, size_t putp, struct in6_addr *addr)
865 {
866 STREAM_VERIFY_SANE(s);
867
868 if (!PUT_AT_VALID (s, putp + 16))
869 {
870 STREAM_BOUND_WARN (s, "put");
871 return 0;
872 }
873
874 memcpy (&s->data[putp], addr, 16);
875 return 16;
876 }
877
878 /* Put prefix by nlri type format. */
879 int
880 stream_put_prefix_addpath (struct stream *s, struct prefix *p,
881 int addpath_encode, u_int32_t addpath_tx_id)
882 {
883 size_t psize;
884 size_t psize_with_addpath;
885
886 STREAM_VERIFY_SANE(s);
887
888 psize = PSIZE (p->prefixlen);
889
890 if (addpath_encode)
891 psize_with_addpath = psize + 4;
892 else
893 psize_with_addpath = psize;
894
895 if (STREAM_WRITEABLE (s) < (psize_with_addpath + sizeof (u_char)))
896 {
897 STREAM_BOUND_WARN (s, "put");
898 return 0;
899 }
900
901 if (addpath_encode)
902 {
903 s->data[s->endp++] = (u_char)(addpath_tx_id >> 24);
904 s->data[s->endp++] = (u_char)(addpath_tx_id >> 16);
905 s->data[s->endp++] = (u_char)(addpath_tx_id >> 8);
906 s->data[s->endp++] = (u_char)addpath_tx_id;
907 }
908
909 s->data[s->endp++] = p->prefixlen;
910 memcpy (s->data + s->endp, &p->u.prefix, psize);
911 s->endp += psize;
912
913 return psize;
914 }
915
916 int
917 stream_put_prefix (struct stream *s, struct prefix *p)
918 {
919 return stream_put_prefix_addpath (s, p, 0, 0);
920 }
921
922 /* Put NLRI with label */
923 int
924 stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label)
925 {
926 size_t psize;
927
928 STREAM_VERIFY_SANE(s);
929
930 psize = PSIZE (p->prefixlen);
931
932 if (STREAM_WRITEABLE (s) < (psize + 3))
933 {
934 STREAM_BOUND_WARN (s, "put");
935 return 0;
936 }
937
938 stream_putc (s, (p->prefixlen + 24));
939 stream_putc(s, label[0]);
940 stream_putc(s, label[1]);
941 stream_putc(s, label[2]);
942 memcpy (s->data + s->endp, &p->u.prefix, psize);
943 s->endp += psize;
944
945 return (psize + 3);
946 }
947
948 /* Read size from fd. */
949 int
950 stream_read (struct stream *s, int fd, size_t size)
951 {
952 int nbytes;
953
954 STREAM_VERIFY_SANE(s);
955
956 if (STREAM_WRITEABLE (s) < size)
957 {
958 STREAM_BOUND_WARN (s, "put");
959 return 0;
960 }
961
962 nbytes = readn (fd, s->data + s->endp, size);
963
964 if (nbytes > 0)
965 s->endp += nbytes;
966
967 return nbytes;
968 }
969
970 ssize_t
971 stream_read_try(struct stream *s, int fd, size_t size)
972 {
973 ssize_t nbytes;
974
975 STREAM_VERIFY_SANE(s);
976
977 if (STREAM_WRITEABLE(s) < size)
978 {
979 STREAM_BOUND_WARN (s, "put");
980 /* Fatal (not transient) error, since retrying will not help
981 (stream is too small to contain the desired data). */
982 return -1;
983 }
984
985 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
986 {
987 s->endp += nbytes;
988 return nbytes;
989 }
990 /* Error: was it transient (return -2) or fatal (return -1)? */
991 if (ERRNO_IO_RETRY(errno))
992 return -2;
993 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
994 return -1;
995 }
996
997 /* Read up to size bytes into the stream from the fd, using recvmsgfrom
998 * whose arguments match the remaining arguments to this function
999 */
1000 ssize_t
1001 stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
1002 struct sockaddr *from, socklen_t *fromlen)
1003 {
1004 ssize_t nbytes;
1005
1006 STREAM_VERIFY_SANE(s);
1007
1008 if (STREAM_WRITEABLE(s) < size)
1009 {
1010 STREAM_BOUND_WARN (s, "put");
1011 /* Fatal (not transient) error, since retrying will not help
1012 (stream is too small to contain the desired data). */
1013 return -1;
1014 }
1015
1016 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
1017 flags, from, fromlen)) >= 0)
1018 {
1019 s->endp += nbytes;
1020 return nbytes;
1021 }
1022 /* Error: was it transient (return -2) or fatal (return -1)? */
1023 if (ERRNO_IO_RETRY(errno))
1024 return -2;
1025 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
1026 return -1;
1027 }
1028
1029 /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
1030 * from endp.
1031 * First iovec will be used to receive the data.
1032 * Stream need not be empty.
1033 */
1034 ssize_t
1035 stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
1036 size_t size)
1037 {
1038 int nbytes;
1039 struct iovec *iov;
1040
1041 STREAM_VERIFY_SANE(s);
1042 assert (msgh->msg_iovlen > 0);
1043
1044 if (STREAM_WRITEABLE (s) < size)
1045 {
1046 STREAM_BOUND_WARN (s, "put");
1047 /* This is a logic error in the calling code: the stream is too small
1048 to hold the desired data! */
1049 return -1;
1050 }
1051
1052 iov = &(msgh->msg_iov[0]);
1053 iov->iov_base = (s->data + s->endp);
1054 iov->iov_len = size;
1055
1056 nbytes = recvmsg (fd, msgh, flags);
1057
1058 if (nbytes > 0)
1059 s->endp += nbytes;
1060
1061 return nbytes;
1062 }
1063
1064 /* Write data to buffer. */
1065 size_t
1066 stream_write (struct stream *s, const void *ptr, size_t size)
1067 {
1068
1069 CHECK_SIZE(s, size);
1070
1071 STREAM_VERIFY_SANE(s);
1072
1073 if (STREAM_WRITEABLE (s) < size)
1074 {
1075 STREAM_BOUND_WARN (s, "put");
1076 return 0;
1077 }
1078
1079 memcpy (s->data + s->endp, ptr, size);
1080 s->endp += size;
1081
1082 return size;
1083 }
1084
1085 /* Return current read pointer.
1086 * DEPRECATED!
1087 * Use stream_get_pnt_to if you must, but decoding streams properly
1088 * is preferred
1089 */
1090 u_char *
1091 stream_pnt (struct stream *s)
1092 {
1093 STREAM_VERIFY_SANE(s);
1094 return s->data + s->getp;
1095 }
1096
1097 /* Check does this stream empty? */
1098 int
1099 stream_empty (struct stream *s)
1100 {
1101 STREAM_VERIFY_SANE(s);
1102
1103 return (s->endp == 0);
1104 }
1105
1106 /* Reset stream. */
1107 void
1108 stream_reset (struct stream *s)
1109 {
1110 STREAM_VERIFY_SANE (s);
1111
1112 s->getp = s->endp = 0;
1113 }
1114
1115 /* Write stream contens to the file discriptor. */
1116 int
1117 stream_flush (struct stream *s, int fd)
1118 {
1119 int nbytes;
1120
1121 STREAM_VERIFY_SANE(s);
1122
1123 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
1124
1125 return nbytes;
1126 }
1127
1128 /* Stream first in first out queue. */
1129
1130 struct stream_fifo *
1131 stream_fifo_new (void)
1132 {
1133 struct stream_fifo *new;
1134
1135 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
1136 return new;
1137 }
1138
1139 /* Add new stream to fifo. */
1140 void
1141 stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
1142 {
1143 if (fifo->tail)
1144 fifo->tail->next = s;
1145 else
1146 fifo->head = s;
1147
1148 fifo->tail = s;
1149
1150 fifo->count++;
1151 }
1152
1153 /* Delete first stream from fifo. */
1154 struct stream *
1155 stream_fifo_pop (struct stream_fifo *fifo)
1156 {
1157 struct stream *s;
1158
1159 s = fifo->head;
1160
1161 if (s)
1162 {
1163 fifo->head = s->next;
1164
1165 if (fifo->head == NULL)
1166 fifo->tail = NULL;
1167
1168 fifo->count--;
1169 }
1170
1171 return s;
1172 }
1173
1174 /* Return first fifo entry. */
1175 struct stream *
1176 stream_fifo_head (struct stream_fifo *fifo)
1177 {
1178 return fifo->head;
1179 }
1180
1181 void
1182 stream_fifo_clean (struct stream_fifo *fifo)
1183 {
1184 struct stream *s;
1185 struct stream *next;
1186
1187 for (s = fifo->head; s; s = next)
1188 {
1189 next = s->next;
1190 stream_free (s);
1191 }
1192 fifo->head = fifo->tail = NULL;
1193 fifo->count = 0;
1194 }
1195
1196 void
1197 stream_fifo_free (struct stream_fifo *fifo)
1198 {
1199 stream_fifo_clean (fifo);
1200 XFREE (MTYPE_STREAM_FIFO, fifo);
1201 }