blob: d8c1088299cf9a790a70b69a9eb24041223785e0 [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
paul109ac962005-02-19 01:17:07 +0000102 s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, data[size]));
paul718e3742002-12-13 20:15:29 +0000103
paul050c0132005-02-14 23:47:47 +0000104 if (s == NULL)
105 return s;
106
paul718e3742002-12-13 20:15:29 +0000107 s->size = size;
108 return s;
109}
110
111/* Free it now. */
112void
113stream_free (struct stream *s)
114{
paul718e3742002-12-13 20:15:29 +0000115 XFREE (MTYPE_STREAM, s);
116}
paul050c0132005-02-14 23:47:47 +0000117
118struct stream *
119stream_copy (struct stream *new, struct stream *src)
120{
121 STREAM_VERIFY_SANE (src);
122
123 assert (new != NULL);
124 assert (STREAM_SIZE(new) >= src->endp);
125
126 new->endp = src->endp;
127 new->getp = src->getp;
128
129 memcpy (new->data, src->data, src->endp);
130
131 return new;
132}
133
134struct stream *
135stream_dup (struct stream *s)
136{
137 struct stream *new;
138
139 STREAM_VERIFY_SANE (s);
140
141 if ( (new = stream_new (s->endp)) == NULL)
142 return NULL;
143
144 return (stream_copy (new, s));
145}
paul718e3742002-12-13 20:15:29 +0000146
paulf2e6c422005-02-12 14:35:49 +0000147size_t
paul718e3742002-12-13 20:15:29 +0000148stream_get_getp (struct stream *s)
149{
paul050c0132005-02-14 23:47:47 +0000150 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000151 return s->getp;
152}
153
paulf2e6c422005-02-12 14:35:49 +0000154size_t
paul718e3742002-12-13 20:15:29 +0000155stream_get_endp (struct stream *s)
156{
paul050c0132005-02-14 23:47:47 +0000157 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000158 return s->endp;
159}
160
paulf2e6c422005-02-12 14:35:49 +0000161size_t
paul718e3742002-12-13 20:15:29 +0000162stream_get_size (struct stream *s)
163{
paul050c0132005-02-14 23:47:47 +0000164 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000165 return s->size;
166}
167
168/* Stream structre' stream pointer related functions. */
169void
paulf2e6c422005-02-12 14:35:49 +0000170stream_set_getp (struct stream *s, size_t pos)
paul718e3742002-12-13 20:15:29 +0000171{
paul050c0132005-02-14 23:47:47 +0000172 STREAM_VERIFY_SANE(s);
173
174 if (!GETP_VALID (s, pos))
175 {
176 STREAM_BOUND_WARN (s, "set getp");
177 pos = s->endp;
178 }
179
paul718e3742002-12-13 20:15:29 +0000180 s->getp = pos;
181}
182
paul718e3742002-12-13 20:15:29 +0000183/* Forward pointer. */
184void
paul050c0132005-02-14 23:47:47 +0000185stream_forward_getp (struct stream *s, size_t size)
paul718e3742002-12-13 20:15:29 +0000186{
paul050c0132005-02-14 23:47:47 +0000187 STREAM_VERIFY_SANE(s);
188
189 if (!GETP_VALID (s, s->getp + size))
190 {
191 STREAM_BOUND_WARN (s, "seek getp");
192 return;
193 }
194
paul718e3742002-12-13 20:15:29 +0000195 s->getp += size;
196}
paul9985f832005-02-09 15:51:56 +0000197
198void
paul050c0132005-02-14 23:47:47 +0000199stream_forward_endp (struct stream *s, size_t size)
paul9985f832005-02-09 15:51:56 +0000200{
paul050c0132005-02-14 23:47:47 +0000201 STREAM_VERIFY_SANE(s);
202
203 if (!ENDP_VALID (s, s->endp + size))
204 {
205 STREAM_BOUND_WARN (s, "seek endp");
206 return;
207 }
208
paul9985f832005-02-09 15:51:56 +0000209 s->endp += size;
210}
paul718e3742002-12-13 20:15:29 +0000211
212/* Copy from stream to destination. */
213void
214stream_get (void *dst, struct stream *s, size_t size)
215{
paul050c0132005-02-14 23:47:47 +0000216 STREAM_VERIFY_SANE(s);
217
218 if (STREAM_READABLE(s) < size)
219 {
220 STREAM_BOUND_WARN (s, "get");
221 return;
222 }
223
paul718e3742002-12-13 20:15:29 +0000224 memcpy (dst, s->data + s->getp, size);
225 s->getp += size;
226}
227
228/* Get next character from the stream. */
229u_char
230stream_getc (struct stream *s)
231{
232 u_char c;
paul050c0132005-02-14 23:47:47 +0000233
234 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000235
paul050c0132005-02-14 23:47:47 +0000236 if (STREAM_READABLE(s) < sizeof (u_char))
237 {
238 STREAM_BOUND_WARN (s, "get char");
239 return 0;
240 }
241 c = s->data[s->getp++];
242
paul718e3742002-12-13 20:15:29 +0000243 return c;
244}
245
246/* Get next character from the stream. */
247u_char
paulf2e6c422005-02-12 14:35:49 +0000248stream_getc_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000249{
250 u_char c;
251
paul050c0132005-02-14 23:47:47 +0000252 STREAM_VERIFY_SANE(s);
253
254 if (!GETP_VALID (s, from + sizeof (u_char)))
255 {
256 STREAM_BOUND_WARN (s, "get char");
257 return 0;
258 }
259
paul718e3742002-12-13 20:15:29 +0000260 c = s->data[from];
paul050c0132005-02-14 23:47:47 +0000261
paul718e3742002-12-13 20:15:29 +0000262 return c;
263}
264
265/* Get next word from the stream. */
266u_int16_t
267stream_getw (struct stream *s)
268{
269 u_int16_t w;
270
paul050c0132005-02-14 23:47:47 +0000271 STREAM_VERIFY_SANE (s);
272
273 if (STREAM_READABLE (s) < sizeof (u_int16_t))
274 {
275 STREAM_BOUND_WARN (s, "get ");
276 return 0;
277 }
278
paul718e3742002-12-13 20:15:29 +0000279 w = s->data[s->getp++] << 8;
280 w |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000281
paul718e3742002-12-13 20:15:29 +0000282 return w;
283}
284
285/* Get next word from the stream. */
286u_int16_t
paulf2e6c422005-02-12 14:35:49 +0000287stream_getw_from (struct stream *s, size_t from)
paul718e3742002-12-13 20:15:29 +0000288{
289 u_int16_t w;
290
paul050c0132005-02-14 23:47:47 +0000291 STREAM_VERIFY_SANE(s);
292
293 if (!GETP_VALID (s, from + sizeof (u_int16_t)))
294 {
295 STREAM_BOUND_WARN (s, "get ");
296 return 0;
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 w = s->data[from++] << 8;
300 w |= s->data[from];
paul050c0132005-02-14 23:47:47 +0000301
paul718e3742002-12-13 20:15:29 +0000302 return w;
303}
304
305/* Get next long word from the stream. */
306u_int32_t
paul050c0132005-02-14 23:47:47 +0000307stream_getl_from (struct stream *s, size_t from)
308{
309 u_int32_t l;
310
311 STREAM_VERIFY_SANE(s);
312
313 if (!GETP_VALID (s, from + sizeof (u_int32_t)))
314 {
315 STREAM_BOUND_WARN (s, "get long");
316 return 0;
317 }
318
319 l = s->data[from++] << 24;
320 l |= s->data[from++] << 16;
321 l |= s->data[from++] << 8;
322 l |= s->data[from];
323
324 return l;
325}
326
327u_int32_t
paul718e3742002-12-13 20:15:29 +0000328stream_getl (struct stream *s)
329{
330 u_int32_t l;
331
paul050c0132005-02-14 23:47:47 +0000332 STREAM_VERIFY_SANE(s);
333
334 if (STREAM_READABLE (s) < sizeof (u_int32_t))
335 {
336 STREAM_BOUND_WARN (s, "get long");
337 return 0;
338 }
339
paul718e3742002-12-13 20:15:29 +0000340 l = s->data[s->getp++] << 24;
341 l |= s->data[s->getp++] << 16;
342 l |= s->data[s->getp++] << 8;
343 l |= s->data[s->getp++];
paul050c0132005-02-14 23:47:47 +0000344
paul718e3742002-12-13 20:15:29 +0000345 return l;
346}
paul718e3742002-12-13 20:15:29 +0000347/* Get next long word from the stream. */
348u_int32_t
349stream_get_ipv4 (struct stream *s)
350{
351 u_int32_t l;
352
paul050c0132005-02-14 23:47:47 +0000353 STREAM_VERIFY_SANE(s);
354
355 if (STREAM_READABLE (s) < sizeof(u_int32_t))
356 {
357 STREAM_BOUND_WARN (s, "get ipv4");
358 return 0;
359 }
360
361 memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
362 s->getp += sizeof(u_int32_t);
paul718e3742002-12-13 20:15:29 +0000363
364 return l;
365}
366
paul050c0132005-02-14 23:47:47 +0000367/* Copy to source to stream.
368 *
369 * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
370 * around. This should be fixed once the stream updates are working.
paul0dab9302005-05-03 09:07:56 +0000371 *
372 * stream_write() is saner
paul050c0132005-02-14 23:47:47 +0000373 */
paul718e3742002-12-13 20:15:29 +0000374void
375stream_put (struct stream *s, void *src, size_t size)
376{
377
paul050c0132005-02-14 23:47:47 +0000378 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000379 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000380
381 STREAM_VERIFY_SANE(s);
382
383 if (STREAM_WRITEABLE (s) < size)
384 {
385 STREAM_BOUND_WARN (s, "put");
386 return;
387 }
388
paul718e3742002-12-13 20:15:29 +0000389 if (src)
paul9985f832005-02-09 15:51:56 +0000390 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000391 else
paul9985f832005-02-09 15:51:56 +0000392 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000393
paul9985f832005-02-09 15:51:56 +0000394 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000395}
396
397/* Put character to the stream. */
398int
399stream_putc (struct stream *s, u_char c)
400{
paul050c0132005-02-14 23:47:47 +0000401 STREAM_VERIFY_SANE(s);
402
403 if (STREAM_WRITEABLE (s) < sizeof(u_char))
404 {
405 STREAM_BOUND_WARN (s, "put");
406 return 0;
407 }
408
409 s->data[s->endp++] = c;
410 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000411}
412
413/* Put word to the stream. */
414int
415stream_putw (struct stream *s, u_int16_t w)
416{
paul050c0132005-02-14 23:47:47 +0000417 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000418
paul050c0132005-02-14 23:47:47 +0000419 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
420 {
421 STREAM_BOUND_WARN (s, "put");
422 return 0;
423 }
424
paul9985f832005-02-09 15:51:56 +0000425 s->data[s->endp++] = (u_char)(w >> 8);
426 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000427
paul718e3742002-12-13 20:15:29 +0000428 return 2;
429}
430
431/* Put long word to the stream. */
432int
433stream_putl (struct stream *s, u_int32_t l)
434{
paul050c0132005-02-14 23:47:47 +0000435 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000436
paul050c0132005-02-14 23:47:47 +0000437 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
438 {
439 STREAM_BOUND_WARN (s, "put");
440 return 0;
441 }
442
paul9985f832005-02-09 15:51:56 +0000443 s->data[s->endp++] = (u_char)(l >> 24);
444 s->data[s->endp++] = (u_char)(l >> 16);
445 s->data[s->endp++] = (u_char)(l >> 8);
446 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000447
paul718e3742002-12-13 20:15:29 +0000448 return 4;
449}
450
451int
paulf2e6c422005-02-12 14:35:49 +0000452stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000453{
paul050c0132005-02-14 23:47:47 +0000454 STREAM_VERIFY_SANE(s);
455
456 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
457 {
458 STREAM_BOUND_WARN (s, "put");
459 return 0;
460 }
461
paul718e3742002-12-13 20:15:29 +0000462 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000463
paul718e3742002-12-13 20:15:29 +0000464 return 1;
465}
466
467int
paulf2e6c422005-02-12 14:35:49 +0000468stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000469{
paul050c0132005-02-14 23:47:47 +0000470 STREAM_VERIFY_SANE(s);
471
472 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
473 {
474 STREAM_BOUND_WARN (s, "put");
475 return 0;
476 }
477
paul718e3742002-12-13 20:15:29 +0000478 s->data[putp] = (u_char)(w >> 8);
479 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000480
paul718e3742002-12-13 20:15:29 +0000481 return 2;
482}
483
484int
paulf2e6c422005-02-12 14:35:49 +0000485stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000486{
paul050c0132005-02-14 23:47:47 +0000487 STREAM_VERIFY_SANE(s);
488
489 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
490 {
491 STREAM_BOUND_WARN (s, "put");
492 return 0;
493 }
paul718e3742002-12-13 20:15:29 +0000494 s->data[putp] = (u_char)(l >> 24);
495 s->data[putp + 1] = (u_char)(l >> 16);
496 s->data[putp + 2] = (u_char)(l >> 8);
497 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000498
paul718e3742002-12-13 20:15:29 +0000499 return 4;
500}
501
502/* Put long word to the stream. */
503int
504stream_put_ipv4 (struct stream *s, u_int32_t l)
505{
paul050c0132005-02-14 23:47:47 +0000506 STREAM_VERIFY_SANE(s);
507
508 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
509 {
510 STREAM_BOUND_WARN (s, "put");
511 return 0;
512 }
513 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
514 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000515
paul050c0132005-02-14 23:47:47 +0000516 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000517}
518
519/* Put long word to the stream. */
520int
521stream_put_in_addr (struct stream *s, struct in_addr *addr)
522{
paul050c0132005-02-14 23:47:47 +0000523 STREAM_VERIFY_SANE(s);
524
525 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
526 {
527 STREAM_BOUND_WARN (s, "put");
528 return 0;
529 }
paul718e3742002-12-13 20:15:29 +0000530
paul050c0132005-02-14 23:47:47 +0000531 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
532 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000533
paul050c0132005-02-14 23:47:47 +0000534 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000535}
536
537/* Put prefix by nlri type format. */
538int
539stream_put_prefix (struct stream *s, struct prefix *p)
540{
paul050c0132005-02-14 23:47:47 +0000541 size_t psize;
542
543 STREAM_VERIFY_SANE(s);
544
paul718e3742002-12-13 20:15:29 +0000545 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000546
547 if (STREAM_WRITEABLE (s) < psize)
548 {
549 STREAM_BOUND_WARN (s, "put");
550 return 0;
551 }
552
paul718e3742002-12-13 20:15:29 +0000553 stream_putc (s, p->prefixlen);
paul9985f832005-02-09 15:51:56 +0000554 memcpy (s->data + s->endp, &p->u.prefix, psize);
555 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000556
paul718e3742002-12-13 20:15:29 +0000557 return psize;
558}
559
560/* Read size from fd. */
561int
562stream_read (struct stream *s, int fd, size_t size)
563{
564 int nbytes;
565
paul050c0132005-02-14 23:47:47 +0000566 STREAM_VERIFY_SANE(s);
567
568 if (STREAM_WRITEABLE (s) < size)
569 {
570 STREAM_BOUND_WARN (s, "put");
571 return 0;
572 }
573
paul9985f832005-02-09 15:51:56 +0000574 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000575
576 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000577 s->endp += nbytes;
578
paul718e3742002-12-13 20:15:29 +0000579 return nbytes;
580}
581
582/* Read size from fd. */
583int
584stream_read_unblock (struct stream *s, int fd, size_t size)
585{
586 int nbytes;
587 int val;
paul050c0132005-02-14 23:47:47 +0000588
589 STREAM_VERIFY_SANE(s);
590
591 if (STREAM_WRITEABLE (s) < size)
592 {
593 STREAM_BOUND_WARN (s, "put");
594 return 0;
595 }
596
paul718e3742002-12-13 20:15:29 +0000597 val = fcntl (fd, F_GETFL, 0);
598 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000599 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000600 fcntl (fd, F_SETFL, val);
601
602 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000603 s->endp += nbytes;
604
paul718e3742002-12-13 20:15:29 +0000605 return nbytes;
606}
607
ajs262feb12005-02-16 20:35:47 +0000608ssize_t
609stream_read_try(struct stream *s, int fd, size_t size)
610{
611 ssize_t nbytes;
612
613 STREAM_VERIFY_SANE(s);
614
615 if (STREAM_WRITEABLE(s) < size)
616 {
617 STREAM_BOUND_WARN (s, "put");
618 /* Fatal (not transient) error, since retrying will not help
619 (stream is too small to contain the desired data). */
620 return -1;
621 }
622
623 if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
624 {
625 s->endp += nbytes;
626 return nbytes;
627 }
628 /* Error: was it transient (return -2) or fatal (return -1)? */
ajs81fb3242005-02-24 16:02:53 +0000629 if (ERRNO_IO_RETRY(errno))
630 return -2;
631 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
632 return -1;
ajs262feb12005-02-16 20:35:47 +0000633}
634
paul0dab9302005-05-03 09:07:56 +0000635/* Read up to size bytes into the stream from the fd, using recvmsgfrom
636 * whose arguments match the remaining arguments to this function
637 */
638ssize_t
639stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
640 struct sockaddr *from, socklen_t *fromlen)
641{
642 ssize_t nbytes;
643
644 STREAM_VERIFY_SANE(s);
645
646 if (STREAM_WRITEABLE(s) < size)
647 {
648 STREAM_BOUND_WARN (s, "put");
649 /* Fatal (not transient) error, since retrying will not help
650 (stream is too small to contain the desired data). */
651 return -1;
652 }
653
654 if ((nbytes = recvfrom (fd, s->data + s->endp, size,
655 flags, from, fromlen)) >= 0)
656 {
657 s->endp += nbytes;
658 return nbytes;
659 }
660 /* Error: was it transient (return -2) or fatal (return -1)? */
661 if (ERRNO_IO_RETRY(errno))
662 return -2;
663 zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
664 return -1;
665}
666
paul050c0132005-02-14 23:47:47 +0000667/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
668 * from endp.
669 * First iovec will be used to receive the data.
670 * Stream need not be empty.
671 */
paul0dab9302005-05-03 09:07:56 +0000672ssize_t
paul050c0132005-02-14 23:47:47 +0000673stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
674 size_t size)
675{
676 int nbytes;
677 struct iovec *iov;
678
679 STREAM_VERIFY_SANE(s);
680 assert (msgh->msg_iovlen > 0);
681
682 if (STREAM_WRITEABLE (s) < size)
683 {
684 STREAM_BOUND_WARN (s, "put");
ajs262feb12005-02-16 20:35:47 +0000685 /* This is a logic error in the calling code: the stream is too small
686 to hold the desired data! */
687 return -1;
paul050c0132005-02-14 23:47:47 +0000688 }
689
690 iov = &(msgh->msg_iov[0]);
691 iov->iov_base = (s->data + s->endp);
692 iov->iov_len = size;
693
694 nbytes = recvmsg (fd, msgh, flags);
695
696 if (nbytes > 0)
697 s->endp += nbytes;
698
699 return nbytes;
700}
701
paul718e3742002-12-13 20:15:29 +0000702/* Write data to buffer. */
paul0dab9302005-05-03 09:07:56 +0000703size_t
paul718e3742002-12-13 20:15:29 +0000704stream_write (struct stream *s, u_char *ptr, size_t size)
705{
706
707 CHECK_SIZE(s, size);
708
paul050c0132005-02-14 23:47:47 +0000709 STREAM_VERIFY_SANE(s);
710
711 if (STREAM_WRITEABLE (s) < size)
712 {
713 STREAM_BOUND_WARN (s, "put");
714 return 0;
715 }
716
paul9985f832005-02-09 15:51:56 +0000717 memcpy (s->data + s->endp, ptr, size);
718 s->endp += size;
719
paul718e3742002-12-13 20:15:29 +0000720 return size;
721}
722
paul050c0132005-02-14 23:47:47 +0000723/* Return current read pointer.
724 * DEPRECATED!
725 * Use stream_get_pnt_to if you must, but decoding streams properly
726 * is preferred
727 */
paul718e3742002-12-13 20:15:29 +0000728u_char *
729stream_pnt (struct stream *s)
730{
paul050c0132005-02-14 23:47:47 +0000731 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000732 return s->data + s->getp;
733}
734
735/* Check does this stream empty? */
736int
737stream_empty (struct stream *s)
738{
paul050c0132005-02-14 23:47:47 +0000739 STREAM_VERIFY_SANE(s);
740
741 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000742}
743
744/* Reset stream. */
745void
746stream_reset (struct stream *s)
747{
paul050c0132005-02-14 23:47:47 +0000748 STREAM_VERIFY_SANE (s);
749
750 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000751}
752
753/* Write stream contens to the file discriptor. */
754int
755stream_flush (struct stream *s, int fd)
756{
757 int nbytes;
paul050c0132005-02-14 23:47:47 +0000758
759 STREAM_VERIFY_SANE(s);
760
paul718e3742002-12-13 20:15:29 +0000761 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000762
paul718e3742002-12-13 20:15:29 +0000763 return nbytes;
764}
765
766/* Stream first in first out queue. */
767
768struct stream_fifo *
ajs81fb3242005-02-24 16:02:53 +0000769stream_fifo_new (void)
paul718e3742002-12-13 20:15:29 +0000770{
771 struct stream_fifo *new;
772
773 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
774 return new;
775}
776
777/* Add new stream to fifo. */
778void
779stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
780{
781 if (fifo->tail)
782 fifo->tail->next = s;
783 else
784 fifo->head = s;
785
786 fifo->tail = s;
787
788 fifo->count++;
789}
790
791/* Delete first stream from fifo. */
792struct stream *
793stream_fifo_pop (struct stream_fifo *fifo)
794{
795 struct stream *s;
796
797 s = fifo->head;
798
799 if (s)
800 {
801 fifo->head = s->next;
802
803 if (fifo->head == NULL)
804 fifo->tail = NULL;
805 }
806
807 fifo->count--;
808
809 return s;
810}
811
812/* Return first fifo entry. */
813struct stream *
814stream_fifo_head (struct stream_fifo *fifo)
815{
816 return fifo->head;
817}
818
819void
820stream_fifo_clean (struct stream_fifo *fifo)
821{
822 struct stream *s;
823 struct stream *next;
824
825 for (s = fifo->head; s; s = next)
826 {
827 next = s->next;
828 stream_free (s);
829 }
830 fifo->head = fifo->tail = NULL;
831 fifo->count = 0;
832}
833
834void
835stream_fifo_free (struct stream_fifo *fifo)
836{
837 stream_fifo_clean (fifo);
838 XFREE (MTYPE_STREAM_FIFO, fifo);
839}