blob: 1b85b130d30e0c95d309bbc2c5d41143f7a50d99 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * 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>
24
25#include "stream.h"
26#include "memory.h"
27#include "network.h"
28#include "prefix.h"
29
30
31/*A macro to check pointers in order to not
32 go behind the allocated mem block
33 S -- stream reference
34 Z -- size of data to be written
35*/
36
37#define CHECK_SIZE(S, Z) \
38 if (((S)->putp + (Z)) > (S)->size) \
39 (Z) = (S)->size - (S)->putp;
40
41/* Stream is fixed length buffer for network output/input. */
42
43/* Make stream buffer. */
44struct stream *
45stream_new (size_t size)
46{
47 struct stream *s;
48
paul0e43a2b2004-12-22 00:15:34 +000049 assert (size > 0);
50
51 if (size == 0)
52 return NULL;
53
paul718e3742002-12-13 20:15:29 +000054 s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
55
56 s->data = XCALLOC (MTYPE_STREAM_DATA, size);
57 s->size = size;
58 return s;
59}
60
61/* Free it now. */
62void
63stream_free (struct stream *s)
64{
65 XFREE (MTYPE_STREAM_DATA, s->data);
66 XFREE (MTYPE_STREAM, s);
67}
68
69unsigned long
70stream_get_getp (struct stream *s)
71{
72 return s->getp;
73}
74
75unsigned long
76stream_get_putp (struct stream *s)
77{
78 return s->putp;
79}
80
81unsigned long
82stream_get_endp (struct stream *s)
83{
84 return s->endp;
85}
86
87unsigned long
88stream_get_size (struct stream *s)
89{
90 return s->size;
91}
92
93/* Stream structre' stream pointer related functions. */
94void
95stream_set_getp (struct stream *s, unsigned long pos)
96{
97 s->getp = pos;
98}
99
100void
101stream_set_putp (struct stream *s, unsigned long pos)
102{
103 s->putp = pos;
104}
105
106/* Forward pointer. */
107void
108stream_forward (struct stream *s, int size)
109{
110 s->getp += size;
111}
112
113/* Copy from stream to destination. */
114void
115stream_get (void *dst, struct stream *s, size_t size)
116{
117 memcpy (dst, s->data + s->getp, size);
118 s->getp += size;
119}
120
121/* Get next character from the stream. */
122u_char
123stream_getc (struct stream *s)
124{
125 u_char c;
126
127 c = s->data[s->getp];
128 s->getp++;
129 return c;
130}
131
132/* Get next character from the stream. */
133u_char
134stream_getc_from (struct stream *s, unsigned long from)
135{
136 u_char c;
137
138 c = s->data[from];
139 return c;
140}
141
142/* Get next word from the stream. */
143u_int16_t
144stream_getw (struct stream *s)
145{
146 u_int16_t w;
147
148 w = s->data[s->getp++] << 8;
149 w |= s->data[s->getp++];
150 return w;
151}
152
153/* Get next word from the stream. */
154u_int16_t
155stream_getw_from (struct stream *s, unsigned long from)
156{
157 u_int16_t w;
158
159 w = s->data[from++] << 8;
160 w |= s->data[from];
161 return w;
162}
163
164/* Get next long word from the stream. */
165u_int32_t
166stream_getl (struct stream *s)
167{
168 u_int32_t l;
169
170 l = s->data[s->getp++] << 24;
171 l |= s->data[s->getp++] << 16;
172 l |= s->data[s->getp++] << 8;
173 l |= s->data[s->getp++];
174 return l;
175}
176
177/* Get next long word from the stream. */
178u_int32_t
179stream_get_ipv4 (struct stream *s)
180{
181 u_int32_t l;
182
183 memcpy (&l, s->data + s->getp, 4);
184 s->getp += 4;
185
186 return l;
187}
188
189/* Copy to source to stream. */
190void
191stream_put (struct stream *s, void *src, size_t size)
192{
193
194 CHECK_SIZE(s, size);
195
196 if (src)
197 memcpy (s->data + s->putp, src, size);
198 else
199 memset (s->data + s->putp, 0, size);
200
201 s->putp += size;
202 if (s->putp > s->endp)
203 s->endp = s->putp;
204}
205
206/* Put character to the stream. */
207int
208stream_putc (struct stream *s, u_char c)
209{
210 if (s->putp >= s->size) return 0;
211
212 s->data[s->putp] = c;
213 s->putp++;
214 if (s->putp > s->endp)
215 s->endp = s->putp;
216 return 1;
217}
218
219/* Put word to the stream. */
220int
221stream_putw (struct stream *s, u_int16_t w)
222{
223 if ((s->size - s->putp) < 2) return 0;
224
225 s->data[s->putp++] = (u_char)(w >> 8);
226 s->data[s->putp++] = (u_char) w;
227
228 if (s->putp > s->endp)
229 s->endp = s->putp;
230 return 2;
231}
232
233/* Put long word to the stream. */
234int
235stream_putl (struct stream *s, u_int32_t l)
236{
237 if ((s->size - s->putp) < 4) return 0;
238
239 s->data[s->putp++] = (u_char)(l >> 24);
240 s->data[s->putp++] = (u_char)(l >> 16);
241 s->data[s->putp++] = (u_char)(l >> 8);
242 s->data[s->putp++] = (u_char)l;
243
244 if (s->putp > s->endp)
245 s->endp = s->putp;
246 return 4;
247}
248
249int
250stream_putc_at (struct stream *s, unsigned long putp, u_char c)
251{
252 s->data[putp] = c;
253 return 1;
254}
255
256int
257stream_putw_at (struct stream *s, unsigned long putp, u_int16_t w)
258{
259 s->data[putp] = (u_char)(w >> 8);
260 s->data[putp + 1] = (u_char) w;
261 return 2;
262}
263
264int
265stream_putl_at (struct stream *s, unsigned long putp, u_int32_t l)
266{
267 s->data[putp] = (u_char)(l >> 24);
268 s->data[putp + 1] = (u_char)(l >> 16);
269 s->data[putp + 2] = (u_char)(l >> 8);
270 s->data[putp + 3] = (u_char)l;
271 return 4;
272}
273
274/* Put long word to the stream. */
275int
276stream_put_ipv4 (struct stream *s, u_int32_t l)
277{
278 if ((s->size - s->putp) < 4)
279 return 0;
280
281 memcpy (s->data + s->putp, &l, 4);
282 s->putp += 4;
283
284 if (s->putp > s->endp)
285 s->endp = s->putp;
286 return 4;
287}
288
289/* Put long word to the stream. */
290int
291stream_put_in_addr (struct stream *s, struct in_addr *addr)
292{
293 if ((s->size - s->putp) < 4)
294 return 0;
295
296 memcpy (s->data + s->putp, addr, 4);
297 s->putp += 4;
298
299 if (s->putp > s->endp)
300 s->endp = s->putp;
301 return 4;
302}
303
304/* Put prefix by nlri type format. */
305int
306stream_put_prefix (struct stream *s, struct prefix *p)
307{
308 u_char psize;
309
310 psize = PSIZE (p->prefixlen);
311
312 if ((s->size - s->putp) < psize) return 0;
313
314 stream_putc (s, p->prefixlen);
315 memcpy (s->data + s->putp, &p->u.prefix, psize);
316 s->putp += psize;
317
318 if (s->putp > s->endp)
319 s->endp = s->putp;
320
321 return psize;
322}
323
324/* Read size from fd. */
325int
326stream_read (struct stream *s, int fd, size_t size)
327{
328 int nbytes;
329
330 nbytes = readn (fd, s->data + s->putp, size);
331
332 if (nbytes > 0)
333 {
334 s->putp += nbytes;
335 s->endp += nbytes;
336 }
337 return nbytes;
338}
339
340/* Read size from fd. */
341int
342stream_read_unblock (struct stream *s, int fd, size_t size)
343{
344 int nbytes;
345 int val;
346
347 val = fcntl (fd, F_GETFL, 0);
348 fcntl (fd, F_SETFL, val|O_NONBLOCK);
349 nbytes = read (fd, s->data + s->putp, size);
350 fcntl (fd, F_SETFL, val);
351
352 if (nbytes > 0)
353 {
354 s->putp += nbytes;
355 s->endp += nbytes;
356 }
357 return nbytes;
358}
359
360/* Write data to buffer. */
361int
362stream_write (struct stream *s, u_char *ptr, size_t size)
363{
364
365 CHECK_SIZE(s, size);
366
367 memcpy (s->data + s->putp, ptr, size);
368 s->putp += size;
369 if (s->putp > s->endp)
370 s->endp = s->putp;
371 return size;
372}
373
374/* Return current read pointer. */
375u_char *
376stream_pnt (struct stream *s)
377{
378 return s->data + s->getp;
379}
380
381/* Check does this stream empty? */
382int
383stream_empty (struct stream *s)
384{
385 if (s->putp == 0 && s->endp == 0 && s->getp == 0)
386 return 1;
387 else
388 return 0;
389}
390
391/* Reset stream. */
392void
393stream_reset (struct stream *s)
394{
395 s->putp = 0;
396 s->endp = 0;
397 s->getp = 0;
398}
399
400/* Write stream contens to the file discriptor. */
401int
402stream_flush (struct stream *s, int fd)
403{
404 int nbytes;
405
406 nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
407
408 return nbytes;
409}
410
411/* Stream first in first out queue. */
412
413struct stream_fifo *
414stream_fifo_new ()
415{
416 struct stream_fifo *new;
417
418 new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
419 return new;
420}
421
422/* Add new stream to fifo. */
423void
424stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
425{
426 if (fifo->tail)
427 fifo->tail->next = s;
428 else
429 fifo->head = s;
430
431 fifo->tail = s;
432
433 fifo->count++;
434}
435
436/* Delete first stream from fifo. */
437struct stream *
438stream_fifo_pop (struct stream_fifo *fifo)
439{
440 struct stream *s;
441
442 s = fifo->head;
443
444 if (s)
445 {
446 fifo->head = s->next;
447
448 if (fifo->head == NULL)
449 fifo->tail = NULL;
450 }
451
452 fifo->count--;
453
454 return s;
455}
456
457/* Return first fifo entry. */
458struct stream *
459stream_fifo_head (struct stream_fifo *fifo)
460{
461 return fifo->head;
462}
463
464void
465stream_fifo_clean (struct stream_fifo *fifo)
466{
467 struct stream *s;
468 struct stream *next;
469
470 for (s = fifo->head; s; s = next)
471 {
472 next = s->next;
473 stream_free (s);
474 }
475 fifo->head = fifo->tail = NULL;
476 fifo->count = 0;
477}
478
479void
480stream_fifo_free (struct stream_fifo *fifo)
481{
482 stream_fifo_clean (fifo);
483 XFREE (MTYPE_STREAM_FIFO, fifo);
484}