blob: 9c26fea88c9a774310d9454f7e39a29eac0447d0 [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", \
David Lampartereed3c482015-03-03 08:51:53 +010056 (void *)(S), \
paul050c0132005-02-14 23:47:47 +000057 (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 { \
Wenjian Ma1ed8ce42015-06-19 10:53:26 +080063 if ( !(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp)) ) \
paul050c0132005-02-14 23:47:47 +000064 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
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000157struct stream *
158stream_dupcat (struct stream *s1, struct stream *s2, size_t offset)
159{
160 struct stream *new;
161
162 STREAM_VERIFY_SANE (s1);
163 STREAM_VERIFY_SANE (s2);
164
165 if ( (new = stream_new (s1->endp + s2->endp)) == NULL)
166 return NULL;
167
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;
173 return new;
174}
175
paul4b201d42006-01-10 14:35:19 +0000176size_t
177stream_resize (struct stream *s, size_t newsize)
178{
179 u_char *newdata;
180 STREAM_VERIFY_SANE (s);
181
182 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
183
184 if (newdata == NULL)
185 return s->size;
186
187 s->data = newdata;
188 s->size = newsize;
189
190 if (s->endp > s->size)
191 s->endp = s->size;
192 if (s->getp > s->endp)
193 s->getp = s->endp;
194
195 STREAM_VERIFY_SANE (s);
196
197 return s->size;
198}
David Lamparter6b0655a2014-06-04 06:53:35 +0200199
paulf2e6c422005-02-12 14:35:49 +0000200size_t
paul718e3742002-12-13 20:15:29 +0000201stream_get_getp (struct stream *s)
202{
paul050c0132005-02-14 23:47:47 +0000203 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000204 return s->getp;
205}
206
paulf2e6c422005-02-12 14:35:49 +0000207size_t
paul718e3742002-12-13 20:15:29 +0000208stream_get_endp (struct stream *s)
209{
paul050c0132005-02-14 23:47:47 +0000210 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000211 return s->endp;
212}
213
paulf2e6c422005-02-12 14:35:49 +0000214size_t
paul718e3742002-12-13 20:15:29 +0000215stream_get_size (struct stream *s)
216{
paul050c0132005-02-14 23:47:47 +0000217 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000218 return s->size;
219}
220
221/* Stream structre' stream pointer related functions. */
222void
paulf2e6c422005-02-12 14:35:49 +0000223stream_set_getp (struct stream *s, size_t pos)
paul718e3742002-12-13 20:15:29 +0000224{
paul050c0132005-02-14 23:47:47 +0000225 STREAM_VERIFY_SANE(s);
226
227 if (!GETP_VALID (s, pos))
228 {
229 STREAM_BOUND_WARN (s, "set getp");
230 pos = s->endp;
231 }
232
paul718e3742002-12-13 20:15:29 +0000233 s->getp = pos;
234}
235
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700236void
237stream_set_endp (struct stream *s, size_t pos)
238{
239 STREAM_VERIFY_SANE(s);
240
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700241 if (!ENDP_VALID(s, pos))
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700242 {
243 STREAM_BOUND_WARN (s, "set endp");
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700244 return;
245 }
246
247 /*
248 * Make sure the current read pointer is not beyond the new endp.
249 */
250 if (s->getp > pos)
251 {
252 STREAM_BOUND_WARN(s, "set endp");
253 return;
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700254 }
255
256 s->endp = pos;
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700257 STREAM_VERIFY_SANE(s);
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700258}
259
paul718e3742002-12-13 20:15:29 +0000260/* Forward pointer. */
261void
paul050c0132005-02-14 23:47:47 +0000262stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000263{
paul050c0132005-02-14 23:47:47 +0000264 STREAM_VERIFY_SANE(s);
265
266 if (!GETP_VALID (s, s->getp + size))
267 {
268 STREAM_BOUND_WARN (s, "seek getp");
269 return;
270 }
271
paul718e3742002-12-13 20:15:29 +0000272 s->getp += size;
273}
paul9985f832005-02-09 15:51:56 +0000274
275void
paul050c0132005-02-14 23:47:47 +0000276stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000277{
paul050c0132005-02-14 23:47:47 +0000278 STREAM_VERIFY_SANE(s);
279
280 if (!ENDP_VALID (s, s->endp + size))
281 {
282 STREAM_BOUND_WARN (s, "seek endp");
283 return;
284 }
285
paul9985f832005-02-09 15:51:56 +0000286 s->endp += size;
287}
David Lamparter6b0655a2014-06-04 06:53:35 +0200288
paul718e3742002-12-13 20:15:29 +0000289/* Copy from stream to destination. */
290void
291stream_get (void *dst, struct stream *s, size_t size)
292{
paul050c0132005-02-14 23:47:47 +0000293 STREAM_VERIFY_SANE(s);
294
295 if (STREAM_READABLE(s) < size)
296 {
297 STREAM_BOUND_WARN (s, "get");
298 return;
299 }
300
paul718e3742002-12-13 20:15:29 +0000301 memcpy (dst, s->data + s->getp, size);
302 s->getp += size;
303}
304
305/* Get next character from the stream. */
306u_char
307stream_getc (struct stream *s)
308{
309 u_char c;
paul050c0132005-02-14 23:47:47 +0000310
311 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000312
paul050c0132005-02-14 23:47:47 +0000313 if (STREAM_READABLE(s) < sizeof (u_char))
314 {
315 STREAM_BOUND_WARN (s, "get char");
316 return 0;
317 }
318 c = s->data[s->getp++];
319
paul718e3742002-12-13 20:15:29 +0000320 return c;
321}
322
323/* Get next character from the stream. */
324u_char
paulf2e6c422005-02-12 14:35:49 +0000325stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000326{
327 u_char c;
328
paul050c0132005-02-14 23:47:47 +0000329 STREAM_VERIFY_SANE(s);
330
331 if (!GETP_VALID (s, from + sizeof (u_char)))
332 {
333 STREAM_BOUND_WARN (s, "get char");
334 return 0;
335 }
336
paul718e3742002-12-13 20:15:29 +0000337 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000338
paul718e3742002-12-13 20:15:29 +0000339 return c;
340}
341
342/* Get next word from the stream. */
343u_int16_t
344stream_getw (struct stream *s)
345{
346 u_int16_t w;
347
paul050c0132005-02-14 23:47:47 +0000348 STREAM_VERIFY_SANE (s);
349
350 if (STREAM_READABLE (s) < sizeof (u_int16_t))
351 {
352 STREAM_BOUND_WARN (s, "get ");
353 return 0;
354 }
355
paul718e3742002-12-13 20:15:29 +0000356 w = s->data[s->getp++] << 8;
357 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000358
paul718e3742002-12-13 20:15:29 +0000359 return w;
360}
361
362/* Get next word from the stream. */
363u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000364stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000365{
366 u_int16_t w;
367
paul050c0132005-02-14 23:47:47 +0000368 STREAM_VERIFY_SANE(s);
369
370 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
371 {
372 STREAM_BOUND_WARN (s, "get ");
373 return 0;
374 }
375
paul718e3742002-12-13 20:15:29 +0000376 w = s->data[from++] << 8;
377 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000378
paul718e3742002-12-13 20:15:29 +0000379 return w;
380}
381
382/* Get next long word from the stream. */
383u_int32_t
paul050c0132005-02-14 23:47:47 +0000384stream_getl_from (struct stream *s, size_t from)
385{
386 u_int32_t l;
387
388 STREAM_VERIFY_SANE(s);
389
390 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
391 {
392 STREAM_BOUND_WARN (s, "get long");
393 return 0;
394 }
395
396 l = s->data[from++] << 24;
397 l |= s->data[from++] << 16;
398 l |= s->data[from++] << 8;
399 l |= s->data[from];
400
401 return l;
402}
403
404u_int32_t
paul718e3742002-12-13 20:15:29 +0000405stream_getl (struct stream *s)
406{
407 u_int32_t l;
408
paul050c0132005-02-14 23:47:47 +0000409 STREAM_VERIFY_SANE(s);
410
411 if (STREAM_READABLE (s) < sizeof (u_int32_t))
412 {
413 STREAM_BOUND_WARN (s, "get long");
414 return 0;
415 }
416
paul718e3742002-12-13 20:15:29 +0000417 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++];
paul050c0132005-02-14 23:47:47 +0000421
paul718e3742002-12-13 20:15:29 +0000422 return l;
423}
paul4b201d42006-01-10 14:35:19 +0000424
425/* Get next quad word from the stream. */
426uint64_t
427stream_getq_from (struct stream *s, size_t from)
428{
paul581a02a2006-01-19 20:22:16 +0000429 uint64_t q;
paul4b201d42006-01-10 14:35:19 +0000430
431 STREAM_VERIFY_SANE(s);
432
433 if (!GETP_VALID (s, from + sizeof (uint64_t)))
434 {
435 STREAM_BOUND_WARN (s, "get quad");
436 return 0;
437 }
438
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++]);
447
448 return q;
449}
450
451uint64_t
452stream_getq (struct stream *s)
453{
454 uint64_t q;
455
456 STREAM_VERIFY_SANE(s);
457
458 if (STREAM_READABLE (s) < sizeof (uint64_t))
459 {
460 STREAM_BOUND_WARN (s, "get quad");
461 return 0;
462 }
463
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++]);
472
473 return q;
474}
475
paul718e3742002-12-13 20:15:29 +0000476/* Get next long word from the stream. */
477u_int32_t
478stream_get_ipv4 (struct stream *s)
479{
480 u_int32_t l;
481
paul050c0132005-02-14 23:47:47 +0000482 STREAM_VERIFY_SANE(s);
483
484 if (STREAM_READABLE (s) < sizeof(u_int32_t))
485 {
486 STREAM_BOUND_WARN (s, "get ipv4");
487 return 0;
488 }
489
490 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
491 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000492
493 return l;
494}
David Lamparter6b0655a2014-06-04 06:53:35 +0200495
paul050c0132005-02-14 23:47:47 +0000496/* Copy to source to stream.
497 *
498 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
499 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000500 *
501 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000502 */
paul718e3742002-12-13 20:15:29 +0000503void
Paul Jakma3d52bb82008-06-07 20:42:07 +0000504stream_put (struct stream *s, const void *src, size_t size)
paul718e3742002-12-13 20:15:29 +0000505{
506
paul050c0132005-02-14 23:47:47 +0000507 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000508 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000509
510 STREAM_VERIFY_SANE(s);
511
512 if (STREAM_WRITEABLE (s) < size)
513 {
514 STREAM_BOUND_WARN (s, "put");
515 return;
516 }
517
paul718e3742002-12-13 20:15:29 +0000518 if (src)
paul9985f832005-02-09 15:51:56 +0000519 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000520 else
paul9985f832005-02-09 15:51:56 +0000521 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000522
paul9985f832005-02-09 15:51:56 +0000523 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000524}
525
526/* Put character to the stream. */
527int
528stream_putc (struct stream *s, u_char c)
529{
paul050c0132005-02-14 23:47:47 +0000530 STREAM_VERIFY_SANE(s);
531
532 if (STREAM_WRITEABLE (s) < sizeof(u_char))
533 {
534 STREAM_BOUND_WARN (s, "put");
535 return 0;
536 }
537
538 s->data[s->endp++] = c;
539 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000540}
541
542/* Put word to the stream. */
543int
544stream_putw (struct stream *s, u_int16_t w)
545{
paul050c0132005-02-14 23:47:47 +0000546 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000547
paul050c0132005-02-14 23:47:47 +0000548 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
549 {
550 STREAM_BOUND_WARN (s, "put");
551 return 0;
552 }
553
paul9985f832005-02-09 15:51:56 +0000554 s->data[s->endp++] = (u_char)(w >> 8);
555 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000556
paul718e3742002-12-13 20:15:29 +0000557 return 2;
558}
559
560/* Put long word to the stream. */
561int
562stream_putl (struct stream *s, u_int32_t l)
563{
paul050c0132005-02-14 23:47:47 +0000564 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000565
paul050c0132005-02-14 23:47:47 +0000566 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
567 {
568 STREAM_BOUND_WARN (s, "put");
569 return 0;
570 }
571
paul9985f832005-02-09 15:51:56 +0000572 s->data[s->endp++] = (u_char)(l >> 24);
573 s->data[s->endp++] = (u_char)(l >> 16);
574 s->data[s->endp++] = (u_char)(l >> 8);
575 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000576
paul718e3742002-12-13 20:15:29 +0000577 return 4;
578}
579
paul4b201d42006-01-10 14:35:19 +0000580/* Put quad word to the stream. */
581int
582stream_putq (struct stream *s, uint64_t q)
583{
584 STREAM_VERIFY_SANE (s);
585
586 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
587 {
588 STREAM_BOUND_WARN (s, "put quad");
589 return 0;
590 }
591
592 s->data[s->endp++] = (u_char)(q >> 56);
593 s->data[s->endp++] = (u_char)(q >> 48);
594 s->data[s->endp++] = (u_char)(q >> 40);
595 s->data[s->endp++] = (u_char)(q >> 32);
596 s->data[s->endp++] = (u_char)(q >> 24);
597 s->data[s->endp++] = (u_char)(q >> 16);
598 s->data[s->endp++] = (u_char)(q >> 8);
599 s->data[s->endp++] = (u_char)q;
600
601 return 8;
602}
603
paul718e3742002-12-13 20:15:29 +0000604int
paulf2e6c422005-02-12 14:35:49 +0000605stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000606{
paul050c0132005-02-14 23:47:47 +0000607 STREAM_VERIFY_SANE(s);
608
609 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
610 {
611 STREAM_BOUND_WARN (s, "put");
612 return 0;
613 }
614
paul718e3742002-12-13 20:15:29 +0000615 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000616
paul718e3742002-12-13 20:15:29 +0000617 return 1;
618}
619
620int
paulf2e6c422005-02-12 14:35:49 +0000621stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000622{
paul050c0132005-02-14 23:47:47 +0000623 STREAM_VERIFY_SANE(s);
624
625 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
626 {
627 STREAM_BOUND_WARN (s, "put");
628 return 0;
629 }
630
paul718e3742002-12-13 20:15:29 +0000631 s->data[putp] = (u_char)(w >> 8);
632 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000633
paul718e3742002-12-13 20:15:29 +0000634 return 2;
635}
636
637int
paulf2e6c422005-02-12 14:35:49 +0000638stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000639{
paul050c0132005-02-14 23:47:47 +0000640 STREAM_VERIFY_SANE(s);
641
642 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
643 {
644 STREAM_BOUND_WARN (s, "put");
645 return 0;
646 }
paul718e3742002-12-13 20:15:29 +0000647 s->data[putp] = (u_char)(l >> 24);
648 s->data[putp + 1] = (u_char)(l >> 16);
649 s->data[putp + 2] = (u_char)(l >> 8);
650 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000651
paul718e3742002-12-13 20:15:29 +0000652 return 4;
653}
654
paul4b201d42006-01-10 14:35:19 +0000655int
656stream_putq_at (struct stream *s, size_t putp, uint64_t q)
657{
658 STREAM_VERIFY_SANE(s);
659
660 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
661 {
662 STREAM_BOUND_WARN (s, "put");
663 return 0;
664 }
665 s->data[putp] = (u_char)(q >> 56);
666 s->data[putp + 1] = (u_char)(q >> 48);
667 s->data[putp + 2] = (u_char)(q >> 40);
668 s->data[putp + 3] = (u_char)(q >> 32);
669 s->data[putp + 4] = (u_char)(q >> 24);
670 s->data[putp + 5] = (u_char)(q >> 16);
671 s->data[putp + 6] = (u_char)(q >> 8);
672 s->data[putp + 7] = (u_char)q;
673
674 return 8;
675}
676
paul718e3742002-12-13 20:15:29 +0000677/* Put long word to the stream. */
678int
679stream_put_ipv4 (struct stream *s, u_int32_t l)
680{
paul050c0132005-02-14 23:47:47 +0000681 STREAM_VERIFY_SANE(s);
682
683 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
684 {
685 STREAM_BOUND_WARN (s, "put");
686 return 0;
687 }
688 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
689 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000690
paul050c0132005-02-14 23:47:47 +0000691 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000692}
693
694/* Put long word to the stream. */
695int
696stream_put_in_addr (struct stream *s, struct in_addr *addr)
697{
paul050c0132005-02-14 23:47:47 +0000698 STREAM_VERIFY_SANE(s);
699
700 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
701 {
702 STREAM_BOUND_WARN (s, "put");
703 return 0;
704 }
paul718e3742002-12-13 20:15:29 +0000705
paul050c0132005-02-14 23:47:47 +0000706 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
707 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000708
paul050c0132005-02-14 23:47:47 +0000709 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000710}
711
712/* Put prefix by nlri type format. */
713int
714stream_put_prefix (struct stream *s, struct prefix *p)
715{
paul050c0132005-02-14 23:47:47 +0000716 size_t psize;
717
718 STREAM_VERIFY_SANE(s);
719
paul718e3742002-12-13 20:15:29 +0000720 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000721
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000722 if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
paul050c0132005-02-14 23:47:47 +0000723 {
724 STREAM_BOUND_WARN (s, "put");
725 return 0;
726 }
727
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000728 s->data[s->endp++] = p->prefixlen;
paul9985f832005-02-09 15:51:56 +0000729 memcpy (s->data + s->endp, &p->u.prefix, psize);
730 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000731
paul718e3742002-12-13 20:15:29 +0000732 return psize;
733}
David Lamparter6b0655a2014-06-04 06:53:35 +0200734
paul718e3742002-12-13 20:15:29 +0000735/* Read size from fd. */
736int
737stream_read (struct stream *s, int fd, size_t size)
738{
739 int nbytes;
740
paul050c0132005-02-14 23:47:47 +0000741 STREAM_VERIFY_SANE(s);
742
743 if (STREAM_WRITEABLE (s) < size)
744 {
745 STREAM_BOUND_WARN (s, "put");
746 return 0;
747 }
748
paul9985f832005-02-09 15:51:56 +0000749 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000750
751 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000752 s->endp += nbytes;
753
paul718e3742002-12-13 20:15:29 +0000754 return nbytes;
755}
756
ajs262feb12005-02-16 20:35:47 +0000757ssize_t
758stream_read_try(struct stream *s, int fd, size_t size)
759{
760 ssize_t nbytes;
761
762 STREAM_VERIFY_SANE(s);
763
764 if (STREAM_WRITEABLE(s) < size)
765 {
766 STREAM_BOUND_WARN (s, "put");
767 /* Fatal (not transient) error, since retrying will not help
768 (stream is too small to contain the desired data). */
769 return -1;
770 }
771
772 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
773 {
774 s->endp += nbytes;
775 return nbytes;
776 }
777 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000778 if (ERRNO_IO_RETRY(errno))
779 return -2;
780 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
781 return -1;
ajs262feb12005-02-16 20:35:47 +0000782}
783
paul0dab9302005-05-03 09:07:56 +0000784/* Read up to size bytes into the stream from the fd, using recvmsgfrom
785 * whose arguments match the remaining arguments to this function
786 */
787ssize_t
788stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
789 struct sockaddr *from, socklen_t *fromlen)
790{
791 ssize_t nbytes;
792
793 STREAM_VERIFY_SANE(s);
794
795 if (STREAM_WRITEABLE(s) < size)
796 {
797 STREAM_BOUND_WARN (s, "put");
798 /* Fatal (not transient) error, since retrying will not help
799 (stream is too small to contain the desired data). */
800 return -1;
801 }
802
803 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
804 flags, from, fromlen)) >= 0)
805 {
806 s->endp += nbytes;
807 return nbytes;
808 }
809 /* Error: was it transient (return -2) or fatal (return -1)? */
810 if (ERRNO_IO_RETRY(errno))
811 return -2;
812 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
813 return -1;
814}
815
paul050c0132005-02-14 23:47:47 +0000816/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
817 * from endp.
818 * First iovec will be used to receive the data.
819 * Stream need not be empty.
820 */
paul0dab9302005-05-03 09:07:56 +0000821ssize_t
paul050c0132005-02-14 23:47:47 +0000822stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
823 size_t size)
824{
825 int nbytes;
826 struct iovec *iov;
827
828 STREAM_VERIFY_SANE(s);
829 assert (msgh->msg_iovlen > 0);
830
831 if (STREAM_WRITEABLE (s) < size)
832 {
833 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000834 /* This is a logic error in the calling code: the stream is too small
835 to hold the desired data! */
836 return -1;
paul050c0132005-02-14 23:47:47 +0000837 }
838
839 iov = &(msgh->msg_iov[0]);
840 iov->iov_base = (s->data + s->endp);
841 iov->iov_len = size;
842
843 nbytes = recvmsg (fd, msgh, flags);
844
845 if (nbytes > 0)
846 s->endp += nbytes;
847
848 return nbytes;
849}
850
paul718e3742002-12-13 20:15:29 +0000851/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000852size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000853stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000854{
855
856 CHECK_SIZE(s, size);
857
paul050c0132005-02-14 23:47:47 +0000858 STREAM_VERIFY_SANE(s);
859
860 if (STREAM_WRITEABLE (s) < size)
861 {
862 STREAM_BOUND_WARN (s, "put");
863 return 0;
864 }
865
paul9985f832005-02-09 15:51:56 +0000866 memcpy (s->data + s->endp, ptr, size);
867 s->endp += size;
868
paul718e3742002-12-13 20:15:29 +0000869 return size;
870}
871
paul050c0132005-02-14 23:47:47 +0000872/* Return current read pointer.
873 * DEPRECATED!
874 * Use stream_get_pnt_to if you must, but decoding streams properly
875 * is preferred
876 */
paul718e3742002-12-13 20:15:29 +0000877u_char *
878stream_pnt (struct stream *s)
879{
paul050c0132005-02-14 23:47:47 +0000880 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000881 return s->data + s->getp;
882}
883
884/* Check does this stream empty? */
885int
886stream_empty (struct stream *s)
887{
paul050c0132005-02-14 23:47:47 +0000888 STREAM_VERIFY_SANE(s);
889
890 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000891}
892
893/* Reset stream. */
894void
895stream_reset (struct stream *s)
896{
paul050c0132005-02-14 23:47:47 +0000897 STREAM_VERIFY_SANE (s);
898
899 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000900}
901
902/* Write stream contens to the file discriptor. */
903int
904stream_flush (struct stream *s, int fd)
905{
906 int nbytes;
paul050c0132005-02-14 23:47:47 +0000907
908 STREAM_VERIFY_SANE(s);
909
paul718e3742002-12-13 20:15:29 +0000910 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000911
paul718e3742002-12-13 20:15:29 +0000912 return nbytes;
913}
David Lamparter6b0655a2014-06-04 06:53:35 +0200914
paul718e3742002-12-13 20:15:29 +0000915/* Stream first in first out queue. */
916
917struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000918stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000919{
920 struct stream_fifo *new;
921
922 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
923 return new;
924}
925
926/* Add new stream to fifo. */
927void
928stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
929{
930 if (fifo->tail)
931 fifo->tail->next = s;
932 else
933 fifo->head = s;
934
935 fifo->tail = s;
936
937 fifo->count++;
938}
939
940/* Delete first stream from fifo. */
941struct stream *
942stream_fifo_pop (struct stream_fifo *fifo)
943{
944 struct stream *s;
945
946 s = fifo->head;
947
948 if (s)
949 {
950 fifo->head = s->next;
951
952 if (fifo->head == NULL)
953 fifo->tail = NULL;
paul718e3742002-12-13 20:15:29 +0000954
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700955 fifo->count--;
956 }
paul718e3742002-12-13 20:15:29 +0000957
958 return s;
959}
960
961/* Return first fifo entry. */
962struct stream *
963stream_fifo_head (struct stream_fifo *fifo)
964{
965 return fifo->head;
966}
967
968void
969stream_fifo_clean (struct stream_fifo *fifo)
970{
971 struct stream *s;
972 struct stream *next;
973
974 for (s = fifo->head; s; s = next)
975 {
976 next = s->next;
977 stream_free (s);
978 }
979 fifo->head = fifo->tail = NULL;
980 fifo->count = 0;
981}
982
983void
984stream_fifo_free (struct stream_fifo *fifo)
985{
986 stream_fifo_clean (fifo);
987 XFREE (MTYPE_STREAM_FIFO, fifo);
988}