blob: 0fc3c3b1185d50513e819fb546cdbec213a421cb [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
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
757/* Read size from fd. */
758int
759stream_read_unblock (struct stream *s, int fd, size_t size)
760{
761 int nbytes;
762 int val;
paul050c0132005-02-14 23:47:47 +0000763
764 STREAM_VERIFY_SANE(s);
765
766 if (STREAM_WRITEABLE (s) < size)
767 {
768 STREAM_BOUND_WARN (s, "put");
769 return 0;
770 }
771
paul718e3742002-12-13 20:15:29 +0000772 val = fcntl (fd, F_GETFL, 0);
773 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000774 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000775 fcntl (fd, F_SETFL, val);
776
777 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000778 s->endp += nbytes;
779
paul718e3742002-12-13 20:15:29 +0000780 return nbytes;
781}
782
ajs262feb12005-02-16 20:35:47 +0000783ssize_t
784stream_read_try(struct stream *s, int fd, size_t size)
785{
786 ssize_t nbytes;
787
788 STREAM_VERIFY_SANE(s);
789
790 if (STREAM_WRITEABLE(s) < size)
791 {
792 STREAM_BOUND_WARN (s, "put");
793 /* Fatal (not transient) error, since retrying will not help
794 (stream is too small to contain the desired data). */
795 return -1;
796 }
797
798 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
799 {
800 s->endp += nbytes;
801 return nbytes;
802 }
803 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000804 if (ERRNO_IO_RETRY(errno))
805 return -2;
806 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
807 return -1;
ajs262feb12005-02-16 20:35:47 +0000808}
809
paul0dab9302005-05-03 09:07:56 +0000810/* Read up to size bytes into the stream from the fd, using recvmsgfrom
811 * whose arguments match the remaining arguments to this function
812 */
813ssize_t
814stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
815 struct sockaddr *from, socklen_t *fromlen)
816{
817 ssize_t nbytes;
818
819 STREAM_VERIFY_SANE(s);
820
821 if (STREAM_WRITEABLE(s) < size)
822 {
823 STREAM_BOUND_WARN (s, "put");
824 /* Fatal (not transient) error, since retrying will not help
825 (stream is too small to contain the desired data). */
826 return -1;
827 }
828
829 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
830 flags, from, fromlen)) >= 0)
831 {
832 s->endp += nbytes;
833 return nbytes;
834 }
835 /* Error: was it transient (return -2) or fatal (return -1)? */
836 if (ERRNO_IO_RETRY(errno))
837 return -2;
838 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
839 return -1;
840}
841
paul050c0132005-02-14 23:47:47 +0000842/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
843 * from endp.
844 * First iovec will be used to receive the data.
845 * Stream need not be empty.
846 */
paul0dab9302005-05-03 09:07:56 +0000847ssize_t
paul050c0132005-02-14 23:47:47 +0000848stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
849 size_t size)
850{
851 int nbytes;
852 struct iovec *iov;
853
854 STREAM_VERIFY_SANE(s);
855 assert (msgh->msg_iovlen > 0);
856
857 if (STREAM_WRITEABLE (s) < size)
858 {
859 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000860 /* This is a logic error in the calling code: the stream is too small
861 to hold the desired data! */
862 return -1;
paul050c0132005-02-14 23:47:47 +0000863 }
864
865 iov = &(msgh->msg_iov[0]);
866 iov->iov_base = (s->data + s->endp);
867 iov->iov_len = size;
868
869 nbytes = recvmsg (fd, msgh, flags);
870
871 if (nbytes > 0)
872 s->endp += nbytes;
873
874 return nbytes;
875}
876
paul718e3742002-12-13 20:15:29 +0000877/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000878size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000879stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000880{
881
882 CHECK_SIZE(s, size);
883
paul050c0132005-02-14 23:47:47 +0000884 STREAM_VERIFY_SANE(s);
885
886 if (STREAM_WRITEABLE (s) < size)
887 {
888 STREAM_BOUND_WARN (s, "put");
889 return 0;
890 }
891
paul9985f832005-02-09 15:51:56 +0000892 memcpy (s->data + s->endp, ptr, size);
893 s->endp += size;
894
paul718e3742002-12-13 20:15:29 +0000895 return size;
896}
897
paul050c0132005-02-14 23:47:47 +0000898/* Return current read pointer.
899 * DEPRECATED!
900 * Use stream_get_pnt_to if you must, but decoding streams properly
901 * is preferred
902 */
paul718e3742002-12-13 20:15:29 +0000903u_char *
904stream_pnt (struct stream *s)
905{
paul050c0132005-02-14 23:47:47 +0000906 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000907 return s->data + s->getp;
908}
909
910/* Check does this stream empty? */
911int
912stream_empty (struct stream *s)
913{
paul050c0132005-02-14 23:47:47 +0000914 STREAM_VERIFY_SANE(s);
915
916 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000917}
918
919/* Reset stream. */
920void
921stream_reset (struct stream *s)
922{
paul050c0132005-02-14 23:47:47 +0000923 STREAM_VERIFY_SANE (s);
924
925 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000926}
927
928/* Write stream contens to the file discriptor. */
929int
930stream_flush (struct stream *s, int fd)
931{
932 int nbytes;
paul050c0132005-02-14 23:47:47 +0000933
934 STREAM_VERIFY_SANE(s);
935
paul718e3742002-12-13 20:15:29 +0000936 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000937
paul718e3742002-12-13 20:15:29 +0000938 return nbytes;
939}
David Lamparter6b0655a2014-06-04 06:53:35 +0200940
paul718e3742002-12-13 20:15:29 +0000941/* Stream first in first out queue. */
942
943struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000944stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000945{
946 struct stream_fifo *new;
947
948 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
949 return new;
950}
951
952/* Add new stream to fifo. */
953void
954stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
955{
956 if (fifo->tail)
957 fifo->tail->next = s;
958 else
959 fifo->head = s;
960
961 fifo->tail = s;
962
963 fifo->count++;
964}
965
966/* Delete first stream from fifo. */
967struct stream *
968stream_fifo_pop (struct stream_fifo *fifo)
969{
970 struct stream *s;
971
972 s = fifo->head;
973
974 if (s)
975 {
976 fifo->head = s->next;
977
978 if (fifo->head == NULL)
979 fifo->tail = NULL;
paul718e3742002-12-13 20:15:29 +0000980
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700981 fifo->count--;
982 }
paul718e3742002-12-13 20:15:29 +0000983
984 return s;
985}
986
987/* Return first fifo entry. */
988struct stream *
989stream_fifo_head (struct stream_fifo *fifo)
990{
991 return fifo->head;
992}
993
994void
995stream_fifo_clean (struct stream_fifo *fifo)
996{
997 struct stream *s;
998 struct stream *next;
999
1000 for (s = fifo->head; s; s = next)
1001 {
1002 next = s->next;
1003 stream_free (s);
1004 }
1005 fifo->head = fifo->tail = NULL;
1006 fifo->count = 0;
1007}
1008
1009void
1010stream_fifo_free (struct stream_fifo *fifo)
1011{
1012 stream_fifo_clean (fifo);
1013 XFREE (MTYPE_STREAM_FIFO, fifo);
1014}