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