blob: 983330ffb4a3b19ac0a6e7a668aebe76b953f197 [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) \
55 zlog_warn ("&(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \
56 (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
paul718e3742002-12-13 20:15:29 +0000217/* Forward pointer. */
218void
paul050c0132005-02-14 23:47:47 +0000219stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000220{
paul050c0132005-02-14 23:47:47 +0000221 STREAM_VERIFY_SANE(s);
222
223 if (!GETP_VALID (s, s->getp + size))
224 {
225 STREAM_BOUND_WARN (s, "seek getp");
226 return;
227 }
228
paul718e3742002-12-13 20:15:29 +0000229 s->getp += size;
230}
paul9985f832005-02-09 15:51:56 +0000231
232void
paul050c0132005-02-14 23:47:47 +0000233stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000234{
paul050c0132005-02-14 23:47:47 +0000235 STREAM_VERIFY_SANE(s);
236
237 if (!ENDP_VALID (s, s->endp + size))
238 {
239 STREAM_BOUND_WARN (s, "seek endp");
240 return;
241 }
242
paul9985f832005-02-09 15:51:56 +0000243 s->endp += size;
244}
paul718e3742002-12-13 20:15:29 +0000245
246/* Copy from stream to destination. */
247void
248stream_get (void *dst, struct stream *s, size_t size)
249{
paul050c0132005-02-14 23:47:47 +0000250 STREAM_VERIFY_SANE(s);
251
252 if (STREAM_READABLE(s) < size)
253 {
254 STREAM_BOUND_WARN (s, "get");
255 return;
256 }
257
paul718e3742002-12-13 20:15:29 +0000258 memcpy (dst, s->data + s->getp, size);
259 s->getp += size;
260}
261
262/* Get next character from the stream. */
263u_char
264stream_getc (struct stream *s)
265{
266 u_char c;
paul050c0132005-02-14 23:47:47 +0000267
268 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000269
paul050c0132005-02-14 23:47:47 +0000270 if (STREAM_READABLE(s) < sizeof (u_char))
271 {
272 STREAM_BOUND_WARN (s, "get char");
273 return 0;
274 }
275 c = s->data[s->getp++];
276
paul718e3742002-12-13 20:15:29 +0000277 return c;
278}
279
280/* Get next character from the stream. */
281u_char
paulf2e6c422005-02-12 14:35:49 +0000282stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000283{
284 u_char c;
285
paul050c0132005-02-14 23:47:47 +0000286 STREAM_VERIFY_SANE(s);
287
288 if (!GETP_VALID (s, from + sizeof (u_char)))
289 {
290 STREAM_BOUND_WARN (s, "get char");
291 return 0;
292 }
293
paul718e3742002-12-13 20:15:29 +0000294 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000295
paul718e3742002-12-13 20:15:29 +0000296 return c;
297}
298
299/* Get next word from the stream. */
300u_int16_t
301stream_getw (struct stream *s)
302{
303 u_int16_t w;
304
paul050c0132005-02-14 23:47:47 +0000305 STREAM_VERIFY_SANE (s);
306
307 if (STREAM_READABLE (s) < sizeof (u_int16_t))
308 {
309 STREAM_BOUND_WARN (s, "get ");
310 return 0;
311 }
312
paul718e3742002-12-13 20:15:29 +0000313 w = s->data[s->getp++] << 8;
314 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000315
paul718e3742002-12-13 20:15:29 +0000316 return w;
317}
318
319/* Get next word from the stream. */
320u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000321stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000322{
323 u_int16_t w;
324
paul050c0132005-02-14 23:47:47 +0000325 STREAM_VERIFY_SANE(s);
326
327 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
328 {
329 STREAM_BOUND_WARN (s, "get ");
330 return 0;
331 }
332
paul718e3742002-12-13 20:15:29 +0000333 w = s->data[from++] << 8;
334 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000335
paul718e3742002-12-13 20:15:29 +0000336 return w;
337}
338
339/* Get next long word from the stream. */
340u_int32_t
paul050c0132005-02-14 23:47:47 +0000341stream_getl_from (struct stream *s, size_t from)
342{
343 u_int32_t l;
344
345 STREAM_VERIFY_SANE(s);
346
347 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
348 {
349 STREAM_BOUND_WARN (s, "get long");
350 return 0;
351 }
352
353 l = s->data[from++] << 24;
354 l |= s->data[from++] << 16;
355 l |= s->data[from++] << 8;
356 l |= s->data[from];
357
358 return l;
359}
360
361u_int32_t
paul718e3742002-12-13 20:15:29 +0000362stream_getl (struct stream *s)
363{
364 u_int32_t l;
365
paul050c0132005-02-14 23:47:47 +0000366 STREAM_VERIFY_SANE(s);
367
368 if (STREAM_READABLE (s) < sizeof (u_int32_t))
369 {
370 STREAM_BOUND_WARN (s, "get long");
371 return 0;
372 }
373
paul718e3742002-12-13 20:15:29 +0000374 l = s->data[s->getp++] << 24;
375 l |= s->data[s->getp++] << 16;
376 l |= s->data[s->getp++] << 8;
377 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000378
paul718e3742002-12-13 20:15:29 +0000379 return l;
380}
paul4b201d42006-01-10 14:35:19 +0000381
382/* Get next quad word from the stream. */
383uint64_t
384stream_getq_from (struct stream *s, size_t from)
385{
paul581a02a2006-01-19 20:22:16 +0000386 uint64_t q;
paul4b201d42006-01-10 14:35:19 +0000387
388 STREAM_VERIFY_SANE(s);
389
390 if (!GETP_VALID (s, from + sizeof (uint64_t)))
391 {
392 STREAM_BOUND_WARN (s, "get quad");
393 return 0;
394 }
395
396 q = ((uint64_t) s->data[from++]) << 56;
397 q |= ((uint64_t) s->data[from++]) << 48;
398 q |= ((uint64_t) s->data[from++]) << 40;
399 q |= ((uint64_t) s->data[from++]) << 32;
400 q |= ((uint64_t) s->data[from++]) << 24;
401 q |= ((uint64_t) s->data[from++]) << 16;
402 q |= ((uint64_t) s->data[from++]) << 8;
403 q |= ((uint64_t) s->data[from++]);
404
405 return q;
406}
407
408uint64_t
409stream_getq (struct stream *s)
410{
411 uint64_t q;
412
413 STREAM_VERIFY_SANE(s);
414
415 if (STREAM_READABLE (s) < sizeof (uint64_t))
416 {
417 STREAM_BOUND_WARN (s, "get quad");
418 return 0;
419 }
420
421 q = ((uint64_t) s->data[s->getp++]) << 56;
422 q |= ((uint64_t) s->data[s->getp++]) << 48;
423 q |= ((uint64_t) s->data[s->getp++]) << 40;
424 q |= ((uint64_t) s->data[s->getp++]) << 32;
425 q |= ((uint64_t) s->data[s->getp++]) << 24;
426 q |= ((uint64_t) s->data[s->getp++]) << 16;
427 q |= ((uint64_t) s->data[s->getp++]) << 8;
428 q |= ((uint64_t) s->data[s->getp++]);
429
430 return q;
431}
432
paul718e3742002-12-13 20:15:29 +0000433/* Get next long word from the stream. */
434u_int32_t
435stream_get_ipv4 (struct stream *s)
436{
437 u_int32_t l;
438
paul050c0132005-02-14 23:47:47 +0000439 STREAM_VERIFY_SANE(s);
440
441 if (STREAM_READABLE (s) < sizeof(u_int32_t))
442 {
443 STREAM_BOUND_WARN (s, "get ipv4");
444 return 0;
445 }
446
447 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
448 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000449
450 return l;
451}
452
paul050c0132005-02-14 23:47:47 +0000453/* Copy to source to stream.
454 *
455 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
456 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000457 *
458 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000459 */
paul718e3742002-12-13 20:15:29 +0000460void
Paul Jakma3d52bb82008-06-07 20:42:07 +0000461stream_put (struct stream *s, const void *src, size_t size)
paul718e3742002-12-13 20:15:29 +0000462{
463
paul050c0132005-02-14 23:47:47 +0000464 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000465 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000466
467 STREAM_VERIFY_SANE(s);
468
469 if (STREAM_WRITEABLE (s) < size)
470 {
471 STREAM_BOUND_WARN (s, "put");
472 return;
473 }
474
paul718e3742002-12-13 20:15:29 +0000475 if (src)
paul9985f832005-02-09 15:51:56 +0000476 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000477 else
paul9985f832005-02-09 15:51:56 +0000478 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000479
paul9985f832005-02-09 15:51:56 +0000480 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000481}
482
483/* Put character to the stream. */
484int
485stream_putc (struct stream *s, u_char c)
486{
paul050c0132005-02-14 23:47:47 +0000487 STREAM_VERIFY_SANE(s);
488
489 if (STREAM_WRITEABLE (s) < sizeof(u_char))
490 {
491 STREAM_BOUND_WARN (s, "put");
492 return 0;
493 }
494
495 s->data[s->endp++] = c;
496 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000497}
498
499/* Put word to the stream. */
500int
501stream_putw (struct stream *s, u_int16_t w)
502{
paul050c0132005-02-14 23:47:47 +0000503 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000504
paul050c0132005-02-14 23:47:47 +0000505 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
506 {
507 STREAM_BOUND_WARN (s, "put");
508 return 0;
509 }
510
paul9985f832005-02-09 15:51:56 +0000511 s->data[s->endp++] = (u_char)(w >> 8);
512 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000513
paul718e3742002-12-13 20:15:29 +0000514 return 2;
515}
516
517/* Put long word to the stream. */
518int
519stream_putl (struct stream *s, u_int32_t l)
520{
paul050c0132005-02-14 23:47:47 +0000521 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000522
paul050c0132005-02-14 23:47:47 +0000523 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
524 {
525 STREAM_BOUND_WARN (s, "put");
526 return 0;
527 }
528
paul9985f832005-02-09 15:51:56 +0000529 s->data[s->endp++] = (u_char)(l >> 24);
530 s->data[s->endp++] = (u_char)(l >> 16);
531 s->data[s->endp++] = (u_char)(l >> 8);
532 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000533
paul718e3742002-12-13 20:15:29 +0000534 return 4;
535}
536
paul4b201d42006-01-10 14:35:19 +0000537/* Put quad word to the stream. */
538int
539stream_putq (struct stream *s, uint64_t q)
540{
541 STREAM_VERIFY_SANE (s);
542
543 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
544 {
545 STREAM_BOUND_WARN (s, "put quad");
546 return 0;
547 }
548
549 s->data[s->endp++] = (u_char)(q >> 56);
550 s->data[s->endp++] = (u_char)(q >> 48);
551 s->data[s->endp++] = (u_char)(q >> 40);
552 s->data[s->endp++] = (u_char)(q >> 32);
553 s->data[s->endp++] = (u_char)(q >> 24);
554 s->data[s->endp++] = (u_char)(q >> 16);
555 s->data[s->endp++] = (u_char)(q >> 8);
556 s->data[s->endp++] = (u_char)q;
557
558 return 8;
559}
560
paul718e3742002-12-13 20:15:29 +0000561int
paulf2e6c422005-02-12 14:35:49 +0000562stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000563{
paul050c0132005-02-14 23:47:47 +0000564 STREAM_VERIFY_SANE(s);
565
566 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
567 {
568 STREAM_BOUND_WARN (s, "put");
569 return 0;
570 }
571
paul718e3742002-12-13 20:15:29 +0000572 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000573
paul718e3742002-12-13 20:15:29 +0000574 return 1;
575}
576
577int
paulf2e6c422005-02-12 14:35:49 +0000578stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000579{
paul050c0132005-02-14 23:47:47 +0000580 STREAM_VERIFY_SANE(s);
581
582 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
583 {
584 STREAM_BOUND_WARN (s, "put");
585 return 0;
586 }
587
paul718e3742002-12-13 20:15:29 +0000588 s->data[putp] = (u_char)(w >> 8);
589 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000590
paul718e3742002-12-13 20:15:29 +0000591 return 2;
592}
593
594int
paulf2e6c422005-02-12 14:35:49 +0000595stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000596{
paul050c0132005-02-14 23:47:47 +0000597 STREAM_VERIFY_SANE(s);
598
599 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
600 {
601 STREAM_BOUND_WARN (s, "put");
602 return 0;
603 }
paul718e3742002-12-13 20:15:29 +0000604 s->data[putp] = (u_char)(l >> 24);
605 s->data[putp + 1] = (u_char)(l >> 16);
606 s->data[putp + 2] = (u_char)(l >> 8);
607 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000608
paul718e3742002-12-13 20:15:29 +0000609 return 4;
610}
611
paul4b201d42006-01-10 14:35:19 +0000612int
613stream_putq_at (struct stream *s, size_t putp, uint64_t q)
614{
615 STREAM_VERIFY_SANE(s);
616
617 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
618 {
619 STREAM_BOUND_WARN (s, "put");
620 return 0;
621 }
622 s->data[putp] = (u_char)(q >> 56);
623 s->data[putp + 1] = (u_char)(q >> 48);
624 s->data[putp + 2] = (u_char)(q >> 40);
625 s->data[putp + 3] = (u_char)(q >> 32);
626 s->data[putp + 4] = (u_char)(q >> 24);
627 s->data[putp + 5] = (u_char)(q >> 16);
628 s->data[putp + 6] = (u_char)(q >> 8);
629 s->data[putp + 7] = (u_char)q;
630
631 return 8;
632}
633
paul718e3742002-12-13 20:15:29 +0000634/* Put long word to the stream. */
635int
636stream_put_ipv4 (struct stream *s, u_int32_t l)
637{
paul050c0132005-02-14 23:47:47 +0000638 STREAM_VERIFY_SANE(s);
639
640 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
641 {
642 STREAM_BOUND_WARN (s, "put");
643 return 0;
644 }
645 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
646 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000647
paul050c0132005-02-14 23:47:47 +0000648 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000649}
650
651/* Put long word to the stream. */
652int
653stream_put_in_addr (struct stream *s, struct in_addr *addr)
654{
paul050c0132005-02-14 23:47:47 +0000655 STREAM_VERIFY_SANE(s);
656
657 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
658 {
659 STREAM_BOUND_WARN (s, "put");
660 return 0;
661 }
paul718e3742002-12-13 20:15:29 +0000662
paul050c0132005-02-14 23:47:47 +0000663 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
664 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000665
paul050c0132005-02-14 23:47:47 +0000666 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000667}
668
669/* Put prefix by nlri type format. */
670int
671stream_put_prefix (struct stream *s, struct prefix *p)
672{
paul050c0132005-02-14 23:47:47 +0000673 size_t psize;
674
675 STREAM_VERIFY_SANE(s);
676
paul718e3742002-12-13 20:15:29 +0000677 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000678
679 if (STREAM_WRITEABLE (s) < psize)
680 {
681 STREAM_BOUND_WARN (s, "put");
682 return 0;
683 }
684
paul718e3742002-12-13 20:15:29 +0000685 stream_putc (s, p->prefixlen);
paul9985f832005-02-09 15:51:56 +0000686 memcpy (s->data + s->endp, &p->u.prefix, psize);
687 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000688
paul718e3742002-12-13 20:15:29 +0000689 return psize;
690}
691
692/* Read size from fd. */
693int
694stream_read (struct stream *s, int fd, size_t size)
695{
696 int nbytes;
697
paul050c0132005-02-14 23:47:47 +0000698 STREAM_VERIFY_SANE(s);
699
700 if (STREAM_WRITEABLE (s) < size)
701 {
702 STREAM_BOUND_WARN (s, "put");
703 return 0;
704 }
705
paul9985f832005-02-09 15:51:56 +0000706 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000707
708 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000709 s->endp += nbytes;
710
paul718e3742002-12-13 20:15:29 +0000711 return nbytes;
712}
713
714/* Read size from fd. */
715int
716stream_read_unblock (struct stream *s, int fd, size_t size)
717{
718 int nbytes;
719 int val;
paul050c0132005-02-14 23:47:47 +0000720
721 STREAM_VERIFY_SANE(s);
722
723 if (STREAM_WRITEABLE (s) < size)
724 {
725 STREAM_BOUND_WARN (s, "put");
726 return 0;
727 }
728
paul718e3742002-12-13 20:15:29 +0000729 val = fcntl (fd, F_GETFL, 0);
730 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000731 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000732 fcntl (fd, F_SETFL, val);
733
734 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000735 s->endp += nbytes;
736
paul718e3742002-12-13 20:15:29 +0000737 return nbytes;
738}
739
ajs262feb12005-02-16 20:35:47 +0000740ssize_t
741stream_read_try(struct stream *s, int fd, size_t size)
742{
743 ssize_t nbytes;
744
745 STREAM_VERIFY_SANE(s);
746
747 if (STREAM_WRITEABLE(s) < size)
748 {
749 STREAM_BOUND_WARN (s, "put");
750 /* Fatal (not transient) error, since retrying will not help
751 (stream is too small to contain the desired data). */
752 return -1;
753 }
754
755 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
756 {
757 s->endp += nbytes;
758 return nbytes;
759 }
760 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000761 if (ERRNO_IO_RETRY(errno))
762 return -2;
763 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
764 return -1;
ajs262feb12005-02-16 20:35:47 +0000765}
766
paul0dab9302005-05-03 09:07:56 +0000767/* Read up to size bytes into the stream from the fd, using recvmsgfrom
768 * whose arguments match the remaining arguments to this function
769 */
770ssize_t
771stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
772 struct sockaddr *from, socklen_t *fromlen)
773{
774 ssize_t nbytes;
775
776 STREAM_VERIFY_SANE(s);
777
778 if (STREAM_WRITEABLE(s) < size)
779 {
780 STREAM_BOUND_WARN (s, "put");
781 /* Fatal (not transient) error, since retrying will not help
782 (stream is too small to contain the desired data). */
783 return -1;
784 }
785
786 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
787 flags, from, fromlen)) >= 0)
788 {
789 s->endp += nbytes;
790 return nbytes;
791 }
792 /* Error: was it transient (return -2) or fatal (return -1)? */
793 if (ERRNO_IO_RETRY(errno))
794 return -2;
795 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
796 return -1;
797}
798
paul050c0132005-02-14 23:47:47 +0000799/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
800 * from endp.
801 * First iovec will be used to receive the data.
802 * Stream need not be empty.
803 */
paul0dab9302005-05-03 09:07:56 +0000804ssize_t
paul050c0132005-02-14 23:47:47 +0000805stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
806 size_t size)
807{
808 int nbytes;
809 struct iovec *iov;
810
811 STREAM_VERIFY_SANE(s);
812 assert (msgh->msg_iovlen > 0);
813
814 if (STREAM_WRITEABLE (s) < size)
815 {
816 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000817 /* This is a logic error in the calling code: the stream is too small
818 to hold the desired data! */
819 return -1;
paul050c0132005-02-14 23:47:47 +0000820 }
821
822 iov = &(msgh->msg_iov[0]);
823 iov->iov_base = (s->data + s->endp);
824 iov->iov_len = size;
825
826 nbytes = recvmsg (fd, msgh, flags);
827
828 if (nbytes > 0)
829 s->endp += nbytes;
830
831 return nbytes;
832}
833
paul718e3742002-12-13 20:15:29 +0000834/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000835size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000836stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000837{
838
839 CHECK_SIZE(s, size);
840
paul050c0132005-02-14 23:47:47 +0000841 STREAM_VERIFY_SANE(s);
842
843 if (STREAM_WRITEABLE (s) < size)
844 {
845 STREAM_BOUND_WARN (s, "put");
846 return 0;
847 }
848
paul9985f832005-02-09 15:51:56 +0000849 memcpy (s->data + s->endp, ptr, size);
850 s->endp += size;
851
paul718e3742002-12-13 20:15:29 +0000852 return size;
853}
854
paul050c0132005-02-14 23:47:47 +0000855/* Return current read pointer.
856 * DEPRECATED!
857 * Use stream_get_pnt_to if you must, but decoding streams properly
858 * is preferred
859 */
paul718e3742002-12-13 20:15:29 +0000860u_char *
861stream_pnt (struct stream *s)
862{
paul050c0132005-02-14 23:47:47 +0000863 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000864 return s->data + s->getp;
865}
866
867/* Check does this stream empty? */
868int
869stream_empty (struct stream *s)
870{
paul050c0132005-02-14 23:47:47 +0000871 STREAM_VERIFY_SANE(s);
872
873 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000874}
875
876/* Reset stream. */
877void
878stream_reset (struct stream *s)
879{
paul050c0132005-02-14 23:47:47 +0000880 STREAM_VERIFY_SANE (s);
881
882 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000883}
884
885/* Write stream contens to the file discriptor. */
886int
887stream_flush (struct stream *s, int fd)
888{
889 int nbytes;
paul050c0132005-02-14 23:47:47 +0000890
891 STREAM_VERIFY_SANE(s);
892
paul718e3742002-12-13 20:15:29 +0000893 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000894
paul718e3742002-12-13 20:15:29 +0000895 return nbytes;
896}
897
898/* Stream first in first out queue. */
899
900struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000901stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000902{
903 struct stream_fifo *new;
904
905 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
906 return new;
907}
908
909/* Add new stream to fifo. */
910void
911stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
912{
913 if (fifo->tail)
914 fifo->tail->next = s;
915 else
916 fifo->head = s;
917
918 fifo->tail = s;
919
920 fifo->count++;
921}
922
923/* Delete first stream from fifo. */
924struct stream *
925stream_fifo_pop (struct stream_fifo *fifo)
926{
927 struct stream *s;
928
929 s = fifo->head;
930
931 if (s)
932 {
933 fifo->head = s->next;
934
935 if (fifo->head == NULL)
936 fifo->tail = NULL;
937 }
938
939 fifo->count--;
940
941 return s;
942}
943
944/* Return first fifo entry. */
945struct stream *
946stream_fifo_head (struct stream_fifo *fifo)
947{
948 return fifo->head;
949}
950
951void
952stream_fifo_clean (struct stream_fifo *fifo)
953{
954 struct stream *s;
955 struct stream *next;
956
957 for (s = fifo->head; s; s = next)
958 {
959 next = s->next;
960 stream_free (s);
961 }
962 fifo->head = fifo->tail = NULL;
963 fifo->count = 0;
964}
965
966void
967stream_fifo_free (struct stream_fifo *fifo)
968{
969 stream_fifo_clean (fifo);
970 XFREE (MTYPE_STREAM_FIFO, fifo);
971}