blob: b226a25ea544ad8601979b8cfd9a35b2dbf77ae9 [file] [log] [blame]
paul050c0132005-02-14 23:47:47 +00001 /*
paul718e3742002-12-13 20:15:29 +00002 * 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
paul050c0132005-02-14 23:47:47 +000023#include <stddef.h>
paul718e3742002-12-13 20:15:29 +000024#include <zebra.h>
25
26#include "stream.h"
27#include "memory.h"
28#include "network.h"
29#include "prefix.h"
paul050c0132005-02-14 23:47:47 +000030#include "log.h"
paul718e3742002-12-13 20:15:29 +000031
paul050c0132005-02-14 23:47:47 +000032/* 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)
paul718e3742002-12-13 20:15:29 +000038
paul050c0132005-02-14 23:47:47 +000039/* 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) \
Subbaiah Venkatad5310502012-03-24 13:10:19 -070055 zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
paul050c0132005-02-14 23:47:47 +000056 (S), \
57 (unsigned long) (S)->size, \
58 (unsigned long) (S)->getp, \
59 (unsigned long) (S)->endp)\
paul718e3742002-12-13 20:15:29 +000060
paul050c0132005-02-14 23:47:47 +000061#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 */
paul718e3742002-12-13 20:15:29 +000077#define CHECK_SIZE(S, Z) \
paul050c0132005-02-14 23:47:47 +000078 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);
paul718e3742002-12-13 20:15:29 +000087
88/* Make stream buffer. */
89struct stream *
90stream_new (size_t size)
91{
92 struct stream *s;
93
paul0e43a2b2004-12-22 00:15:34 +000094 assert (size > 0);
95
96 if (size == 0)
paul050c0132005-02-14 23:47:47 +000097 {
98 zlog_warn ("stream_new(): called with 0 size!");
99 return NULL;
100 }
paul0e43a2b2004-12-22 00:15:34 +0000101
paul4b201d42006-01-10 14:35:19 +0000102 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
paul718e3742002-12-13 20:15:29 +0000103
paul050c0132005-02-14 23:47:47 +0000104 if (s == NULL)
105 return s;
106
paul4b201d42006-01-10 14:35:19 +0000107 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
108 {
109 XFREE (MTYPE_STREAM, s);
110 return NULL;
111 }
112
paul718e3742002-12-13 20:15:29 +0000113 s->size = size;
114 return s;
115}
116
117/* Free it now. */
118void
119stream_free (struct stream *s)
120{
paul4b201d42006-01-10 14:35:19 +0000121 if (!s)
122 return;
123
124 XFREE (MTYPE_STREAM_DATA, s->data);
paul718e3742002-12-13 20:15:29 +0000125 XFREE (MTYPE_STREAM, s);
126}
paul050c0132005-02-14 23:47:47 +0000127
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}
paul4b201d42006-01-10 14:35:19 +0000156
157size_t
158stream_resize (struct stream *s, size_t newsize)
159{
160 u_char *newdata;
161 STREAM_VERIFY_SANE (s);
162
163 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
164
165 if (newdata == NULL)
166 return s->size;
167
168 s->data = newdata;
169 s->size = newsize;
170
171 if (s->endp > s->size)
172 s->endp = s->size;
173 if (s->getp > s->endp)
174 s->getp = s->endp;
175
176 STREAM_VERIFY_SANE (s);
177
178 return s->size;
179}
paul718e3742002-12-13 20:15:29 +0000180
paulf2e6c422005-02-12 14:35:49 +0000181size_t
paul718e3742002-12-13 20:15:29 +0000182stream_get_getp (struct stream *s)
183{
paul050c0132005-02-14 23:47:47 +0000184 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000185 return s->getp;
186}
187
paulf2e6c422005-02-12 14:35:49 +0000188size_t
paul718e3742002-12-13 20:15:29 +0000189stream_get_endp (struct stream *s)
190{
paul050c0132005-02-14 23:47:47 +0000191 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000192 return s->endp;
193}
194
paulf2e6c422005-02-12 14:35:49 +0000195size_t
paul718e3742002-12-13 20:15:29 +0000196stream_get_size (struct stream *s)
197{
paul050c0132005-02-14 23:47:47 +0000198 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000199 return s->size;
200}
201
202/* Stream structre' stream pointer related functions. */
203void
paulf2e6c422005-02-12 14:35:49 +0000204stream_set_getp (struct stream *s, size_t pos)
paul718e3742002-12-13 20:15:29 +0000205{
paul050c0132005-02-14 23:47:47 +0000206 STREAM_VERIFY_SANE(s);
207
208 if (!GETP_VALID (s, pos))
209 {
210 STREAM_BOUND_WARN (s, "set getp");
211 pos = s->endp;
212 }
213
paul718e3742002-12-13 20:15:29 +0000214 s->getp = pos;
215}
216
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700217void
218stream_set_endp (struct stream *s, size_t pos)
219{
220 STREAM_VERIFY_SANE(s);
221
222 if (!GETP_VALID (s, pos))
223 {
224 STREAM_BOUND_WARN (s, "set endp");
225 pos = s->endp;
226 }
227
228 s->endp = pos;
229}
230
paul718e3742002-12-13 20:15:29 +0000231/* Forward pointer. */
232void
paul050c0132005-02-14 23:47:47 +0000233stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000234{
paul050c0132005-02-14 23:47:47 +0000235 STREAM_VERIFY_SANE(s);
236
237 if (!GETP_VALID (s, s->getp + size))
238 {
239 STREAM_BOUND_WARN (s, "seek getp");
240 return;
241 }
242
paul718e3742002-12-13 20:15:29 +0000243 s->getp += size;
244}
paul9985f832005-02-09 15:51:56 +0000245
246void
paul050c0132005-02-14 23:47:47 +0000247stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000248{
paul050c0132005-02-14 23:47:47 +0000249 STREAM_VERIFY_SANE(s);
250
251 if (!ENDP_VALID (s, s->endp + size))
252 {
253 STREAM_BOUND_WARN (s, "seek endp");
254 return;
255 }
256
paul9985f832005-02-09 15:51:56 +0000257 s->endp += size;
258}
paul718e3742002-12-13 20:15:29 +0000259
260/* Copy from stream to destination. */
261void
262stream_get (void *dst, struct stream *s, size_t size)
263{
paul050c0132005-02-14 23:47:47 +0000264 STREAM_VERIFY_SANE(s);
265
266 if (STREAM_READABLE(s) < size)
267 {
268 STREAM_BOUND_WARN (s, "get");
269 return;
270 }
271
paul718e3742002-12-13 20:15:29 +0000272 memcpy (dst, s->data + s->getp, size);
273 s->getp += size;
274}
275
276/* Get next character from the stream. */
277u_char
278stream_getc (struct stream *s)
279{
280 u_char c;
paul050c0132005-02-14 23:47:47 +0000281
282 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000283
paul050c0132005-02-14 23:47:47 +0000284 if (STREAM_READABLE(s) < sizeof (u_char))
285 {
286 STREAM_BOUND_WARN (s, "get char");
287 return 0;
288 }
289 c = s->data[s->getp++];
290
paul718e3742002-12-13 20:15:29 +0000291 return c;
292}
293
294/* Get next character from the stream. */
295u_char
paulf2e6c422005-02-12 14:35:49 +0000296stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000297{
298 u_char c;
299
paul050c0132005-02-14 23:47:47 +0000300 STREAM_VERIFY_SANE(s);
301
302 if (!GETP_VALID (s, from + sizeof (u_char)))
303 {
304 STREAM_BOUND_WARN (s, "get char");
305 return 0;
306 }
307
paul718e3742002-12-13 20:15:29 +0000308 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000309
paul718e3742002-12-13 20:15:29 +0000310 return c;
311}
312
313/* Get next word from the stream. */
314u_int16_t
315stream_getw (struct stream *s)
316{
317 u_int16_t w;
318
paul050c0132005-02-14 23:47:47 +0000319 STREAM_VERIFY_SANE (s);
320
321 if (STREAM_READABLE (s) < sizeof (u_int16_t))
322 {
323 STREAM_BOUND_WARN (s, "get ");
324 return 0;
325 }
326
paul718e3742002-12-13 20:15:29 +0000327 w = s->data[s->getp++] << 8;
328 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000329
paul718e3742002-12-13 20:15:29 +0000330 return w;
331}
332
333/* Get next word from the stream. */
334u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000335stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000336{
337 u_int16_t w;
338
paul050c0132005-02-14 23:47:47 +0000339 STREAM_VERIFY_SANE(s);
340
341 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
342 {
343 STREAM_BOUND_WARN (s, "get ");
344 return 0;
345 }
346
paul718e3742002-12-13 20:15:29 +0000347 w = s->data[from++] << 8;
348 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000349
paul718e3742002-12-13 20:15:29 +0000350 return w;
351}
352
353/* Get next long word from the stream. */
354u_int32_t
paul050c0132005-02-14 23:47:47 +0000355stream_getl_from (struct stream *s, size_t from)
356{
357 u_int32_t l;
358
359 STREAM_VERIFY_SANE(s);
360
361 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
362 {
363 STREAM_BOUND_WARN (s, "get long");
364 return 0;
365 }
366
367 l = s->data[from++] << 24;
368 l |= s->data[from++] << 16;
369 l |= s->data[from++] << 8;
370 l |= s->data[from];
371
372 return l;
373}
374
375u_int32_t
paul718e3742002-12-13 20:15:29 +0000376stream_getl (struct stream *s)
377{
378 u_int32_t l;
379
paul050c0132005-02-14 23:47:47 +0000380 STREAM_VERIFY_SANE(s);
381
382 if (STREAM_READABLE (s) < sizeof (u_int32_t))
383 {
384 STREAM_BOUND_WARN (s, "get long");
385 return 0;
386 }
387
paul718e3742002-12-13 20:15:29 +0000388 l = s->data[s->getp++] << 24;
389 l |= s->data[s->getp++] << 16;
390 l |= s->data[s->getp++] << 8;
391 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000392
paul718e3742002-12-13 20:15:29 +0000393 return l;
394}
paul4b201d42006-01-10 14:35:19 +0000395
396/* Get next quad word from the stream. */
397uint64_t
398stream_getq_from (struct stream *s, size_t from)
399{
paul581a02a2006-01-19 20:22:16 +0000400 uint64_t q;
paul4b201d42006-01-10 14:35:19 +0000401
402 STREAM_VERIFY_SANE(s);
403
404 if (!GETP_VALID (s, from + sizeof (uint64_t)))
405 {
406 STREAM_BOUND_WARN (s, "get quad");
407 return 0;
408 }
409
410 q = ((uint64_t) s->data[from++]) << 56;
411 q |= ((uint64_t) s->data[from++]) << 48;
412 q |= ((uint64_t) s->data[from++]) << 40;
413 q |= ((uint64_t) s->data[from++]) << 32;
414 q |= ((uint64_t) s->data[from++]) << 24;
415 q |= ((uint64_t) s->data[from++]) << 16;
416 q |= ((uint64_t) s->data[from++]) << 8;
417 q |= ((uint64_t) s->data[from++]);
418
419 return q;
420}
421
422uint64_t
423stream_getq (struct stream *s)
424{
425 uint64_t q;
426
427 STREAM_VERIFY_SANE(s);
428
429 if (STREAM_READABLE (s) < sizeof (uint64_t))
430 {
431 STREAM_BOUND_WARN (s, "get quad");
432 return 0;
433 }
434
435 q = ((uint64_t) s->data[s->getp++]) << 56;
436 q |= ((uint64_t) s->data[s->getp++]) << 48;
437 q |= ((uint64_t) s->data[s->getp++]) << 40;
438 q |= ((uint64_t) s->data[s->getp++]) << 32;
439 q |= ((uint64_t) s->data[s->getp++]) << 24;
440 q |= ((uint64_t) s->data[s->getp++]) << 16;
441 q |= ((uint64_t) s->data[s->getp++]) << 8;
442 q |= ((uint64_t) s->data[s->getp++]);
443
444 return q;
445}
446
paul718e3742002-12-13 20:15:29 +0000447/* Get next long word from the stream. */
448u_int32_t
449stream_get_ipv4 (struct stream *s)
450{
451 u_int32_t l;
452
paul050c0132005-02-14 23:47:47 +0000453 STREAM_VERIFY_SANE(s);
454
455 if (STREAM_READABLE (s) < sizeof(u_int32_t))
456 {
457 STREAM_BOUND_WARN (s, "get ipv4");
458 return 0;
459 }
460
461 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
462 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000463
464 return l;
465}
466
paul050c0132005-02-14 23:47:47 +0000467/* Copy to source to stream.
468 *
469 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
470 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000471 *
472 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000473 */
paul718e3742002-12-13 20:15:29 +0000474void
Paul Jakma3d52bb82008-06-07 20:42:07 +0000475stream_put (struct stream *s, const void *src, size_t size)
paul718e3742002-12-13 20:15:29 +0000476{
477
paul050c0132005-02-14 23:47:47 +0000478 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000479 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000480
481 STREAM_VERIFY_SANE(s);
482
483 if (STREAM_WRITEABLE (s) < size)
484 {
485 STREAM_BOUND_WARN (s, "put");
486 return;
487 }
488
paul718e3742002-12-13 20:15:29 +0000489 if (src)
paul9985f832005-02-09 15:51:56 +0000490 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000491 else
paul9985f832005-02-09 15:51:56 +0000492 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000493
paul9985f832005-02-09 15:51:56 +0000494 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000495}
496
497/* Put character to the stream. */
498int
499stream_putc (struct stream *s, u_char c)
500{
paul050c0132005-02-14 23:47:47 +0000501 STREAM_VERIFY_SANE(s);
502
503 if (STREAM_WRITEABLE (s) < sizeof(u_char))
504 {
505 STREAM_BOUND_WARN (s, "put");
506 return 0;
507 }
508
509 s->data[s->endp++] = c;
510 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000511}
512
513/* Put word to the stream. */
514int
515stream_putw (struct stream *s, u_int16_t w)
516{
paul050c0132005-02-14 23:47:47 +0000517 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000518
paul050c0132005-02-14 23:47:47 +0000519 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
520 {
521 STREAM_BOUND_WARN (s, "put");
522 return 0;
523 }
524
paul9985f832005-02-09 15:51:56 +0000525 s->data[s->endp++] = (u_char)(w >> 8);
526 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000527
paul718e3742002-12-13 20:15:29 +0000528 return 2;
529}
530
531/* Put long word to the stream. */
532int
533stream_putl (struct stream *s, u_int32_t l)
534{
paul050c0132005-02-14 23:47:47 +0000535 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000536
paul050c0132005-02-14 23:47:47 +0000537 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
538 {
539 STREAM_BOUND_WARN (s, "put");
540 return 0;
541 }
542
paul9985f832005-02-09 15:51:56 +0000543 s->data[s->endp++] = (u_char)(l >> 24);
544 s->data[s->endp++] = (u_char)(l >> 16);
545 s->data[s->endp++] = (u_char)(l >> 8);
546 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000547
paul718e3742002-12-13 20:15:29 +0000548 return 4;
549}
550
paul4b201d42006-01-10 14:35:19 +0000551/* Put quad word to the stream. */
552int
553stream_putq (struct stream *s, uint64_t q)
554{
555 STREAM_VERIFY_SANE (s);
556
557 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
558 {
559 STREAM_BOUND_WARN (s, "put quad");
560 return 0;
561 }
562
563 s->data[s->endp++] = (u_char)(q >> 56);
564 s->data[s->endp++] = (u_char)(q >> 48);
565 s->data[s->endp++] = (u_char)(q >> 40);
566 s->data[s->endp++] = (u_char)(q >> 32);
567 s->data[s->endp++] = (u_char)(q >> 24);
568 s->data[s->endp++] = (u_char)(q >> 16);
569 s->data[s->endp++] = (u_char)(q >> 8);
570 s->data[s->endp++] = (u_char)q;
571
572 return 8;
573}
574
paul718e3742002-12-13 20:15:29 +0000575int
paulf2e6c422005-02-12 14:35:49 +0000576stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000577{
paul050c0132005-02-14 23:47:47 +0000578 STREAM_VERIFY_SANE(s);
579
580 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
581 {
582 STREAM_BOUND_WARN (s, "put");
583 return 0;
584 }
585
paul718e3742002-12-13 20:15:29 +0000586 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000587
paul718e3742002-12-13 20:15:29 +0000588 return 1;
589}
590
591int
paulf2e6c422005-02-12 14:35:49 +0000592stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000593{
paul050c0132005-02-14 23:47:47 +0000594 STREAM_VERIFY_SANE(s);
595
596 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
597 {
598 STREAM_BOUND_WARN (s, "put");
599 return 0;
600 }
601
paul718e3742002-12-13 20:15:29 +0000602 s->data[putp] = (u_char)(w >> 8);
603 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000604
paul718e3742002-12-13 20:15:29 +0000605 return 2;
606}
607
608int
paulf2e6c422005-02-12 14:35:49 +0000609stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000610{
paul050c0132005-02-14 23:47:47 +0000611 STREAM_VERIFY_SANE(s);
612
613 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
614 {
615 STREAM_BOUND_WARN (s, "put");
616 return 0;
617 }
paul718e3742002-12-13 20:15:29 +0000618 s->data[putp] = (u_char)(l >> 24);
619 s->data[putp + 1] = (u_char)(l >> 16);
620 s->data[putp + 2] = (u_char)(l >> 8);
621 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000622
paul718e3742002-12-13 20:15:29 +0000623 return 4;
624}
625
paul4b201d42006-01-10 14:35:19 +0000626int
627stream_putq_at (struct stream *s, size_t putp, uint64_t q)
628{
629 STREAM_VERIFY_SANE(s);
630
631 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
632 {
633 STREAM_BOUND_WARN (s, "put");
634 return 0;
635 }
636 s->data[putp] = (u_char)(q >> 56);
637 s->data[putp + 1] = (u_char)(q >> 48);
638 s->data[putp + 2] = (u_char)(q >> 40);
639 s->data[putp + 3] = (u_char)(q >> 32);
640 s->data[putp + 4] = (u_char)(q >> 24);
641 s->data[putp + 5] = (u_char)(q >> 16);
642 s->data[putp + 6] = (u_char)(q >> 8);
643 s->data[putp + 7] = (u_char)q;
644
645 return 8;
646}
647
paul718e3742002-12-13 20:15:29 +0000648/* Put long word to the stream. */
649int
650stream_put_ipv4 (struct stream *s, u_int32_t l)
651{
paul050c0132005-02-14 23:47:47 +0000652 STREAM_VERIFY_SANE(s);
653
654 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
655 {
656 STREAM_BOUND_WARN (s, "put");
657 return 0;
658 }
659 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
660 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000661
paul050c0132005-02-14 23:47:47 +0000662 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000663}
664
665/* Put long word to the stream. */
666int
667stream_put_in_addr (struct stream *s, struct in_addr *addr)
668{
paul050c0132005-02-14 23:47:47 +0000669 STREAM_VERIFY_SANE(s);
670
671 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
672 {
673 STREAM_BOUND_WARN (s, "put");
674 return 0;
675 }
paul718e3742002-12-13 20:15:29 +0000676
paul050c0132005-02-14 23:47:47 +0000677 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
678 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000679
paul050c0132005-02-14 23:47:47 +0000680 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000681}
682
683/* Put prefix by nlri type format. */
684int
685stream_put_prefix (struct stream *s, struct prefix *p)
686{
paul050c0132005-02-14 23:47:47 +0000687 size_t psize;
688
689 STREAM_VERIFY_SANE(s);
690
paul718e3742002-12-13 20:15:29 +0000691 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000692
693 if (STREAM_WRITEABLE (s) < psize)
694 {
695 STREAM_BOUND_WARN (s, "put");
696 return 0;
697 }
698
paul718e3742002-12-13 20:15:29 +0000699 stream_putc (s, p->prefixlen);
paul9985f832005-02-09 15:51:56 +0000700 memcpy (s->data + s->endp, &p->u.prefix, psize);
701 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000702
paul718e3742002-12-13 20:15:29 +0000703 return psize;
704}
705
706/* Read size from fd. */
707int
708stream_read (struct stream *s, int fd, size_t size)
709{
710 int nbytes;
711
paul050c0132005-02-14 23:47:47 +0000712 STREAM_VERIFY_SANE(s);
713
714 if (STREAM_WRITEABLE (s) < size)
715 {
716 STREAM_BOUND_WARN (s, "put");
717 return 0;
718 }
719
paul9985f832005-02-09 15:51:56 +0000720 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000721
722 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000723 s->endp += nbytes;
724
paul718e3742002-12-13 20:15:29 +0000725 return nbytes;
726}
727
728/* Read size from fd. */
729int
730stream_read_unblock (struct stream *s, int fd, size_t size)
731{
732 int nbytes;
733 int val;
paul050c0132005-02-14 23:47:47 +0000734
735 STREAM_VERIFY_SANE(s);
736
737 if (STREAM_WRITEABLE (s) < size)
738 {
739 STREAM_BOUND_WARN (s, "put");
740 return 0;
741 }
742
paul718e3742002-12-13 20:15:29 +0000743 val = fcntl (fd, F_GETFL, 0);
744 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000745 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000746 fcntl (fd, F_SETFL, val);
747
748 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000749 s->endp += nbytes;
750
paul718e3742002-12-13 20:15:29 +0000751 return nbytes;
752}
753
ajs262feb12005-02-16 20:35:47 +0000754ssize_t
755stream_read_try(struct stream *s, int fd, size_t size)
756{
757 ssize_t nbytes;
758
759 STREAM_VERIFY_SANE(s);
760
761 if (STREAM_WRITEABLE(s) < size)
762 {
763 STREAM_BOUND_WARN (s, "put");
764 /* Fatal (not transient) error, since retrying will not help
765 (stream is too small to contain the desired data). */
766 return -1;
767 }
768
769 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
770 {
771 s->endp += nbytes;
772 return nbytes;
773 }
774 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000775 if (ERRNO_IO_RETRY(errno))
776 return -2;
777 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
778 return -1;
ajs262feb12005-02-16 20:35:47 +0000779}
780
paul0dab9302005-05-03 09:07:56 +0000781/* Read up to size bytes into the stream from the fd, using recvmsgfrom
782 * whose arguments match the remaining arguments to this function
783 */
784ssize_t
785stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
786 struct sockaddr *from, socklen_t *fromlen)
787{
788 ssize_t nbytes;
789
790 STREAM_VERIFY_SANE(s);
791
792 if (STREAM_WRITEABLE(s) < size)
793 {
794 STREAM_BOUND_WARN (s, "put");
795 /* Fatal (not transient) error, since retrying will not help
796 (stream is too small to contain the desired data). */
797 return -1;
798 }
799
800 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
801 flags, from, fromlen)) >= 0)
802 {
803 s->endp += nbytes;
804 return nbytes;
805 }
806 /* Error: was it transient (return -2) or fatal (return -1)? */
807 if (ERRNO_IO_RETRY(errno))
808 return -2;
809 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
810 return -1;
811}
812
paul050c0132005-02-14 23:47:47 +0000813/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
814 * from endp.
815 * First iovec will be used to receive the data.
816 * Stream need not be empty.
817 */
paul0dab9302005-05-03 09:07:56 +0000818ssize_t
paul050c0132005-02-14 23:47:47 +0000819stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
820 size_t size)
821{
822 int nbytes;
823 struct iovec *iov;
824
825 STREAM_VERIFY_SANE(s);
826 assert (msgh->msg_iovlen > 0);
827
828 if (STREAM_WRITEABLE (s) < size)
829 {
830 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000831 /* This is a logic error in the calling code: the stream is too small
832 to hold the desired data! */
833 return -1;
paul050c0132005-02-14 23:47:47 +0000834 }
835
836 iov = &(msgh->msg_iov[0]);
837 iov->iov_base = (s->data + s->endp);
838 iov->iov_len = size;
839
840 nbytes = recvmsg (fd, msgh, flags);
841
842 if (nbytes > 0)
843 s->endp += nbytes;
844
845 return nbytes;
846}
847
paul718e3742002-12-13 20:15:29 +0000848/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000849size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000850stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000851{
852
853 CHECK_SIZE(s, size);
854
paul050c0132005-02-14 23:47:47 +0000855 STREAM_VERIFY_SANE(s);
856
857 if (STREAM_WRITEABLE (s) < size)
858 {
859 STREAM_BOUND_WARN (s, "put");
860 return 0;
861 }
862
paul9985f832005-02-09 15:51:56 +0000863 memcpy (s->data + s->endp, ptr, size);
864 s->endp += size;
865
paul718e3742002-12-13 20:15:29 +0000866 return size;
867}
868
paul050c0132005-02-14 23:47:47 +0000869/* Return current read pointer.
870 * DEPRECATED!
871 * Use stream_get_pnt_to if you must, but decoding streams properly
872 * is preferred
873 */
paul718e3742002-12-13 20:15:29 +0000874u_char *
875stream_pnt (struct stream *s)
876{
paul050c0132005-02-14 23:47:47 +0000877 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000878 return s->data + s->getp;
879}
880
881/* Check does this stream empty? */
882int
883stream_empty (struct stream *s)
884{
paul050c0132005-02-14 23:47:47 +0000885 STREAM_VERIFY_SANE(s);
886
887 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000888}
889
890/* Reset stream. */
891void
892stream_reset (struct stream *s)
893{
paul050c0132005-02-14 23:47:47 +0000894 STREAM_VERIFY_SANE (s);
895
896 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000897}
898
899/* Write stream contens to the file discriptor. */
900int
901stream_flush (struct stream *s, int fd)
902{
903 int nbytes;
paul050c0132005-02-14 23:47:47 +0000904
905 STREAM_VERIFY_SANE(s);
906
paul718e3742002-12-13 20:15:29 +0000907 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000908
paul718e3742002-12-13 20:15:29 +0000909 return nbytes;
910}
911
912/* Stream first in first out queue. */
913
914struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000915stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000916{
917 struct stream_fifo *new;
918
919 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
920 return new;
921}
922
923/* Add new stream to fifo. */
924void
925stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
926{
927 if (fifo->tail)
928 fifo->tail->next = s;
929 else
930 fifo->head = s;
931
932 fifo->tail = s;
933
934 fifo->count++;
935}
936
937/* Delete first stream from fifo. */
938struct stream *
939stream_fifo_pop (struct stream_fifo *fifo)
940{
941 struct stream *s;
942
943 s = fifo->head;
944
945 if (s)
946 {
947 fifo->head = s->next;
948
949 if (fifo->head == NULL)
950 fifo->tail = NULL;
paul718e3742002-12-13 20:15:29 +0000951
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700952 fifo->count--;
953 }
paul718e3742002-12-13 20:15:29 +0000954
955 return s;
956}
957
958/* Return first fifo entry. */
959struct stream *
960stream_fifo_head (struct stream_fifo *fifo)
961{
962 return fifo->head;
963}
964
965void
966stream_fifo_clean (struct stream_fifo *fifo)
967{
968 struct stream *s;
969 struct stream *next;
970
971 for (s = fifo->head; s; s = next)
972 {
973 next = s->next;
974 stream_free (s);
975 }
976 fifo->head = fifo->tail = NULL;
977 fifo->count = 0;
978}
979
980void
981stream_fifo_free (struct stream_fifo *fifo)
982{
983 stream_fifo_clean (fifo);
984 XFREE (MTYPE_STREAM_FIFO, fifo);
985}