blob: 43575e1c918e9003921999ff95932cf7f22804a9 [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
23#include <zebra.h>
David Lamparter821df2c2015-09-15 01:53:09 -070024#include <stddef.h>
Paul Jakmad41e7b92015-05-19 15:38:43 +010025/* primarily for __STDC_IEC_559__ with clang */
26#include <features.h>
paul718e3742002-12-13 20:15:29 +000027
28#include "stream.h"
29#include "memory.h"
30#include "network.h"
31#include "prefix.h"
paul050c0132005-02-14 23:47:47 +000032#include "log.h"
paul718e3742002-12-13 20:15:29 +000033
paul050c0132005-02-14 23:47:47 +000034/* Tests whether a position is valid */
35#define GETP_VALID(S,G) \
36 ((G) <= (S)->endp)
37#define PUT_AT_VALID(S,G) GETP_VALID(S,G)
38#define ENDP_VALID(S,E) \
39 ((E) <= (S)->size)
paul718e3742002-12-13 20:15:29 +000040
paul050c0132005-02-14 23:47:47 +000041/* asserting sanity checks. Following must be true before
42 * stream functions are called:
43 *
44 * Following must always be true of stream elements
45 * before and after calls to stream functions:
46 *
47 * getp <= endp <= size
48 *
49 * Note that after a stream function is called following may be true:
50 * if (getp == endp) then stream is no longer readable
51 * if (endp == size) then stream is no longer writeable
52 *
53 * It is valid to put to anywhere within the size of the stream, but only
54 * using stream_put..._at() functions.
55 */
56#define STREAM_WARN_OFFSETS(S) \
Subbaiah Venkatad5310502012-03-24 13:10:19 -070057 zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
David Lampartereed3c482015-03-03 08:51:53 +010058 (void *)(S), \
paul050c0132005-02-14 23:47:47 +000059 (unsigned long) (S)->size, \
60 (unsigned long) (S)->getp, \
61 (unsigned long) (S)->endp)\
paul718e3742002-12-13 20:15:29 +000062
paul050c0132005-02-14 23:47:47 +000063#define STREAM_VERIFY_SANE(S) \
64 do { \
Wenjian Ma1ed8ce42015-06-19 10:53:26 +080065 if ( !(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp)) ) \
paul050c0132005-02-14 23:47:47 +000066 STREAM_WARN_OFFSETS(S); \
67 assert ( GETP_VALID(S, (S)->getp) ); \
68 assert ( ENDP_VALID(S, (S)->endp) ); \
69 } while (0)
70
71#define STREAM_BOUND_WARN(S, WHAT) \
72 do { \
73 zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \
74 STREAM_WARN_OFFSETS(S); \
75 assert (0); \
76 } while (0)
77
78/* XXX: Deprecated macro: do not use */
paul718e3742002-12-13 20:15:29 +000079#define CHECK_SIZE(S, Z) \
paul050c0132005-02-14 23:47:47 +000080 do { \
81 if (((S)->endp + (Z)) > (S)->size) \
82 { \
83 zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \
84 (unsigned long) (Z)); \
85 STREAM_WARN_OFFSETS(S); \
86 (Z) = (S)->size - (S)->endp; \
87 } \
88 } while (0);
paul718e3742002-12-13 20:15:29 +000089
90/* Make stream buffer. */
91struct stream *
92stream_new (size_t size)
93{
94 struct stream *s;
95
paul0e43a2b2004-12-22 00:15:34 +000096 assert (size > 0);
97
98 if (size == 0)
paul050c0132005-02-14 23:47:47 +000099 {
100 zlog_warn ("stream_new(): called with 0 size!");
101 return NULL;
102 }
paul0e43a2b2004-12-22 00:15:34 +0000103
paul4b201d42006-01-10 14:35:19 +0000104 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
paul718e3742002-12-13 20:15:29 +0000105
paul050c0132005-02-14 23:47:47 +0000106 if (s == NULL)
107 return s;
108
paul4b201d42006-01-10 14:35:19 +0000109 if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
110 {
111 XFREE (MTYPE_STREAM, s);
112 return NULL;
113 }
114
paul718e3742002-12-13 20:15:29 +0000115 s->size = size;
116 return s;
117}
118
119/* Free it now. */
120void
121stream_free (struct stream *s)
122{
paul4b201d42006-01-10 14:35:19 +0000123 if (!s)
124 return;
125
126 XFREE (MTYPE_STREAM_DATA, s->data);
paul718e3742002-12-13 20:15:29 +0000127 XFREE (MTYPE_STREAM, s);
128}
paul050c0132005-02-14 23:47:47 +0000129
130struct stream *
131stream_copy (struct stream *new, struct stream *src)
132{
133 STREAM_VERIFY_SANE (src);
134
135 assert (new != NULL);
136 assert (STREAM_SIZE(new) >= src->endp);
137
138 new->endp = src->endp;
139 new->getp = src->getp;
140
141 memcpy (new->data, src->data, src->endp);
142
143 return new;
144}
145
146struct stream *
147stream_dup (struct stream *s)
148{
149 struct stream *new;
150
151 STREAM_VERIFY_SANE (s);
152
153 if ( (new = stream_new (s->endp)) == NULL)
154 return NULL;
155
156 return (stream_copy (new, s));
157}
paul4b201d42006-01-10 14:35:19 +0000158
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000159struct stream *
160stream_dupcat (struct stream *s1, struct stream *s2, size_t offset)
161{
162 struct stream *new;
163
164 STREAM_VERIFY_SANE (s1);
165 STREAM_VERIFY_SANE (s2);
166
167 if ( (new = stream_new (s1->endp + s2->endp)) == NULL)
168 return NULL;
169
170 memcpy (new->data, s1->data, offset);
171 memcpy (new->data + offset, s2->data, s2->endp);
172 memcpy (new->data + offset + s2->endp, s1->data + offset,
173 (s1->endp - offset));
174 new->endp = s1->endp + s2->endp;
175 return new;
176}
177
paul4b201d42006-01-10 14:35:19 +0000178size_t
179stream_resize (struct stream *s, size_t newsize)
180{
181 u_char *newdata;
182 STREAM_VERIFY_SANE (s);
183
184 newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
185
186 if (newdata == NULL)
187 return s->size;
188
189 s->data = newdata;
190 s->size = newsize;
191
192 if (s->endp > s->size)
193 s->endp = s->size;
194 if (s->getp > s->endp)
195 s->getp = s->endp;
196
197 STREAM_VERIFY_SANE (s);
198
199 return s->size;
200}
David Lamparter6b0655a2014-06-04 06:53:35 +0200201
paulf2e6c422005-02-12 14:35:49 +0000202size_t
paul718e3742002-12-13 20:15:29 +0000203stream_get_getp (struct stream *s)
204{
paul050c0132005-02-14 23:47:47 +0000205 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000206 return s->getp;
207}
208
paulf2e6c422005-02-12 14:35:49 +0000209size_t
paul718e3742002-12-13 20:15:29 +0000210stream_get_endp (struct stream *s)
211{
paul050c0132005-02-14 23:47:47 +0000212 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000213 return s->endp;
214}
215
paulf2e6c422005-02-12 14:35:49 +0000216size_t
paul718e3742002-12-13 20:15:29 +0000217stream_get_size (struct stream *s)
218{
paul050c0132005-02-14 23:47:47 +0000219 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000220 return s->size;
221}
222
223/* Stream structre' stream pointer related functions. */
224void
paulf2e6c422005-02-12 14:35:49 +0000225stream_set_getp (struct stream *s, size_t pos)
paul718e3742002-12-13 20:15:29 +0000226{
paul050c0132005-02-14 23:47:47 +0000227 STREAM_VERIFY_SANE(s);
228
229 if (!GETP_VALID (s, pos))
230 {
231 STREAM_BOUND_WARN (s, "set getp");
232 pos = s->endp;
233 }
234
paul718e3742002-12-13 20:15:29 +0000235 s->getp = pos;
236}
237
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700238void
239stream_set_endp (struct stream *s, size_t pos)
240{
241 STREAM_VERIFY_SANE(s);
242
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700243 if (!ENDP_VALID(s, pos))
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700244 {
245 STREAM_BOUND_WARN (s, "set endp");
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700246 return;
247 }
248
249 /*
250 * Make sure the current read pointer is not beyond the new endp.
251 */
252 if (s->getp > pos)
253 {
254 STREAM_BOUND_WARN(s, "set endp");
255 return;
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700256 }
257
258 s->endp = pos;
Avneesh Sachdev4effc292012-05-05 17:42:43 -0700259 STREAM_VERIFY_SANE(s);
Subbaiah Venkatad5310502012-03-24 13:10:19 -0700260}
261
paul718e3742002-12-13 20:15:29 +0000262/* Forward pointer. */
263void
paul050c0132005-02-14 23:47:47 +0000264stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000265{
paul050c0132005-02-14 23:47:47 +0000266 STREAM_VERIFY_SANE(s);
267
268 if (!GETP_VALID (s, s->getp + size))
269 {
270 STREAM_BOUND_WARN (s, "seek getp");
271 return;
272 }
273
paul718e3742002-12-13 20:15:29 +0000274 s->getp += size;
275}
paul9985f832005-02-09 15:51:56 +0000276
277void
paul050c0132005-02-14 23:47:47 +0000278stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000279{
paul050c0132005-02-14 23:47:47 +0000280 STREAM_VERIFY_SANE(s);
281
282 if (!ENDP_VALID (s, s->endp + size))
283 {
284 STREAM_BOUND_WARN (s, "seek endp");
285 return;
286 }
287
paul9985f832005-02-09 15:51:56 +0000288 s->endp += size;
289}
David Lamparter6b0655a2014-06-04 06:53:35 +0200290
paul718e3742002-12-13 20:15:29 +0000291/* Copy from stream to destination. */
292void
293stream_get (void *dst, struct stream *s, size_t size)
294{
paul050c0132005-02-14 23:47:47 +0000295 STREAM_VERIFY_SANE(s);
296
297 if (STREAM_READABLE(s) < size)
298 {
299 STREAM_BOUND_WARN (s, "get");
300 return;
301 }
302
paul718e3742002-12-13 20:15:29 +0000303 memcpy (dst, s->data + s->getp, size);
304 s->getp += size;
305}
306
307/* Get next character from the stream. */
308u_char
309stream_getc (struct stream *s)
310{
311 u_char c;
paul050c0132005-02-14 23:47:47 +0000312
313 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000314
paul050c0132005-02-14 23:47:47 +0000315 if (STREAM_READABLE(s) < sizeof (u_char))
316 {
317 STREAM_BOUND_WARN (s, "get char");
318 return 0;
319 }
320 c = s->data[s->getp++];
321
paul718e3742002-12-13 20:15:29 +0000322 return c;
323}
324
325/* Get next character from the stream. */
326u_char
paulf2e6c422005-02-12 14:35:49 +0000327stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000328{
329 u_char c;
330
paul050c0132005-02-14 23:47:47 +0000331 STREAM_VERIFY_SANE(s);
332
333 if (!GETP_VALID (s, from + sizeof (u_char)))
334 {
335 STREAM_BOUND_WARN (s, "get char");
336 return 0;
337 }
338
paul718e3742002-12-13 20:15:29 +0000339 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000340
paul718e3742002-12-13 20:15:29 +0000341 return c;
342}
343
344/* Get next word from the stream. */
345u_int16_t
346stream_getw (struct stream *s)
347{
348 u_int16_t w;
349
paul050c0132005-02-14 23:47:47 +0000350 STREAM_VERIFY_SANE (s);
351
352 if (STREAM_READABLE (s) < sizeof (u_int16_t))
353 {
354 STREAM_BOUND_WARN (s, "get ");
355 return 0;
356 }
357
paul718e3742002-12-13 20:15:29 +0000358 w = s->data[s->getp++] << 8;
359 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000360
paul718e3742002-12-13 20:15:29 +0000361 return w;
362}
363
364/* Get next word from the stream. */
365u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000366stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000367{
368 u_int16_t w;
369
paul050c0132005-02-14 23:47:47 +0000370 STREAM_VERIFY_SANE(s);
371
372 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
373 {
374 STREAM_BOUND_WARN (s, "get ");
375 return 0;
376 }
377
paul718e3742002-12-13 20:15:29 +0000378 w = s->data[from++] << 8;
379 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000380
paul718e3742002-12-13 20:15:29 +0000381 return w;
382}
383
384/* Get next long word from the stream. */
385u_int32_t
paul050c0132005-02-14 23:47:47 +0000386stream_getl_from (struct stream *s, size_t from)
387{
388 u_int32_t l;
389
390 STREAM_VERIFY_SANE(s);
391
392 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
393 {
394 STREAM_BOUND_WARN (s, "get long");
395 return 0;
396 }
397
398 l = s->data[from++] << 24;
399 l |= s->data[from++] << 16;
400 l |= s->data[from++] << 8;
401 l |= s->data[from];
402
403 return l;
404}
405
406u_int32_t
paul718e3742002-12-13 20:15:29 +0000407stream_getl (struct stream *s)
408{
409 u_int32_t l;
410
paul050c0132005-02-14 23:47:47 +0000411 STREAM_VERIFY_SANE(s);
412
413 if (STREAM_READABLE (s) < sizeof (u_int32_t))
414 {
415 STREAM_BOUND_WARN (s, "get long");
416 return 0;
417 }
418
paul718e3742002-12-13 20:15:29 +0000419 l = s->data[s->getp++] << 24;
420 l |= s->data[s->getp++] << 16;
421 l |= s->data[s->getp++] << 8;
422 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000423
paul718e3742002-12-13 20:15:29 +0000424 return l;
425}
paul4b201d42006-01-10 14:35:19 +0000426
427/* Get next quad word from the stream. */
428uint64_t
429stream_getq_from (struct stream *s, size_t from)
430{
paul581a02a2006-01-19 20:22:16 +0000431 uint64_t q;
paul4b201d42006-01-10 14:35:19 +0000432
433 STREAM_VERIFY_SANE(s);
434
435 if (!GETP_VALID (s, from + sizeof (uint64_t)))
436 {
437 STREAM_BOUND_WARN (s, "get quad");
438 return 0;
439 }
440
441 q = ((uint64_t) s->data[from++]) << 56;
442 q |= ((uint64_t) s->data[from++]) << 48;
443 q |= ((uint64_t) s->data[from++]) << 40;
444 q |= ((uint64_t) s->data[from++]) << 32;
445 q |= ((uint64_t) s->data[from++]) << 24;
446 q |= ((uint64_t) s->data[from++]) << 16;
447 q |= ((uint64_t) s->data[from++]) << 8;
448 q |= ((uint64_t) s->data[from++]);
449
450 return q;
451}
452
453uint64_t
454stream_getq (struct stream *s)
455{
456 uint64_t q;
457
458 STREAM_VERIFY_SANE(s);
459
460 if (STREAM_READABLE (s) < sizeof (uint64_t))
461 {
462 STREAM_BOUND_WARN (s, "get quad");
463 return 0;
464 }
465
466 q = ((uint64_t) s->data[s->getp++]) << 56;
467 q |= ((uint64_t) s->data[s->getp++]) << 48;
468 q |= ((uint64_t) s->data[s->getp++]) << 40;
469 q |= ((uint64_t) s->data[s->getp++]) << 32;
470 q |= ((uint64_t) s->data[s->getp++]) << 24;
471 q |= ((uint64_t) s->data[s->getp++]) << 16;
472 q |= ((uint64_t) s->data[s->getp++]) << 8;
473 q |= ((uint64_t) s->data[s->getp++]);
474
475 return q;
476}
477
paul718e3742002-12-13 20:15:29 +0000478/* Get next long word from the stream. */
479u_int32_t
480stream_get_ipv4 (struct stream *s)
481{
482 u_int32_t l;
483
paul050c0132005-02-14 23:47:47 +0000484 STREAM_VERIFY_SANE(s);
485
486 if (STREAM_READABLE (s) < sizeof(u_int32_t))
487 {
488 STREAM_BOUND_WARN (s, "get ipv4");
489 return 0;
490 }
491
492 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
493 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000494
495 return l;
496}
David Lamparter6b0655a2014-06-04 06:53:35 +0200497
Paul Jakmad41e7b92015-05-19 15:38:43 +0100498float
499stream_getf (struct stream *s)
500{
Paul Jakmaa3b161b2016-08-01 15:13:58 +0100501#if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
502#warning "Unknown floating-point format, __func__ may be wrong"
503#endif
504/* we assume 'float' is in the single precision IEC 60559 binary
505 format, in host byte order */
Paul Jakmad41e7b92015-05-19 15:38:43 +0100506 union {
507 float r;
508 uint32_t d;
509 } u;
510 u.d = stream_getl (s);
511 return u.r;
Paul Jakmad41e7b92015-05-19 15:38:43 +0100512}
513
514double
515stream_getd (struct stream *s)
516{
Paul Jakmaa3b161b2016-08-01 15:13:58 +0100517#if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
518#warning "Unknown floating-point format, __func__ may be wrong"
519#endif
Paul Jakmad41e7b92015-05-19 15:38:43 +0100520 union {
521 double r;
522 uint64_t d;
523 } u;
524 u.d = stream_getq (s);
525 return u.r;
Paul Jakmad41e7b92015-05-19 15:38:43 +0100526}
527
paul050c0132005-02-14 23:47:47 +0000528/* Copy to source to stream.
529 *
530 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
531 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000532 *
533 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000534 */
paul718e3742002-12-13 20:15:29 +0000535void
Paul Jakma3d52bb82008-06-07 20:42:07 +0000536stream_put (struct stream *s, const void *src, size_t size)
paul718e3742002-12-13 20:15:29 +0000537{
538
paul050c0132005-02-14 23:47:47 +0000539 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000540 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000541
542 STREAM_VERIFY_SANE(s);
543
544 if (STREAM_WRITEABLE (s) < size)
545 {
546 STREAM_BOUND_WARN (s, "put");
547 return;
548 }
549
paul718e3742002-12-13 20:15:29 +0000550 if (src)
paul9985f832005-02-09 15:51:56 +0000551 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000552 else
paul9985f832005-02-09 15:51:56 +0000553 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000554
paul9985f832005-02-09 15:51:56 +0000555 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000556}
557
558/* Put character to the stream. */
559int
560stream_putc (struct stream *s, u_char c)
561{
paul050c0132005-02-14 23:47:47 +0000562 STREAM_VERIFY_SANE(s);
563
564 if (STREAM_WRITEABLE (s) < sizeof(u_char))
565 {
566 STREAM_BOUND_WARN (s, "put");
567 return 0;
568 }
569
570 s->data[s->endp++] = c;
571 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000572}
573
574/* Put word to the stream. */
575int
576stream_putw (struct stream *s, u_int16_t w)
577{
paul050c0132005-02-14 23:47:47 +0000578 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000579
paul050c0132005-02-14 23:47:47 +0000580 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
581 {
582 STREAM_BOUND_WARN (s, "put");
583 return 0;
584 }
585
paul9985f832005-02-09 15:51:56 +0000586 s->data[s->endp++] = (u_char)(w >> 8);
587 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000588
paul718e3742002-12-13 20:15:29 +0000589 return 2;
590}
591
592/* Put long word to the stream. */
593int
594stream_putl (struct stream *s, u_int32_t l)
595{
paul050c0132005-02-14 23:47:47 +0000596 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000597
paul050c0132005-02-14 23:47:47 +0000598 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
599 {
600 STREAM_BOUND_WARN (s, "put");
601 return 0;
602 }
603
paul9985f832005-02-09 15:51:56 +0000604 s->data[s->endp++] = (u_char)(l >> 24);
605 s->data[s->endp++] = (u_char)(l >> 16);
606 s->data[s->endp++] = (u_char)(l >> 8);
607 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000608
paul718e3742002-12-13 20:15:29 +0000609 return 4;
610}
611
paul4b201d42006-01-10 14:35:19 +0000612/* Put quad word to the stream. */
613int
614stream_putq (struct stream *s, uint64_t q)
615{
616 STREAM_VERIFY_SANE (s);
617
618 if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
619 {
620 STREAM_BOUND_WARN (s, "put quad");
621 return 0;
622 }
623
624 s->data[s->endp++] = (u_char)(q >> 56);
625 s->data[s->endp++] = (u_char)(q >> 48);
626 s->data[s->endp++] = (u_char)(q >> 40);
627 s->data[s->endp++] = (u_char)(q >> 32);
628 s->data[s->endp++] = (u_char)(q >> 24);
629 s->data[s->endp++] = (u_char)(q >> 16);
630 s->data[s->endp++] = (u_char)(q >> 8);
631 s->data[s->endp++] = (u_char)q;
632
633 return 8;
634}
635
paul718e3742002-12-13 20:15:29 +0000636int
Paul Jakmad41e7b92015-05-19 15:38:43 +0100637stream_putf (struct stream *s, float f)
638{
Paul Jakmaa3b161b2016-08-01 15:13:58 +0100639#if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
640#warning "Unknown floating-point format, __func__ may be wrong"
641#endif
642
Paul Jakmad41e7b92015-05-19 15:38:43 +0100643/* we can safely assume 'float' is in the single precision
644 IEC 60559 binary format in host order */
645 union {
646 float i;
647 uint32_t o;
648 } u;
649 u.i = f;
650 return stream_putl (s, u.o);
Paul Jakmad41e7b92015-05-19 15:38:43 +0100651}
652
653int
654stream_putd (struct stream *s, double d)
655{
Paul Jakmaa3b161b2016-08-01 15:13:58 +0100656#if !defined(__STDC_IEC_559__) && __GCC_IEC_559 < 1
657#warning "Unknown floating-point format, __func__ may be wrong"
658#endif
Paul Jakmad41e7b92015-05-19 15:38:43 +0100659 union {
660 double i;
661 uint64_t o;
662 } u;
663 u.i = d;
664 return stream_putq (s, u.o);
Paul Jakmad41e7b92015-05-19 15:38:43 +0100665}
666
667int
paulf2e6c422005-02-12 14:35:49 +0000668stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000669{
paul050c0132005-02-14 23:47:47 +0000670 STREAM_VERIFY_SANE(s);
671
672 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
673 {
674 STREAM_BOUND_WARN (s, "put");
675 return 0;
676 }
677
paul718e3742002-12-13 20:15:29 +0000678 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000679
paul718e3742002-12-13 20:15:29 +0000680 return 1;
681}
682
683int
paulf2e6c422005-02-12 14:35:49 +0000684stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000685{
paul050c0132005-02-14 23:47:47 +0000686 STREAM_VERIFY_SANE(s);
687
688 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
689 {
690 STREAM_BOUND_WARN (s, "put");
691 return 0;
692 }
693
paul718e3742002-12-13 20:15:29 +0000694 s->data[putp] = (u_char)(w >> 8);
695 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000696
paul718e3742002-12-13 20:15:29 +0000697 return 2;
698}
699
700int
paulf2e6c422005-02-12 14:35:49 +0000701stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000702{
paul050c0132005-02-14 23:47:47 +0000703 STREAM_VERIFY_SANE(s);
704
705 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
706 {
707 STREAM_BOUND_WARN (s, "put");
708 return 0;
709 }
paul718e3742002-12-13 20:15:29 +0000710 s->data[putp] = (u_char)(l >> 24);
711 s->data[putp + 1] = (u_char)(l >> 16);
712 s->data[putp + 2] = (u_char)(l >> 8);
713 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000714
paul718e3742002-12-13 20:15:29 +0000715 return 4;
716}
717
paul4b201d42006-01-10 14:35:19 +0000718int
719stream_putq_at (struct stream *s, size_t putp, uint64_t q)
720{
721 STREAM_VERIFY_SANE(s);
722
723 if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
724 {
725 STREAM_BOUND_WARN (s, "put");
726 return 0;
727 }
728 s->data[putp] = (u_char)(q >> 56);
729 s->data[putp + 1] = (u_char)(q >> 48);
730 s->data[putp + 2] = (u_char)(q >> 40);
731 s->data[putp + 3] = (u_char)(q >> 32);
732 s->data[putp + 4] = (u_char)(q >> 24);
733 s->data[putp + 5] = (u_char)(q >> 16);
734 s->data[putp + 6] = (u_char)(q >> 8);
735 s->data[putp + 7] = (u_char)q;
736
737 return 8;
738}
739
paul718e3742002-12-13 20:15:29 +0000740/* Put long word to the stream. */
741int
742stream_put_ipv4 (struct stream *s, u_int32_t l)
743{
paul050c0132005-02-14 23:47:47 +0000744 STREAM_VERIFY_SANE(s);
745
746 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
747 {
748 STREAM_BOUND_WARN (s, "put");
749 return 0;
750 }
751 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
752 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000753
paul050c0132005-02-14 23:47:47 +0000754 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000755}
756
757/* Put long word to the stream. */
758int
759stream_put_in_addr (struct stream *s, struct in_addr *addr)
760{
paul050c0132005-02-14 23:47:47 +0000761 STREAM_VERIFY_SANE(s);
762
763 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
764 {
765 STREAM_BOUND_WARN (s, "put");
766 return 0;
767 }
paul718e3742002-12-13 20:15:29 +0000768
paul050c0132005-02-14 23:47:47 +0000769 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
770 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000771
paul050c0132005-02-14 23:47:47 +0000772 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000773}
774
775/* Put prefix by nlri type format. */
776int
777stream_put_prefix (struct stream *s, struct prefix *p)
778{
paul050c0132005-02-14 23:47:47 +0000779 size_t psize;
780
781 STREAM_VERIFY_SANE(s);
782
paul718e3742002-12-13 20:15:29 +0000783 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000784
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000785 if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
paul050c0132005-02-14 23:47:47 +0000786 {
787 STREAM_BOUND_WARN (s, "put");
788 return 0;
789 }
790
Jorge Boncompte [DTI2]af514772013-07-31 16:16:05 +0000791 s->data[s->endp++] = p->prefixlen;
paul9985f832005-02-09 15:51:56 +0000792 memcpy (s->data + s->endp, &p->u.prefix, psize);
793 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000794
paul718e3742002-12-13 20:15:29 +0000795 return psize;
796}
David Lamparter6b0655a2014-06-04 06:53:35 +0200797
paul718e3742002-12-13 20:15:29 +0000798/* Read size from fd. */
799int
800stream_read (struct stream *s, int fd, size_t size)
801{
802 int nbytes;
803
paul050c0132005-02-14 23:47:47 +0000804 STREAM_VERIFY_SANE(s);
805
806 if (STREAM_WRITEABLE (s) < size)
807 {
808 STREAM_BOUND_WARN (s, "put");
809 return 0;
810 }
811
paul9985f832005-02-09 15:51:56 +0000812 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000813
814 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000815 s->endp += nbytes;
816
paul718e3742002-12-13 20:15:29 +0000817 return nbytes;
818}
819
ajs262feb12005-02-16 20:35:47 +0000820ssize_t
821stream_read_try(struct stream *s, int fd, size_t size)
822{
823 ssize_t nbytes;
824
825 STREAM_VERIFY_SANE(s);
826
827 if (STREAM_WRITEABLE(s) < size)
828 {
829 STREAM_BOUND_WARN (s, "put");
830 /* Fatal (not transient) error, since retrying will not help
831 (stream is too small to contain the desired data). */
832 return -1;
833 }
834
835 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
836 {
837 s->endp += nbytes;
838 return nbytes;
839 }
840 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000841 if (ERRNO_IO_RETRY(errno))
842 return -2;
843 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
844 return -1;
ajs262feb12005-02-16 20:35:47 +0000845}
846
paul0dab9302005-05-03 09:07:56 +0000847/* Read up to size bytes into the stream from the fd, using recvmsgfrom
848 * whose arguments match the remaining arguments to this function
849 */
850ssize_t
851stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
852 struct sockaddr *from, socklen_t *fromlen)
853{
854 ssize_t nbytes;
855
856 STREAM_VERIFY_SANE(s);
857
858 if (STREAM_WRITEABLE(s) < size)
859 {
860 STREAM_BOUND_WARN (s, "put");
861 /* Fatal (not transient) error, since retrying will not help
862 (stream is too small to contain the desired data). */
863 return -1;
864 }
865
866 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
867 flags, from, fromlen)) >= 0)
868 {
869 s->endp += nbytes;
870 return nbytes;
871 }
872 /* Error: was it transient (return -2) or fatal (return -1)? */
873 if (ERRNO_IO_RETRY(errno))
874 return -2;
875 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
876 return -1;
877}
878
paul050c0132005-02-14 23:47:47 +0000879/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
880 * from endp.
881 * First iovec will be used to receive the data.
882 * Stream need not be empty.
883 */
paul0dab9302005-05-03 09:07:56 +0000884ssize_t
paul050c0132005-02-14 23:47:47 +0000885stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
886 size_t size)
887{
888 int nbytes;
889 struct iovec *iov;
890
891 STREAM_VERIFY_SANE(s);
892 assert (msgh->msg_iovlen > 0);
893
894 if (STREAM_WRITEABLE (s) < size)
895 {
896 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000897 /* This is a logic error in the calling code: the stream is too small
898 to hold the desired data! */
899 return -1;
paul050c0132005-02-14 23:47:47 +0000900 }
901
902 iov = &(msgh->msg_iov[0]);
903 iov->iov_base = (s->data + s->endp);
904 iov->iov_len = size;
905
906 nbytes = recvmsg (fd, msgh, flags);
907
908 if (nbytes > 0)
909 s->endp += nbytes;
910
911 return nbytes;
912}
913
paul718e3742002-12-13 20:15:29 +0000914/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000915size_t
Paul Jakma3d52bb82008-06-07 20:42:07 +0000916stream_write (struct stream *s, const void *ptr, size_t size)
paul718e3742002-12-13 20:15:29 +0000917{
918
919 CHECK_SIZE(s, size);
920
paul050c0132005-02-14 23:47:47 +0000921 STREAM_VERIFY_SANE(s);
922
923 if (STREAM_WRITEABLE (s) < size)
924 {
925 STREAM_BOUND_WARN (s, "put");
926 return 0;
927 }
928
paul9985f832005-02-09 15:51:56 +0000929 memcpy (s->data + s->endp, ptr, size);
930 s->endp += size;
931
paul718e3742002-12-13 20:15:29 +0000932 return size;
933}
934
paul050c0132005-02-14 23:47:47 +0000935/* Return current read pointer.
936 * DEPRECATED!
937 * Use stream_get_pnt_to if you must, but decoding streams properly
938 * is preferred
939 */
paul718e3742002-12-13 20:15:29 +0000940u_char *
941stream_pnt (struct stream *s)
942{
paul050c0132005-02-14 23:47:47 +0000943 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000944 return s->data + s->getp;
945}
946
947/* Check does this stream empty? */
948int
949stream_empty (struct stream *s)
950{
paul050c0132005-02-14 23:47:47 +0000951 STREAM_VERIFY_SANE(s);
952
953 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000954}
955
956/* Reset stream. */
957void
958stream_reset (struct stream *s)
959{
paul050c0132005-02-14 23:47:47 +0000960 STREAM_VERIFY_SANE (s);
961
962 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000963}
964
965/* Write stream contens to the file discriptor. */
966int
967stream_flush (struct stream *s, int fd)
968{
969 int nbytes;
paul050c0132005-02-14 23:47:47 +0000970
971 STREAM_VERIFY_SANE(s);
972
paul718e3742002-12-13 20:15:29 +0000973 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000974
paul718e3742002-12-13 20:15:29 +0000975 return nbytes;
976}
David Lamparter6b0655a2014-06-04 06:53:35 +0200977
paul718e3742002-12-13 20:15:29 +0000978/* Stream first in first out queue. */
979
980struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000981stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000982{
983 struct stream_fifo *new;
984
985 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
986 return new;
987}
988
989/* Add new stream to fifo. */
990void
991stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
992{
993 if (fifo->tail)
994 fifo->tail->next = s;
995 else
996 fifo->head = s;
997
998 fifo->tail = s;
999
1000 fifo->count++;
1001}
1002
1003/* Delete first stream from fifo. */
1004struct stream *
1005stream_fifo_pop (struct stream_fifo *fifo)
1006{
1007 struct stream *s;
1008
1009 s = fifo->head;
1010
1011 if (s)
1012 {
1013 fifo->head = s->next;
1014
1015 if (fifo->head == NULL)
1016 fifo->tail = NULL;
paul718e3742002-12-13 20:15:29 +00001017
Subbaiah Venkatad5310502012-03-24 13:10:19 -07001018 fifo->count--;
1019 }
paul718e3742002-12-13 20:15:29 +00001020
1021 return s;
1022}
1023
1024/* Return first fifo entry. */
1025struct stream *
1026stream_fifo_head (struct stream_fifo *fifo)
1027{
1028 return fifo->head;
1029}
1030
1031void
1032stream_fifo_clean (struct stream_fifo *fifo)
1033{
1034 struct stream *s;
1035 struct stream *next;
1036
1037 for (s = fifo->head; s; s = next)
1038 {
1039 next = s->next;
1040 stream_free (s);
1041 }
1042 fifo->head = fifo->tail = NULL;
1043 fifo->count = 0;
1044}
1045
1046void
1047stream_fifo_free (struct stream_fifo *fifo)
1048{
1049 stream_fifo_clean (fifo);
1050 XFREE (MTYPE_STREAM_FIFO, fifo);
1051}