blob: e15d04267551a5104d8300942656bd3c54cd84b1 [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
paul050c0132005-02-14 23:47:47 +0000102 s = XCALLOC (MTYPE_STREAM, offsetof(struct stream, 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.
371 */
paul718e3742002-12-13 20:15:29 +0000372void
373stream_put (struct stream *s, void *src, size_t size)
374{
375
paul050c0132005-02-14 23:47:47 +0000376 /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
paul718e3742002-12-13 20:15:29 +0000377 CHECK_SIZE(s, size);
paul050c0132005-02-14 23:47:47 +0000378
379 STREAM_VERIFY_SANE(s);
380
381 if (STREAM_WRITEABLE (s) < size)
382 {
383 STREAM_BOUND_WARN (s, "put");
384 return;
385 }
386
paul718e3742002-12-13 20:15:29 +0000387 if (src)
paul9985f832005-02-09 15:51:56 +0000388 memcpy (s->data + s->endp, src, size);
paul718e3742002-12-13 20:15:29 +0000389 else
paul9985f832005-02-09 15:51:56 +0000390 memset (s->data + s->endp, 0, size);
paul718e3742002-12-13 20:15:29 +0000391
paul9985f832005-02-09 15:51:56 +0000392 s->endp += size;
paul718e3742002-12-13 20:15:29 +0000393}
394
395/* Put character to the stream. */
396int
397stream_putc (struct stream *s, u_char c)
398{
paul050c0132005-02-14 23:47:47 +0000399 STREAM_VERIFY_SANE(s);
400
401 if (STREAM_WRITEABLE (s) < sizeof(u_char))
402 {
403 STREAM_BOUND_WARN (s, "put");
404 return 0;
405 }
406
407 s->data[s->endp++] = c;
408 return sizeof (u_char);
paul718e3742002-12-13 20:15:29 +0000409}
410
411/* Put word to the stream. */
412int
413stream_putw (struct stream *s, u_int16_t w)
414{
paul050c0132005-02-14 23:47:47 +0000415 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000416
paul050c0132005-02-14 23:47:47 +0000417 if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
418 {
419 STREAM_BOUND_WARN (s, "put");
420 return 0;
421 }
422
paul9985f832005-02-09 15:51:56 +0000423 s->data[s->endp++] = (u_char)(w >> 8);
424 s->data[s->endp++] = (u_char) w;
paul718e3742002-12-13 20:15:29 +0000425
paul718e3742002-12-13 20:15:29 +0000426 return 2;
427}
428
429/* Put long word to the stream. */
430int
431stream_putl (struct stream *s, u_int32_t l)
432{
paul050c0132005-02-14 23:47:47 +0000433 STREAM_VERIFY_SANE (s);
paul718e3742002-12-13 20:15:29 +0000434
paul050c0132005-02-14 23:47:47 +0000435 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
436 {
437 STREAM_BOUND_WARN (s, "put");
438 return 0;
439 }
440
paul9985f832005-02-09 15:51:56 +0000441 s->data[s->endp++] = (u_char)(l >> 24);
442 s->data[s->endp++] = (u_char)(l >> 16);
443 s->data[s->endp++] = (u_char)(l >> 8);
444 s->data[s->endp++] = (u_char)l;
paul718e3742002-12-13 20:15:29 +0000445
paul718e3742002-12-13 20:15:29 +0000446 return 4;
447}
448
449int
paulf2e6c422005-02-12 14:35:49 +0000450stream_putc_at (struct stream *s, size_t putp, u_char c)
paul718e3742002-12-13 20:15:29 +0000451{
paul050c0132005-02-14 23:47:47 +0000452 STREAM_VERIFY_SANE(s);
453
454 if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
455 {
456 STREAM_BOUND_WARN (s, "put");
457 return 0;
458 }
459
paul718e3742002-12-13 20:15:29 +0000460 s->data[putp] = c;
paul050c0132005-02-14 23:47:47 +0000461
paul718e3742002-12-13 20:15:29 +0000462 return 1;
463}
464
465int
paulf2e6c422005-02-12 14:35:49 +0000466stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
paul718e3742002-12-13 20:15:29 +0000467{
paul050c0132005-02-14 23:47:47 +0000468 STREAM_VERIFY_SANE(s);
469
470 if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
471 {
472 STREAM_BOUND_WARN (s, "put");
473 return 0;
474 }
475
paul718e3742002-12-13 20:15:29 +0000476 s->data[putp] = (u_char)(w >> 8);
477 s->data[putp + 1] = (u_char) w;
paul050c0132005-02-14 23:47:47 +0000478
paul718e3742002-12-13 20:15:29 +0000479 return 2;
480}
481
482int
paulf2e6c422005-02-12 14:35:49 +0000483stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
paul718e3742002-12-13 20:15:29 +0000484{
paul050c0132005-02-14 23:47:47 +0000485 STREAM_VERIFY_SANE(s);
486
487 if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
488 {
489 STREAM_BOUND_WARN (s, "put");
490 return 0;
491 }
paul718e3742002-12-13 20:15:29 +0000492 s->data[putp] = (u_char)(l >> 24);
493 s->data[putp + 1] = (u_char)(l >> 16);
494 s->data[putp + 2] = (u_char)(l >> 8);
495 s->data[putp + 3] = (u_char)l;
paul050c0132005-02-14 23:47:47 +0000496
paul718e3742002-12-13 20:15:29 +0000497 return 4;
498}
499
500/* Put long word to the stream. */
501int
502stream_put_ipv4 (struct stream *s, u_int32_t l)
503{
paul050c0132005-02-14 23:47:47 +0000504 STREAM_VERIFY_SANE(s);
505
506 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
507 {
508 STREAM_BOUND_WARN (s, "put");
509 return 0;
510 }
511 memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
512 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000513
paul050c0132005-02-14 23:47:47 +0000514 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000515}
516
517/* Put long word to the stream. */
518int
519stream_put_in_addr (struct stream *s, struct in_addr *addr)
520{
paul050c0132005-02-14 23:47:47 +0000521 STREAM_VERIFY_SANE(s);
522
523 if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
524 {
525 STREAM_BOUND_WARN (s, "put");
526 return 0;
527 }
paul718e3742002-12-13 20:15:29 +0000528
paul050c0132005-02-14 23:47:47 +0000529 memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
530 s->endp += sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000531
paul050c0132005-02-14 23:47:47 +0000532 return sizeof (u_int32_t);
paul718e3742002-12-13 20:15:29 +0000533}
534
535/* Put prefix by nlri type format. */
536int
537stream_put_prefix (struct stream *s, struct prefix *p)
538{
paul050c0132005-02-14 23:47:47 +0000539 size_t psize;
540
541 STREAM_VERIFY_SANE(s);
542
paul718e3742002-12-13 20:15:29 +0000543 psize = PSIZE (p->prefixlen);
paul050c0132005-02-14 23:47:47 +0000544
545 if (STREAM_WRITEABLE (s) < psize)
546 {
547 STREAM_BOUND_WARN (s, "put");
548 return 0;
549 }
550
paul718e3742002-12-13 20:15:29 +0000551 stream_putc (s, p->prefixlen);
paul9985f832005-02-09 15:51:56 +0000552 memcpy (s->data + s->endp, &p->u.prefix, psize);
553 s->endp += psize;
paul718e3742002-12-13 20:15:29 +0000554
paul718e3742002-12-13 20:15:29 +0000555 return psize;
556}
557
558/* Read size from fd. */
559int
560stream_read (struct stream *s, int fd, size_t size)
561{
562 int nbytes;
563
paul050c0132005-02-14 23:47:47 +0000564 STREAM_VERIFY_SANE(s);
565
566 if (STREAM_WRITEABLE (s) < size)
567 {
568 STREAM_BOUND_WARN (s, "put");
569 return 0;
570 }
571
paul9985f832005-02-09 15:51:56 +0000572 nbytes = readn (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000573
574 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000575 s->endp += nbytes;
576
paul718e3742002-12-13 20:15:29 +0000577 return nbytes;
578}
579
580/* Read size from fd. */
581int
582stream_read_unblock (struct stream *s, int fd, size_t size)
583{
584 int nbytes;
585 int val;
paul050c0132005-02-14 23:47:47 +0000586
587 STREAM_VERIFY_SANE(s);
588
589 if (STREAM_WRITEABLE (s) < size)
590 {
591 STREAM_BOUND_WARN (s, "put");
592 return 0;
593 }
594
paul718e3742002-12-13 20:15:29 +0000595 val = fcntl (fd, F_GETFL, 0);
596 fcntl (fd, F_SETFL, val|O_NONBLOCK);
paul9985f832005-02-09 15:51:56 +0000597 nbytes = read (fd, s->data + s->endp, size);
paul718e3742002-12-13 20:15:29 +0000598 fcntl (fd, F_SETFL, val);
599
600 if (nbytes > 0)
paul9985f832005-02-09 15:51:56 +0000601 s->endp += nbytes;
602
paul718e3742002-12-13 20:15:29 +0000603 return nbytes;
604}
605
paul050c0132005-02-14 23:47:47 +0000606/* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
607 * from endp.
608 * First iovec will be used to receive the data.
609 * Stream need not be empty.
610 */
611int
612stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
613 size_t size)
614{
615 int nbytes;
616 struct iovec *iov;
617
618 STREAM_VERIFY_SANE(s);
619 assert (msgh->msg_iovlen > 0);
620
621 if (STREAM_WRITEABLE (s) < size)
622 {
623 STREAM_BOUND_WARN (s, "put");
624 return 0;
625 }
626
627 iov = &(msgh->msg_iov[0]);
628 iov->iov_base = (s->data + s->endp);
629 iov->iov_len = size;
630
631 nbytes = recvmsg (fd, msgh, flags);
632
633 if (nbytes > 0)
634 s->endp += nbytes;
635
636 return nbytes;
637}
638
paul718e3742002-12-13 20:15:29 +0000639/* Write data to buffer. */
640int
641stream_write (struct stream *s, u_char *ptr, size_t size)
642{
643
644 CHECK_SIZE(s, size);
645
paul050c0132005-02-14 23:47:47 +0000646 STREAM_VERIFY_SANE(s);
647
648 if (STREAM_WRITEABLE (s) < size)
649 {
650 STREAM_BOUND_WARN (s, "put");
651 return 0;
652 }
653
paul9985f832005-02-09 15:51:56 +0000654 memcpy (s->data + s->endp, ptr, size);
655 s->endp += size;
656
paul718e3742002-12-13 20:15:29 +0000657 return size;
658}
659
paul050c0132005-02-14 23:47:47 +0000660/* Return current read pointer.
661 * DEPRECATED!
662 * Use stream_get_pnt_to if you must, but decoding streams properly
663 * is preferred
664 */
paul718e3742002-12-13 20:15:29 +0000665u_char *
666stream_pnt (struct stream *s)
667{
paul050c0132005-02-14 23:47:47 +0000668 STREAM_VERIFY_SANE(s);
paul718e3742002-12-13 20:15:29 +0000669 return s->data + s->getp;
670}
671
672/* Check does this stream empty? */
673int
674stream_empty (struct stream *s)
675{
paul050c0132005-02-14 23:47:47 +0000676 STREAM_VERIFY_SANE(s);
677
678 return (s->endp == 0);
paul718e3742002-12-13 20:15:29 +0000679}
680
681/* Reset stream. */
682void
683stream_reset (struct stream *s)
684{
paul050c0132005-02-14 23:47:47 +0000685 STREAM_VERIFY_SANE (s);
686
687 s->getp = s->endp = 0;
paul718e3742002-12-13 20:15:29 +0000688}
689
690/* Write stream contens to the file discriptor. */
691int
692stream_flush (struct stream *s, int fd)
693{
694 int nbytes;
paul050c0132005-02-14 23:47:47 +0000695
696 STREAM_VERIFY_SANE(s);
697
paul718e3742002-12-13 20:15:29 +0000698 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
paul050c0132005-02-14 23:47:47 +0000699
paul718e3742002-12-13 20:15:29 +0000700 return nbytes;
701}
702
703/* Stream first in first out queue. */
704
705struct stream_fifo *
706stream_fifo_new ()
707{
708 struct stream_fifo *new;
709
710 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
711 return new;
712}
713
714/* Add new stream to fifo. */
715void
716stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
717{
718 if (fifo->tail)
719 fifo->tail->next = s;
720 else
721 fifo->head = s;
722
723 fifo->tail = s;
724
725 fifo->count++;
726}
727
728/* Delete first stream from fifo. */
729struct stream *
730stream_fifo_pop (struct stream_fifo *fifo)
731{
732 struct stream *s;
733
734 s = fifo->head;
735
736 if (s)
737 {
738 fifo->head = s->next;
739
740 if (fifo->head == NULL)
741 fifo->tail = NULL;
742 }
743
744 fifo->count--;
745
746 return s;
747}
748
749/* Return first fifo entry. */
750struct stream *
751stream_fifo_head (struct stream_fifo *fifo)
752{
753 return fifo->head;
754}
755
756void
757stream_fifo_clean (struct stream_fifo *fifo)
758{
759 struct stream *s;
760 struct stream *next;
761
762 for (s = fifo->head; s; s = next)
763 {
764 next = s->next;
765 stream_free (s);
766 }
767 fifo->head = fifo->tail = NULL;
768 fifo->count = 0;
769}
770
771void
772stream_fifo_free (struct stream_fifo *fifo)
773{
774 stream_fifo_clean (fifo);
775 XFREE (MTYPE_STREAM_FIFO, fifo);
776}