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