blob: ccd4623ff16f4c542fc44278dcb51393024c048a [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
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700222 if (!ENDP_VALID(s, pos))
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700223 {
224 STREAM_BOUND_WARN (s, "set endp");
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700225 return;
226 }
227
228 /*
229 * Make sure the current read pointer is not beyond the new endp.
230 */
231 if (s->getp > pos)
232 {
233 STREAM_BOUND_WARN(s, "set endp");
234 return;
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700235 }
236
237 s->endp = pos;
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700238 STREAM_VERIFY_SANE(s);
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700239}
240
paul718e3742002-12-13 20:15:29 +0000241/* Forward pointer. */
242void
paul050c0132005-02-14 23:47:47 +0000243stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000244{
paul050c0132005-02-14 23:47:47 +0000245 STREAM_VERIFY_SANE(s);
246
247 if (!GETP_VALID (s, s->getp + size))
248 {
249 STREAM_BOUND_WARN (s, "seek getp");
250 return;
251 }
252
paul718e3742002-12-13 20:15:29 +0000253 s->getp += size;
254}
paul9985f832005-02-09 15:51:56 +0000255
256void
paul050c0132005-02-14 23:47:47 +0000257stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000258{
paul050c0132005-02-14 23:47:47 +0000259 STREAM_VERIFY_SANE(s);
260
261 if (!ENDP_VALID (s, s->endp + size))
262 {
263 STREAM_BOUND_WARN (s, "seek endp");
264 return;
265 }
266
paul9985f832005-02-09 15:51:56 +0000267 s->endp += size;
268}
paul718e3742002-12-13 20:15:29 +0000269
270/* Copy from stream to destination. */
271void
272stream_get (void *dst, struct stream *s, size_t size)
273{
paul050c0132005-02-14 23:47:47 +0000274 STREAM_VERIFY_SANE(s);
275
276 if (STREAM_READABLE(s) < size)
277 {
278 STREAM_BOUND_WARN (s, "get");
279 return;
280 }
281
paul718e3742002-12-13 20:15:29 +0000282 memcpy (dst, s->data + s->getp, size);
283 s->getp += size;
284}
285
286/* Get next character from the stream. */
287u_char
288stream_getc (struct stream *s)
289{
290 u_char c;
paul050c0132005-02-14 23:47:47 +0000291
292 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000293
paul050c0132005-02-14 23:47:47 +0000294 if (STREAM_READABLE(s) < sizeof (u_char))
295 {
296 STREAM_BOUND_WARN (s, "get char");
297 return 0;
298 }
299 c = s->data[s->getp++];
300
paul718e3742002-12-13 20:15:29 +0000301 return c;
302}
303
304/* Get next character from the stream. */
305u_char
paulf2e6c422005-02-12 14:35:49 +0000306stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000307{
308 u_char c;
309
paul050c0132005-02-14 23:47:47 +0000310 STREAM_VERIFY_SANE(s);
311
312 if (!GETP_VALID (s, from + sizeof (u_char)))
313 {
314 STREAM_BOUND_WARN (s, "get char");
315 return 0;
316 }
317
paul718e3742002-12-13 20:15:29 +0000318 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000319
paul718e3742002-12-13 20:15:29 +0000320 return c;
321}
322
323/* Get next word from the stream. */
324u_int16_t
325stream_getw (struct stream *s)
326{
327 u_int16_t w;
328
paul050c0132005-02-14 23:47:47 +0000329 STREAM_VERIFY_SANE (s);
330
331 if (STREAM_READABLE (s) < sizeof (u_int16_t))
332 {
333 STREAM_BOUND_WARN (s, "get ");
334 return 0;
335 }
336
paul718e3742002-12-13 20:15:29 +0000337 w = s->data[s->getp++] << 8;
338 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000339
paul718e3742002-12-13 20:15:29 +0000340 return w;
341}
342
343/* Get next word from the stream. */
344u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000345stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000346{
347 u_int16_t w;
348
paul050c0132005-02-14 23:47:47 +0000349 STREAM_VERIFY_SANE(s);
350
351 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
352 {
353 STREAM_BOUND_WARN (s, "get ");
354 return 0;
355 }
356
paul718e3742002-12-13 20:15:29 +0000357 w = s->data[from++] << 8;
358 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000359
paul718e3742002-12-13 20:15:29 +0000360 return w;
361}
362
363/* Get next long word from the stream. */
364u_int32_t
paul050c0132005-02-14 23:47:47 +0000365stream_getl_from (struct stream *s, size_t from)
366{
367 u_int32_t l;
368
369 STREAM_VERIFY_SANE(s);
370
371 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
372 {
373 STREAM_BOUND_WARN (s, "get long");
374 return 0;
375 }
376
377 l = s->data[from++] << 24;
378 l |= s->data[from++] << 16;
379 l |= s->data[from++] << 8;
380 l |= s->data[from];
381
382 return l;
383}
384
385u_int32_t
paul718e3742002-12-13 20:15:29 +0000386stream_getl (struct stream *s)
387{
388 u_int32_t l;
389
paul050c0132005-02-14 23:47:47 +0000390 STREAM_VERIFY_SANE(s);
391
392 if (STREAM_READABLE (s) < sizeof (u_int32_t))
393 {
394 STREAM_BOUND_WARN (s, "get long");
395 return 0;
396 }
397
paul718e3742002-12-13 20:15:29 +0000398 l = s->data[s->getp++] << 24;
399 l |= s->data[s->getp++] << 16;
400 l |= s->data[s->getp++] << 8;
401 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000402
paul718e3742002-12-13 20:15:29 +0000403 return l;
404}
paul4b201d42006-01-10 14:35:19 +0000405
406/* Get next quad word from the stream. */
407uint64_t
408stream_getq_from (struct stream *s, size_t from)
409{
paul581a02a2006-01-19 20:22:16 +0000410 uint64_t q;
paul4b201d42006-01-10 14:35:19 +0000411
412 STREAM_VERIFY_SANE(s);
413
414 if (!GETP_VALID (s, from + sizeof (uint64_t)))
415 {
416 STREAM_BOUND_WARN (s, "get quad");
417 return 0;
418 }
419
420 q = ((uint64_t) s->data[from++]) << 56;
421 q |= ((uint64_t) s->data[from++]) << 48;
422 q |= ((uint64_t) s->data[from++]) << 40;
423 q |= ((uint64_t) s->data[from++]) << 32;
424 q |= ((uint64_t) s->data[from++]) << 24;
425 q |= ((uint64_t) s->data[from++]) << 16;
426 q |= ((uint64_t) s->data[from++]) << 8;
427 q |= ((uint64_t) s->data[from++]);
428
429 return q;
430}
431
432uint64_t
433stream_getq (struct stream *s)
434{
435 uint64_t q;
436
437 STREAM_VERIFY_SANE(s);
438
439 if (STREAM_READABLE (s) < sizeof (uint64_t))
440 {
441 STREAM_BOUND_WARN (s, "get quad");
442 return 0;
443 }
444
445 q = ((uint64_t) s->data[s->getp++]) << 56;
446 q |= ((uint64_t) s->data[s->getp++]) << 48;
447 q |= ((uint64_t) s->data[s->getp++]) << 40;
448 q |= ((uint64_t) s->data[s->getp++]) << 32;
449 q |= ((uint64_t) s->data[s->getp++]) << 24;
450 q |= ((uint64_t) s->data[s->getp++]) << 16;
451 q |= ((uint64_t) s->data[s->getp++]) << 8;
452 q |= ((uint64_t) s->data[s->getp++]);
453
454 return q;
455}
456
paul718e3742002-12-13 20:15:29 +0000457/* Get next long word from the stream. */
458u_int32_t
459stream_get_ipv4 (struct stream *s)
460{
461 u_int32_t l;
462
paul050c0132005-02-14 23:47:47 +0000463 STREAM_VERIFY_SANE(s);
464
465 if (STREAM_READABLE (s) < sizeof(u_int32_t))
466 {
467 STREAM_BOUND_WARN (s, "get ipv4");
468 return 0;
469 }
470
471 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
472 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000473
474 return l;
475}
476
paul050c0132005-02-14 23:47:47 +0000477/* Copy to source to stream.
478 *
479 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
480 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000481 *
482 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000483 */
paul718e3742002-12-13 20:15:29 +0000484void
Paul Jakma3d52bb82008-06-07 20:42:07 +0000485stream_put (struct stream *s, const void *src, size_t size)
paul718e3742002-12-13 20:15:29 +0000486{
487
paul050c0132005-02-14 23:47:47 +0000488 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000489 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000490
491 STREAM_VERIFY_SANE(s);
492
493 if (STREAM_WRITEABLE (s) < size)
494 {
495 STREAM_BOUND_WARN (s, "put");
496 return;
497 }
498
paul718e3742002-12-13 20:15:29 +0000499 if (src)
paul9985f832005-02-09 15:51:56 +0000500 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000501 else
paul9985f832005-02-09 15:51:56 +0000502 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000503
paul9985f832005-02-09 15:51:56 +0000504 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000505}
506
507/* Put character to the stream. */
508int
509stream_putc (struct stream *s, u_char c)
510{
paul050c0132005-02-14 23:47:47 +0000511 STREAM_VERIFY_SANE(s);
512
513 if (STREAM_WRITEABLE (s) < sizeof(u_char))
514 {
515 STREAM_BOUND_WARN (s, "put");
516 return 0;
517 }
518
519 s->data[s->endp++] = c;
520 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000521}
522
523/* Put word to the stream. */
524int
525stream_putw (struct stream *s, u_int16_t w)
526{
paul050c0132005-02-14 23:47:47 +0000527 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000528
paul050c0132005-02-14 23:47:47 +0000529 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
530 {
531 STREAM_BOUND_WARN (s, "put");
532 return 0;
533 }
534
paul9985f832005-02-09 15:51:56 +0000535 s->data[s->endp++] = (u_char)(w >> 8);
536 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000537
paul718e3742002-12-13 20:15:29 +0000538 return 2;
539}
540
541/* Put long word to the stream. */
542int
543stream_putl (struct stream *s, u_int32_t l)
544{
paul050c0132005-02-14 23:47:47 +0000545 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000546
paul050c0132005-02-14 23:47:47 +0000547 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
548 {
549 STREAM_BOUND_WARN (s, "put");
550 return 0;
551 }
552
paul9985f832005-02-09 15:51:56 +0000553 s->data[s->endp++] = (u_char)(l >> 24);
554 s->data[s->endp++] = (u_char)(l >> 16);
555 s->data[s->endp++] = (u_char)(l >> 8);
556 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000557
paul718e3742002-12-13 20:15:29 +0000558 return 4;
559}
560
paul4b201d42006-01-10 14:35:19 +0000561/* Put quad word to the stream. */
562int
563stream_putq (struct stream *s, uint64_t q)
564{
565 STREAM_VERIFY_SANE (s);
566
567 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
568 {
569 STREAM_BOUND_WARN (s, "put quad");
570 return 0;
571 }
572
573 s->data[s->endp++] = (u_char)(q >> 56);
574 s->data[s->endp++] = (u_char)(q >> 48);
575 s->data[s->endp++] = (u_char)(q >> 40);
576 s->data[s->endp++] = (u_char)(q >> 32);
577 s->data[s->endp++] = (u_char)(q >> 24);
578 s->data[s->endp++] = (u_char)(q >> 16);
579 s->data[s->endp++] = (u_char)(q >> 8);
580 s->data[s->endp++] = (u_char)q;
581
582 return 8;
583}
584
paul718e3742002-12-13 20:15:29 +0000585int
paulf2e6c422005-02-12 14:35:49 +0000586stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000587{
paul050c0132005-02-14 23:47:47 +0000588 STREAM_VERIFY_SANE(s);
589
590 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
591 {
592 STREAM_BOUND_WARN (s, "put");
593 return 0;
594 }
595
paul718e3742002-12-13 20:15:29 +0000596 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000597
paul718e3742002-12-13 20:15:29 +0000598 return 1;
599}
600
601int
paulf2e6c422005-02-12 14:35:49 +0000602stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000603{
paul050c0132005-02-14 23:47:47 +0000604 STREAM_VERIFY_SANE(s);
605
606 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
607 {
608 STREAM_BOUND_WARN (s, "put");
609 return 0;
610 }
611
paul718e3742002-12-13 20:15:29 +0000612 s->data[putp] = (u_char)(w >> 8);
613 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000614
paul718e3742002-12-13 20:15:29 +0000615 return 2;
616}
617
618int
paulf2e6c422005-02-12 14:35:49 +0000619stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000620{
paul050c0132005-02-14 23:47:47 +0000621 STREAM_VERIFY_SANE(s);
622
623 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
624 {
625 STREAM_BOUND_WARN (s, "put");
626 return 0;
627 }
paul718e3742002-12-13 20:15:29 +0000628 s->data[putp] = (u_char)(l >> 24);
629 s->data[putp + 1] = (u_char)(l >> 16);
630 s->data[putp + 2] = (u_char)(l >> 8);
631 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000632
paul718e3742002-12-13 20:15:29 +0000633 return 4;
634}
635
paul4b201d42006-01-10 14:35:19 +0000636int
637stream_putq_at (struct stream *s, size_t putp, uint64_t q)
638{
639 STREAM_VERIFY_SANE(s);
640
641 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
642 {
643 STREAM_BOUND_WARN (s, "put");
644 return 0;
645 }
646 s->data[putp] = (u_char)(q >> 56);
647 s->data[putp + 1] = (u_char)(q >> 48);
648 s->data[putp + 2] = (u_char)(q >> 40);
649 s->data[putp + 3] = (u_char)(q >> 32);
650 s->data[putp + 4] = (u_char)(q >> 24);
651 s->data[putp + 5] = (u_char)(q >> 16);
652 s->data[putp + 6] = (u_char)(q >> 8);
653 s->data[putp + 7] = (u_char)q;
654
655 return 8;
656}
657
paul718e3742002-12-13 20:15:29 +0000658/* Put long word to the stream. */
659int
660stream_put_ipv4 (struct stream *s, u_int32_t l)
661{
paul050c0132005-02-14 23:47:47 +0000662 STREAM_VERIFY_SANE(s);
663
664 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
665 {
666 STREAM_BOUND_WARN (s, "put");
667 return 0;
668 }
669 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
670 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000671
paul050c0132005-02-14 23:47:47 +0000672 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000673}
674
675/* Put long word to the stream. */
676int
677stream_put_in_addr (struct stream *s, struct in_addr *addr)
678{
paul050c0132005-02-14 23:47:47 +0000679 STREAM_VERIFY_SANE(s);
680
681 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
682 {
683 STREAM_BOUND_WARN (s, "put");
684 return 0;
685 }
paul718e3742002-12-13 20:15:29 +0000686
paul050c0132005-02-14 23:47:47 +0000687 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
688 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000689
paul050c0132005-02-14 23:47:47 +0000690 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000691}
692
693/* Put prefix by nlri type format. */
694int
695stream_put_prefix (struct stream *s, struct prefix *p)
696{
paul050c0132005-02-14 23:47:47 +0000697 size_t psize;
698
699 STREAM_VERIFY_SANE(s);
700
paul718e3742002-12-13 20:15:29 +0000701 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000702
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000703 if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
paul050c0132005-02-14 23:47:47 +0000704 {
705 STREAM_BOUND_WARN (s, "put");
706 return 0;
707 }
708
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000709 s->data[s->endp++] = p->prefixlen;
paul9985f832005-02-09 15:51:56 +0000710 memcpy (s->data + s->endp, &p->u.prefix, psize);
711 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000712
paul718e3742002-12-13 20:15:29 +0000713 return psize;
714}
715
716/* Read size from fd. */
717int
718stream_read (struct stream *s, int fd, size_t size)
719{
720 int nbytes;
721
paul050c0132005-02-14 23:47:47 +0000722 STREAM_VERIFY_SANE(s);
723
724 if (STREAM_WRITEABLE (s) < size)
725 {
726 STREAM_BOUND_WARN (s, "put");
727 return 0;
728 }
729
paul9985f832005-02-09 15:51:56 +0000730 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000731
732 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000733 s->endp += nbytes;
734
paul718e3742002-12-13 20:15:29 +0000735 return nbytes;
736}
737
738/* Read size from fd. */
739int
740stream_read_unblock (struct stream *s, int fd, size_t size)
741{
742 int nbytes;
743 int val;
paul050c0132005-02-14 23:47:47 +0000744
745 STREAM_VERIFY_SANE(s);
746
747 if (STREAM_WRITEABLE (s) < size)
748 {
749 STREAM_BOUND_WARN (s, "put");
750 return 0;
751 }
752
paul718e3742002-12-13 20:15:29 +0000753 val = fcntl (fd, F_GETFL, 0);
754 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000755 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000756 fcntl (fd, F_SETFL, val);
757
758 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000759 s->endp += nbytes;
760
paul718e3742002-12-13 20:15:29 +0000761 return nbytes;
762}
763
ajs262feb12005-02-16 20:35:47 +0000764ssize_t
765stream_read_try(struct stream *s, int fd, size_t size)
766{
767 ssize_t nbytes;
768
769 STREAM_VERIFY_SANE(s);
770
771 if (STREAM_WRITEABLE(s) < size)
772 {
773 STREAM_BOUND_WARN (s, "put");
774 /* Fatal (not transient) error, since retrying will not help
775 (stream is too small to contain the desired data). */
776 return -1;
777 }
778
779 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
780 {
781 s->endp += nbytes;
782 return nbytes;
783 }
784 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000785 if (ERRNO_IO_RETRY(errno))
786 return -2;
787 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
788 return -1;
ajs262feb12005-02-16 20:35:47 +0000789}
790
paul0dab9302005-05-03 09:07:56 +0000791/* Read up to size bytes into the stream from the fd, using recvmsgfrom
792 * whose arguments match the remaining arguments to this function
793 */
794ssize_t
795stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
796 struct sockaddr *from, socklen_t *fromlen)
797{
798 ssize_t nbytes;
799
800 STREAM_VERIFY_SANE(s);
801
802 if (STREAM_WRITEABLE(s) < size)
803 {
804 STREAM_BOUND_WARN (s, "put");
805 /* Fatal (not transient) error, since retrying will not help
806 (stream is too small to contain the desired data). */
807 return -1;
808 }
809
810 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
811 flags, from, fromlen)) >= 0)
812 {
813 s->endp += nbytes;
814 return nbytes;
815 }
816 /* Error: was it transient (return -2) or fatal (return -1)? */
817 if (ERRNO_IO_RETRY(errno))
818 return -2;
819 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
820 return -1;
821}
822
paul050c0132005-02-14 23:47:47 +0000823/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
824 * from endp.
825 * First iovec will be used to receive the data.
826 * Stream need not be empty.
827 */
paul0dab9302005-05-03 09:07:56 +0000828ssize_t
paul050c0132005-02-14 23:47:47 +0000829stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
830 size_t size)
831{
832 int nbytes;
833 struct iovec *iov;
834
835 STREAM_VERIFY_SANE(s);
836 assert (msgh->msg_iovlen > 0);
837
838 if (STREAM_WRITEABLE (s) < size)
839 {
840 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000841 /* This is a logic error in the calling code: the stream is too small
842 to hold the desired data! */
843 return -1;
paul050c0132005-02-14 23:47:47 +0000844 }
845
846 iov = &(msgh->msg_iov[0]);
847 iov->iov_base = (s->data + s->endp);
848 iov->iov_len = size;
849
850 nbytes = recvmsg (fd, msgh, flags);
851
852 if (nbytes > 0)
853 s->endp += nbytes;
854
855 return nbytes;
856}
857
paul718e3742002-12-13 20:15:29 +0000858/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000859size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000860stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000861{
862
863 CHECK_SIZE(s, size);
864
paul050c0132005-02-14 23:47:47 +0000865 STREAM_VERIFY_SANE(s);
866
867 if (STREAM_WRITEABLE (s) < size)
868 {
869 STREAM_BOUND_WARN (s, "put");
870 return 0;
871 }
872
paul9985f832005-02-09 15:51:56 +0000873 memcpy (s->data + s->endp, ptr, size);
874 s->endp += size;
875
paul718e3742002-12-13 20:15:29 +0000876 return size;
877}
878
paul050c0132005-02-14 23:47:47 +0000879/* Return current read pointer.
880 * DEPRECATED!
881 * Use stream_get_pnt_to if you must, but decoding streams properly
882 * is preferred
883 */
paul718e3742002-12-13 20:15:29 +0000884u_char *
885stream_pnt (struct stream *s)
886{
paul050c0132005-02-14 23:47:47 +0000887 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000888 return s->data + s->getp;
889}
890
891/* Check does this stream empty? */
892int
893stream_empty (struct stream *s)
894{
paul050c0132005-02-14 23:47:47 +0000895 STREAM_VERIFY_SANE(s);
896
897 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000898}
899
900/* Reset stream. */
901void
902stream_reset (struct stream *s)
903{
paul050c0132005-02-14 23:47:47 +0000904 STREAM_VERIFY_SANE (s);
905
906 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000907}
908
909/* Write stream contens to the file discriptor. */
910int
911stream_flush (struct stream *s, int fd)
912{
913 int nbytes;
paul050c0132005-02-14 23:47:47 +0000914
915 STREAM_VERIFY_SANE(s);
916
paul718e3742002-12-13 20:15:29 +0000917 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000918
paul718e3742002-12-13 20:15:29 +0000919 return nbytes;
920}
921
922/* Stream first in first out queue. */
923
924struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000925stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000926{
927 struct stream_fifo *new;
928
929 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
930 return new;
931}
932
933/* Add new stream to fifo. */
934void
935stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
936{
937 if (fifo->tail)
938 fifo->tail->next = s;
939 else
940 fifo->head = s;
941
942 fifo->tail = s;
943
944 fifo->count++;
945}
946
947/* Delete first stream from fifo. */
948struct stream *
949stream_fifo_pop (struct stream_fifo *fifo)
950{
951 struct stream *s;
952
953 s = fifo->head;
954
955 if (s)
956 {
957 fifo->head = s->next;
958
959 if (fifo->head == NULL)
960 fifo->tail = NULL;
paul718e3742002-12-13 20:15:29 +0000961
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700962 fifo->count--;
963 }
paul718e3742002-12-13 20:15:29 +0000964
965 return s;
966}
967
968/* Return first fifo entry. */
969struct stream *
970stream_fifo_head (struct stream_fifo *fifo)
971{
972 return fifo->head;
973}
974
975void
976stream_fifo_clean (struct stream_fifo *fifo)
977{
978 struct stream *s;
979 struct stream *next;
980
981 for (s = fifo->head; s; s = next)
982 {
983 next = s->next;
984 stream_free (s);
985 }
986 fifo->head = fifo->tail = NULL;
987 fifo->count = 0;
988}
989
990void
991stream_fifo_free (struct stream_fifo *fifo)
992{
993 stream_fifo_clean (fifo);
994 XFREE (MTYPE_STREAM_FIFO, fifo);
995}