LCOV - code coverage report
Current view: top level - lib - stream.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 373 44.2 %
Date: 2015-11-19 Functions: 27 50 54.0 %

          Line data    Source code
       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 <stddef.h>
      24             : #include <zebra.h>
      25             : 
      26             : #include "stream.h"
      27             : #include "memory.h"
      28             : #include "network.h"
      29             : #include "prefix.h"
      30             : #include "log.h"
      31             : 
      32             : /* 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)
      38             : 
      39             : /* 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, getp: %lu, endp: %lu\n", \
      56             :              (S), \
      57             :              (unsigned long) (S)->size, \
      58             :              (unsigned long) (S)->getp, \
      59             :              (unsigned long) (S)->endp)\
      60             : 
      61             : #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 */
      77             : #define CHECK_SIZE(S, Z) \
      78             :   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);
      87             : 
      88             : /* Make stream buffer. */
      89             : struct stream *
      90         540 : stream_new (size_t size)
      91             : {
      92             :   struct stream *s;
      93             : 
      94         540 :   assert (size > 0);
      95             :   
      96         540 :   if (size == 0)
      97             :     {
      98           0 :       zlog_warn ("stream_new(): called with 0 size!");
      99           0 :       return NULL;
     100             :     }
     101             :   
     102         540 :   s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
     103             : 
     104         540 :   if (s == NULL)
     105           0 :     return s;
     106             :   
     107         540 :   if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
     108             :     {
     109           0 :       XFREE (MTYPE_STREAM, s);
     110           0 :       return NULL;
     111             :     }
     112             :   
     113         540 :   s->size = size;
     114         540 :   return s;
     115             : }
     116             : 
     117             : /* Free it now. */
     118             : void
     119         397 : stream_free (struct stream *s)
     120             : {
     121         397 :   if (!s)
     122           0 :     return;
     123             :   
     124         397 :   XFREE (MTYPE_STREAM_DATA, s->data);
     125         397 :   XFREE (MTYPE_STREAM, s);
     126             : }
     127             : 
     128             : struct stream *
     129           0 : stream_copy (struct stream *new, struct stream *src)
     130             : {
     131           0 :   STREAM_VERIFY_SANE (src);
     132             :   
     133           0 :   assert (new != NULL);
     134           0 :   assert (STREAM_SIZE(new) >= src->endp);
     135             : 
     136           0 :   new->endp = src->endp;
     137           0 :   new->getp = src->getp;
     138             :   
     139           0 :   memcpy (new->data, src->data, src->endp);
     140             :   
     141           0 :   return new;
     142             : }
     143             : 
     144             : struct stream *
     145           0 : stream_dup (struct stream *s)
     146             : {
     147             :   struct stream *new;
     148             : 
     149           0 :   STREAM_VERIFY_SANE (s);
     150             : 
     151           0 :   if ( (new = stream_new (s->endp)) == NULL)
     152           0 :     return NULL;
     153             : 
     154           0 :   return (stream_copy (new, s));
     155             : }
     156             : 
     157             : size_t
     158           1 : stream_resize (struct stream *s, size_t newsize)
     159             : {
     160             :   u_char *newdata;
     161           1 :   STREAM_VERIFY_SANE (s);
     162             :   
     163           1 :   newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
     164             :   
     165           1 :   if (newdata == NULL)
     166           0 :     return s->size;
     167             :   
     168           1 :   s->data = newdata;
     169           1 :   s->size = newsize;
     170             :   
     171           1 :   if (s->endp > s->size)
     172           0 :     s->endp = s->size;
     173           1 :   if (s->getp > s->endp)
     174           0 :     s->getp = s->endp;
     175             :   
     176           1 :   STREAM_VERIFY_SANE (s);
     177             :   
     178           1 :   return s->size;
     179             : }
     180             : 
     181             : size_t
     182        1080 : stream_get_getp (struct stream *s)
     183             : {
     184        1080 :   STREAM_VERIFY_SANE(s);
     185        1080 :   return s->getp;
     186             : }
     187             : 
     188             : size_t
     189         739 : stream_get_endp (struct stream *s)
     190             : {
     191         739 :   STREAM_VERIFY_SANE(s);
     192         739 :   return s->endp;
     193             : }
     194             : 
     195             : size_t
     196           0 : stream_get_size (struct stream *s)
     197             : {
     198           0 :   STREAM_VERIFY_SANE(s);
     199           0 :   return s->size;
     200             : }
     201             : 
     202             : /* Stream structre' stream pointer related functions.  */
     203             : void
     204         297 : stream_set_getp (struct stream *s, size_t pos)
     205             : {
     206         297 :   STREAM_VERIFY_SANE(s);
     207             :   
     208         297 :   if (!GETP_VALID (s, pos))
     209             :     {
     210           0 :       STREAM_BOUND_WARN (s, "set getp");
     211             :       pos = s->endp;
     212             :     }
     213             : 
     214         297 :   s->getp = pos;
     215         297 : }
     216             : 
     217             : void
     218           0 : stream_set_endp (struct stream *s, size_t pos)
     219             : {
     220           0 :   STREAM_VERIFY_SANE(s);
     221             : 
     222           0 :   if (!ENDP_VALID(s, pos))
     223             :     {
     224           0 :       STREAM_BOUND_WARN (s, "set endp");
     225             :       return;
     226             :     }
     227             : 
     228             :   /*
     229             :    * Make sure the current read pointer is not beyond the new endp.
     230             :    */
     231           0 :   if (s->getp > pos)
     232             :     {
     233           0 :       STREAM_BOUND_WARN(s, "set endp");
     234             :       return;
     235             :     }
     236             : 
     237           0 :   s->endp = pos;
     238           0 :   STREAM_VERIFY_SANE(s);
     239           0 : }
     240             : 
     241             : /* Forward pointer. */
     242             : void
     243          93 : stream_forward_getp (struct stream *s, size_t size)
     244             : {
     245          93 :   STREAM_VERIFY_SANE(s);
     246             :   
     247          93 :   if (!GETP_VALID (s, s->getp + size))
     248             :     {
     249           0 :       STREAM_BOUND_WARN (s, "seek getp");
     250             :       return;
     251             :     }
     252             :   
     253          93 :   s->getp += size;
     254          93 : }
     255             : 
     256             : void
     257           0 : stream_forward_endp (struct stream *s, size_t size)
     258             : {
     259           0 :   STREAM_VERIFY_SANE(s);
     260             :   
     261           0 :   if (!ENDP_VALID (s, s->endp + size))
     262             :     {
     263           0 :       STREAM_BOUND_WARN (s, "seek endp");
     264             :       return;
     265             :     }
     266             :   
     267           0 :   s->endp += size;
     268           0 : }
     269             : 
     270             : /* Copy from stream to destination. */
     271             : void
     272         194 : stream_get (void *dst, struct stream *s, size_t size)
     273             : {
     274         194 :   STREAM_VERIFY_SANE(s);
     275             :   
     276         194 :   if (STREAM_READABLE(s) < size)
     277             :     {
     278           0 :       STREAM_BOUND_WARN (s, "get");
     279             :       return;
     280             :     }
     281             :   
     282         194 :   memcpy (dst, s->data + s->getp, size);
     283         194 :   s->getp += size;
     284         194 : }
     285             : 
     286             : /* Get next character from the stream. */
     287             : u_char
     288        3350 : stream_getc (struct stream *s)
     289             : {
     290             :   u_char c;
     291             :   
     292        3350 :   STREAM_VERIFY_SANE (s);
     293             : 
     294        3350 :   if (STREAM_READABLE(s) < sizeof (u_char))
     295             :     {
     296           0 :       STREAM_BOUND_WARN (s, "get char");
     297             :       return 0;
     298             :     }
     299        3350 :   c = s->data[s->getp++];
     300             :   
     301        3350 :   return c;
     302             : }
     303             : 
     304             : /* Get next character from the stream. */
     305             : u_char
     306           0 : stream_getc_from (struct stream *s, size_t from)
     307             : {
     308             :   u_char c;
     309             : 
     310           0 :   STREAM_VERIFY_SANE(s);
     311             :   
     312           0 :   if (!GETP_VALID (s, from + sizeof (u_char)))
     313             :     {
     314           0 :       STREAM_BOUND_WARN (s, "get char");
     315             :       return 0;
     316             :     }
     317             :   
     318           0 :   c = s->data[from];
     319             :   
     320           0 :   return c;
     321             : }
     322             : 
     323             : /* Get next word from the stream. */
     324             : u_int16_t
     325        3271 : stream_getw (struct stream *s)
     326             : {
     327             :   u_int16_t w;
     328             : 
     329        3271 :   STREAM_VERIFY_SANE (s);
     330             : 
     331        3271 :   if (STREAM_READABLE (s) < sizeof (u_int16_t))
     332             :     {
     333           0 :       STREAM_BOUND_WARN (s, "get ");
     334             :       return 0;
     335             :     }
     336             :   
     337        3271 :   w = s->data[s->getp++] << 8;
     338        3271 :   w |= s->data[s->getp++];
     339             :   
     340        3271 :   return w;
     341             : }
     342             : 
     343             : /* Get next word from the stream. */
     344             : u_int16_t
     345           0 : stream_getw_from (struct stream *s, size_t from)
     346             : {
     347             :   u_int16_t w;
     348             : 
     349           0 :   STREAM_VERIFY_SANE(s);
     350             :   
     351           0 :   if (!GETP_VALID (s, from + sizeof (u_int16_t)))
     352             :     {
     353           0 :       STREAM_BOUND_WARN (s, "get ");
     354             :       return 0;
     355             :     }
     356             :   
     357           0 :   w = s->data[from++] << 8;
     358           0 :   w |= s->data[from];
     359             :   
     360           0 :   return w;
     361             : }
     362             : 
     363             : /* Get next long word from the stream. */
     364             : u_int32_t
     365           0 : stream_getl_from (struct stream *s, size_t from)
     366             : {
     367             :   u_int32_t l;
     368             : 
     369           0 :   STREAM_VERIFY_SANE(s);
     370             :   
     371           0 :   if (!GETP_VALID (s, from + sizeof (u_int32_t)))
     372             :     {
     373           0 :       STREAM_BOUND_WARN (s, "get long");
     374             :       return 0;
     375             :     }
     376             :   
     377           0 :   l  = s->data[from++] << 24;
     378           0 :   l |= s->data[from++] << 16;
     379           0 :   l |= s->data[from++] << 8;
     380           0 :   l |= s->data[from];
     381             :   
     382           0 :   return l;
     383             : }
     384             : 
     385             : u_int32_t
     386        1280 : stream_getl (struct stream *s)
     387             : {
     388             :   u_int32_t l;
     389             : 
     390        1280 :   STREAM_VERIFY_SANE(s);
     391             :   
     392        1280 :   if (STREAM_READABLE (s) < sizeof (u_int32_t))
     393             :     {
     394           0 :       STREAM_BOUND_WARN (s, "get long");
     395             :       return 0;
     396             :     }
     397             :   
     398        1280 :   l  = s->data[s->getp++] << 24;
     399        1280 :   l |= s->data[s->getp++] << 16;
     400        1280 :   l |= s->data[s->getp++] << 8;
     401        1280 :   l |= s->data[s->getp++];
     402             :   
     403        1280 :   return l;
     404             : }
     405             : 
     406             : /* Get next quad word from the stream. */
     407             : uint64_t
     408           0 : stream_getq_from (struct stream *s, size_t from)
     409             : {
     410             :   uint64_t q;
     411             : 
     412           0 :   STREAM_VERIFY_SANE(s);
     413             :   
     414           0 :   if (!GETP_VALID (s, from + sizeof (uint64_t)))
     415             :     {
     416           0 :       STREAM_BOUND_WARN (s, "get quad");
     417             :       return 0;
     418             :     }
     419             :   
     420           0 :   q  = ((uint64_t) s->data[from++]) << 56;
     421           0 :   q |= ((uint64_t) s->data[from++]) << 48;
     422           0 :   q |= ((uint64_t) s->data[from++]) << 40;
     423           0 :   q |= ((uint64_t) s->data[from++]) << 32;  
     424           0 :   q |= ((uint64_t) s->data[from++]) << 24;
     425           0 :   q |= ((uint64_t) s->data[from++]) << 16;
     426           0 :   q |= ((uint64_t) s->data[from++]) << 8;
     427           0 :   q |= ((uint64_t) s->data[from++]);
     428             :   
     429           0 :   return q;
     430             : }
     431             : 
     432             : uint64_t
     433           1 : stream_getq (struct stream *s)
     434             : {
     435             :   uint64_t q;
     436             : 
     437           1 :   STREAM_VERIFY_SANE(s);
     438             :   
     439           1 :   if (STREAM_READABLE (s) < sizeof (uint64_t))
     440             :     {
     441           0 :       STREAM_BOUND_WARN (s, "get quad");
     442             :       return 0;
     443             :     }
     444             :   
     445           1 :   q  = ((uint64_t) s->data[s->getp++]) << 56;
     446           1 :   q |= ((uint64_t) s->data[s->getp++]) << 48;
     447           1 :   q |= ((uint64_t) s->data[s->getp++]) << 40;
     448           1 :   q |= ((uint64_t) s->data[s->getp++]) << 32;  
     449           1 :   q |= ((uint64_t) s->data[s->getp++]) << 24;
     450           1 :   q |= ((uint64_t) s->data[s->getp++]) << 16;
     451           1 :   q |= ((uint64_t) s->data[s->getp++]) << 8;
     452           1 :   q |= ((uint64_t) s->data[s->getp++]);
     453             :   
     454           1 :   return q;
     455             : }
     456             : 
     457             : /* Get next long word from the stream. */
     458             : u_int32_t
     459         335 : stream_get_ipv4 (struct stream *s)
     460             : {
     461             :   u_int32_t l;
     462             : 
     463         335 :   STREAM_VERIFY_SANE(s);
     464             :   
     465         335 :   if (STREAM_READABLE (s) < sizeof(u_int32_t))
     466             :     {
     467           0 :       STREAM_BOUND_WARN (s, "get ipv4");
     468             :       return 0;
     469             :     }
     470             :   
     471         335 :   memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
     472         335 :   s->getp += sizeof(u_int32_t);
     473             : 
     474         335 :   return l;
     475             : }
     476             : 
     477             : /* Copy to source to stream.
     478             :  *
     479             :  * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
     480             :  * around. This should be fixed once the stream updates are working.
     481             :  *
     482             :  * stream_write() is saner
     483             :  */
     484             : void
     485         349 : stream_put (struct stream *s, const void *src, size_t size)
     486             : {
     487             : 
     488             :   /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
     489         349 :   CHECK_SIZE(s, size);
     490             :   
     491         349 :   STREAM_VERIFY_SANE(s);
     492             :   
     493         349 :   if (STREAM_WRITEABLE (s) < size)
     494             :     {
     495           0 :       STREAM_BOUND_WARN (s, "put");
     496             :       return;
     497             :     }
     498             :   
     499         349 :   if (src)
     500         286 :     memcpy (s->data + s->endp, src, size);
     501             :   else
     502          63 :     memset (s->data + s->endp, 0, size);
     503             : 
     504         349 :   s->endp += size;
     505         349 : }
     506             : 
     507             : /* Put character to the stream. */
     508             : int
     509        1307 : stream_putc (struct stream *s, u_char c)
     510             : {
     511        1307 :   STREAM_VERIFY_SANE(s);
     512             :   
     513        1307 :   if (STREAM_WRITEABLE (s) < sizeof(u_char))
     514             :     {
     515           0 :       STREAM_BOUND_WARN (s, "put");
     516             :       return 0;
     517             :     }
     518             :   
     519        1307 :   s->data[s->endp++] = c;
     520        1307 :   return sizeof (u_char);
     521             : }
     522             : 
     523             : /* Put word to the stream. */
     524             : int
     525        1248 : stream_putw (struct stream *s, u_int16_t w)
     526             : {
     527        1248 :   STREAM_VERIFY_SANE (s);
     528             : 
     529        1248 :   if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
     530             :     {
     531           0 :       STREAM_BOUND_WARN (s, "put");
     532             :       return 0;
     533             :     }
     534             :   
     535        1248 :   s->data[s->endp++] = (u_char)(w >>  8);
     536        1248 :   s->data[s->endp++] = (u_char) w;
     537             : 
     538        1248 :   return 2;
     539             : }
     540             : 
     541             : /* Put long word to the stream. */
     542             : int
     543        1224 : stream_putl (struct stream *s, u_int32_t l)
     544             : {
     545        1224 :   STREAM_VERIFY_SANE (s);
     546             : 
     547        1224 :   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
     548             :     {
     549           0 :       STREAM_BOUND_WARN (s, "put");
     550             :       return 0;
     551             :     }
     552             :   
     553        1224 :   s->data[s->endp++] = (u_char)(l >> 24);
     554        1224 :   s->data[s->endp++] = (u_char)(l >> 16);
     555        1224 :   s->data[s->endp++] = (u_char)(l >>  8);
     556        1224 :   s->data[s->endp++] = (u_char)l;
     557             : 
     558        1224 :   return 4;
     559             : }
     560             : 
     561             : /* Put quad word to the stream. */
     562             : int
     563           1 : stream_putq (struct stream *s, uint64_t q)
     564             : {
     565           1 :   STREAM_VERIFY_SANE (s);
     566             : 
     567           1 :   if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
     568             :     {
     569           0 :       STREAM_BOUND_WARN (s, "put quad");
     570             :       return 0;
     571             :     }
     572             :   
     573           1 :   s->data[s->endp++] = (u_char)(q >> 56);
     574           1 :   s->data[s->endp++] = (u_char)(q >> 48);
     575           1 :   s->data[s->endp++] = (u_char)(q >> 40);
     576           1 :   s->data[s->endp++] = (u_char)(q >> 32);
     577           1 :   s->data[s->endp++] = (u_char)(q >> 24);
     578           1 :   s->data[s->endp++] = (u_char)(q >> 16);
     579           1 :   s->data[s->endp++] = (u_char)(q >>  8);
     580           1 :   s->data[s->endp++] = (u_char)q;
     581             : 
     582           1 :   return 8;
     583             : }
     584             : 
     585             : int
     586           0 : stream_putc_at (struct stream *s, size_t putp, u_char c)
     587             : {
     588           0 :   STREAM_VERIFY_SANE(s);
     589             :   
     590           0 :   if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
     591             :     {
     592           0 :       STREAM_BOUND_WARN (s, "put");
     593             :       return 0;
     594             :     }
     595             :   
     596           0 :   s->data[putp] = c;
     597             :   
     598           0 :   return 1;
     599             : }
     600             : 
     601             : int
     602          34 : stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
     603             : {
     604          34 :   STREAM_VERIFY_SANE(s);
     605             :   
     606          34 :   if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
     607             :     {
     608           0 :       STREAM_BOUND_WARN (s, "put");
     609             :       return 0;
     610             :     }
     611             :   
     612          34 :   s->data[putp] = (u_char)(w >>  8);
     613          34 :   s->data[putp + 1] = (u_char) w;
     614             :   
     615          34 :   return 2;
     616             : }
     617             : 
     618             : int
     619           0 : stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
     620             : {
     621           0 :   STREAM_VERIFY_SANE(s);
     622             :   
     623           0 :   if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
     624             :     {
     625           0 :       STREAM_BOUND_WARN (s, "put");
     626             :       return 0;
     627             :     }
     628           0 :   s->data[putp] = (u_char)(l >> 24);
     629           0 :   s->data[putp + 1] = (u_char)(l >> 16);
     630           0 :   s->data[putp + 2] = (u_char)(l >>  8);
     631           0 :   s->data[putp + 3] = (u_char)l;
     632             :   
     633           0 :   return 4;
     634             : }
     635             : 
     636             : int
     637           0 : stream_putq_at (struct stream *s, size_t putp, uint64_t q)
     638             : {
     639           0 :   STREAM_VERIFY_SANE(s);
     640             :   
     641           0 :   if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
     642             :     {
     643           0 :       STREAM_BOUND_WARN (s, "put");
     644             :       return 0;
     645             :     }
     646           0 :   s->data[putp] =     (u_char)(q >> 56);
     647           0 :   s->data[putp + 1] = (u_char)(q >> 48);
     648           0 :   s->data[putp + 2] = (u_char)(q >> 40);
     649           0 :   s->data[putp + 3] = (u_char)(q >> 32);
     650           0 :   s->data[putp + 4] = (u_char)(q >> 24);
     651           0 :   s->data[putp + 5] = (u_char)(q >> 16);
     652           0 :   s->data[putp + 6] = (u_char)(q >>  8);
     653           0 :   s->data[putp + 7] = (u_char)q;
     654             :   
     655           0 :   return 8;
     656             : }
     657             : 
     658             : /* Put long word to the stream. */
     659             : int
     660           0 : stream_put_ipv4 (struct stream *s, u_int32_t l)
     661             : {
     662           0 :   STREAM_VERIFY_SANE(s);
     663             :   
     664           0 :   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
     665             :     {
     666           0 :       STREAM_BOUND_WARN (s, "put");
     667             :       return 0;
     668             :     }
     669           0 :   memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
     670           0 :   s->endp += sizeof (u_int32_t);
     671             : 
     672           0 :   return sizeof (u_int32_t);
     673             : }
     674             : 
     675             : /* Put long word to the stream. */
     676             : int
     677           0 : stream_put_in_addr (struct stream *s, struct in_addr *addr)
     678             : {
     679           0 :   STREAM_VERIFY_SANE(s);
     680             :   
     681           0 :   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
     682             :     {
     683           0 :       STREAM_BOUND_WARN (s, "put");
     684             :       return 0;
     685             :     }
     686             : 
     687           0 :   memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
     688           0 :   s->endp += sizeof (u_int32_t);
     689             : 
     690           0 :   return sizeof (u_int32_t);
     691             : }
     692             : 
     693             : /* Put prefix by nlri type format. */
     694             : int
     695           0 : stream_put_prefix (struct stream *s, struct prefix *p)
     696             : {
     697             :   size_t psize;
     698             :   
     699           0 :   STREAM_VERIFY_SANE(s);
     700             :   
     701           0 :   psize = PSIZE (p->prefixlen);
     702             :   
     703           0 :   if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
     704             :     {
     705           0 :       STREAM_BOUND_WARN (s, "put");
     706             :       return 0;
     707             :     }
     708             :   
     709           0 :   s->data[s->endp++] = p->prefixlen;
     710           0 :   memcpy (s->data + s->endp, &p->u.prefix, psize);
     711           0 :   s->endp += psize;
     712             :   
     713           0 :   return psize;
     714             : }
     715             : 
     716             : /* Read size from fd. */
     717             : int
     718           0 : stream_read (struct stream *s, int fd, size_t size)
     719             : {
     720             :   int nbytes;
     721             : 
     722           0 :   STREAM_VERIFY_SANE(s);
     723             :   
     724           0 :   if (STREAM_WRITEABLE (s) < size)
     725             :     {
     726           0 :       STREAM_BOUND_WARN (s, "put");
     727             :       return 0;
     728             :     }
     729             :   
     730           0 :   nbytes = readn (fd, s->data + s->endp, size);
     731             : 
     732           0 :   if (nbytes > 0)
     733           0 :     s->endp += nbytes;
     734             :   
     735           0 :   return nbytes;
     736             : }
     737             : 
     738             : /* Read size from fd. */
     739             : int
     740           0 : stream_read_unblock (struct stream *s, int fd, size_t size)
     741             : {
     742             :   int nbytes;
     743             :   int val;
     744             :   
     745           0 :   STREAM_VERIFY_SANE(s);
     746             :   
     747           0 :   if (STREAM_WRITEABLE (s) < size)
     748             :     {
     749           0 :       STREAM_BOUND_WARN (s, "put");
     750             :       return 0;
     751             :     }
     752             :   
     753           0 :   val = fcntl (fd, F_GETFL, 0);
     754           0 :   fcntl (fd, F_SETFL, val|O_NONBLOCK);
     755           0 :   nbytes = read (fd, s->data + s->endp, size);
     756           0 :   fcntl (fd, F_SETFL, val);
     757             : 
     758           0 :   if (nbytes > 0)
     759           0 :     s->endp += nbytes;
     760             :   
     761           0 :   return nbytes;
     762             : }
     763             : 
     764             : ssize_t
     765         417 : stream_read_try(struct stream *s, int fd, size_t size)
     766             : {
     767             :   ssize_t nbytes;
     768             : 
     769         417 :   STREAM_VERIFY_SANE(s);
     770             :   
     771         417 :   if (STREAM_WRITEABLE(s) < size)
     772             :     {
     773           0 :       STREAM_BOUND_WARN (s, "put");
     774             :       /* Fatal (not transient) error, since retrying will not help
     775             :          (stream is too small to contain the desired data). */
     776             :       return -1;
     777             :     }
     778             : 
     779         417 :   if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
     780             :     {
     781         417 :       s->endp += nbytes;
     782         417 :       return nbytes;
     783             :     }
     784             :   /* Error: was it transient (return -2) or fatal (return -1)? */
     785           0 :   if (ERRNO_IO_RETRY(errno))
     786           0 :     return -2;
     787           0 :   zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
     788           0 :   return -1;
     789             : }
     790             : 
     791             : /* Read up to size bytes into the stream from the fd, using recvmsgfrom
     792             :  * whose arguments match the remaining arguments to this function
     793             :  */
     794             : ssize_t 
     795           0 : stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
     796             :                  struct sockaddr *from, socklen_t *fromlen)                     
     797             : {
     798             :   ssize_t nbytes;
     799             : 
     800           0 :   STREAM_VERIFY_SANE(s);
     801             :   
     802           0 :   if (STREAM_WRITEABLE(s) < size)
     803             :     {
     804           0 :       STREAM_BOUND_WARN (s, "put");
     805             :       /* Fatal (not transient) error, since retrying will not help
     806             :          (stream is too small to contain the desired data). */
     807             :       return -1;
     808             :     }
     809             : 
     810           0 :   if ((nbytes = recvfrom (fd, s->data + s->endp, size, 
     811             :                           flags, from, fromlen)) >= 0)
     812             :     {
     813           0 :       s->endp += nbytes;
     814           0 :       return nbytes;
     815             :     }
     816             :   /* Error: was it transient (return -2) or fatal (return -1)? */
     817           0 :   if (ERRNO_IO_RETRY(errno))
     818           0 :     return -2;
     819           0 :   zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
     820           0 :   return -1;
     821             : }
     822             : 
     823             : /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
     824             :  * from endp.
     825             :  * First iovec will be used to receive the data.
     826             :  * Stream need not be empty.
     827             :  */
     828             : ssize_t
     829           0 : stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, 
     830             :                 size_t size)
     831             : {
     832             :   int nbytes;
     833             :   struct iovec *iov;
     834             :   
     835           0 :   STREAM_VERIFY_SANE(s);
     836           0 :   assert (msgh->msg_iovlen > 0);  
     837             :   
     838           0 :   if (STREAM_WRITEABLE (s) < size)
     839             :     {
     840           0 :       STREAM_BOUND_WARN (s, "put");
     841             :       /* This is a logic error in the calling code: the stream is too small
     842             :          to hold the desired data! */
     843             :       return -1;
     844             :     }
     845             :   
     846           0 :   iov = &(msgh->msg_iov[0]);
     847           0 :   iov->iov_base = (s->data + s->endp);
     848           0 :   iov->iov_len = size;
     849             :   
     850           0 :   nbytes = recvmsg (fd, msgh, flags);
     851             :   
     852           0 :   if (nbytes > 0)
     853           0 :     s->endp += nbytes;
     854             :   
     855           0 :   return nbytes;
     856             : }
     857             :   
     858             : /* Write data to buffer. */
     859             : size_t
     860          80 : stream_write (struct stream *s, const void *ptr, size_t size)
     861             : {
     862             : 
     863          80 :   CHECK_SIZE(s, size);
     864             : 
     865          80 :   STREAM_VERIFY_SANE(s);
     866             :   
     867          80 :   if (STREAM_WRITEABLE (s) < size)
     868             :     {
     869           0 :       STREAM_BOUND_WARN (s, "put");
     870             :       return 0;
     871             :     }
     872             :   
     873          80 :   memcpy (s->data + s->endp, ptr, size);
     874          80 :   s->endp += size;
     875             : 
     876          80 :   return size;
     877             : }
     878             : 
     879             : /* Return current read pointer. 
     880             :  * DEPRECATED!
     881             :  * Use stream_get_pnt_to if you must, but decoding streams properly
     882             :  * is preferred
     883             :  */
     884             : u_char *
     885         302 : stream_pnt (struct stream *s)
     886             : {
     887         302 :   STREAM_VERIFY_SANE(s);
     888         302 :   return s->data + s->getp;
     889             : }
     890             : 
     891             : /* Check does this stream empty? */
     892             : int
     893           0 : stream_empty (struct stream *s)
     894             : {
     895           0 :   STREAM_VERIFY_SANE(s);
     896             : 
     897           0 :   return (s->endp == 0);
     898             : }
     899             : 
     900             : /* Reset stream. */
     901             : void
     902         391 : stream_reset (struct stream *s)
     903             : {
     904         391 :   STREAM_VERIFY_SANE (s);
     905             : 
     906         391 :   s->getp = s->endp = 0;
     907         391 : }
     908             : 
     909             : /* Write stream contens to the file discriptor. */
     910             : int
     911           0 : stream_flush (struct stream *s, int fd)
     912             : {
     913             :   int nbytes;
     914             :   
     915           0 :   STREAM_VERIFY_SANE(s);
     916             :   
     917           0 :   nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
     918             :   
     919           0 :   return nbytes;
     920             : }
     921             : 
     922             : /* Stream first in first out queue. */
     923             : 
     924             : struct stream_fifo *
     925          17 : stream_fifo_new (void)
     926             : {
     927             :   struct stream_fifo *new;
     928             :  
     929          17 :   new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
     930          17 :   return new;
     931             : }
     932             : 
     933             : /* Add new stream to fifo. */
     934             : void
     935          34 : stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
     936             : {
     937          34 :   if (fifo->tail)
     938           0 :     fifo->tail->next = s;
     939             :   else
     940          34 :     fifo->head = s;
     941             :      
     942          34 :   fifo->tail = s;
     943             : 
     944          34 :   fifo->count++;
     945          34 : }
     946             : 
     947             : /* Delete first stream from fifo. */
     948             : struct stream *
     949           0 : stream_fifo_pop (struct stream_fifo *fifo)
     950             : {
     951             :   struct stream *s;
     952             :   
     953           0 :   s = fifo->head; 
     954             : 
     955           0 :   if (s)
     956             :     { 
     957           0 :       fifo->head = s->next;
     958             : 
     959           0 :       if (fifo->head == NULL)
     960           0 :         fifo->tail = NULL;
     961             : 
     962           0 :       fifo->count--;
     963             :     }
     964             : 
     965           0 :   return s; 
     966             : }
     967             : 
     968             : /* Return first fifo entry. */
     969             : struct stream *
     970          34 : stream_fifo_head (struct stream_fifo *fifo)
     971             : {
     972          34 :   return fifo->head;
     973             : }
     974             : 
     975             : void
     976          34 : stream_fifo_clean (struct stream_fifo *fifo)
     977             : {
     978             :   struct stream *s;
     979             :   struct stream *next;
     980             : 
     981          57 :   for (s = fifo->head; s; s = next)
     982             :     {
     983          23 :       next = s->next;
     984          23 :       stream_free (s);
     985             :     }
     986          34 :   fifo->head = fifo->tail = NULL;
     987          34 :   fifo->count = 0;
     988          34 : }
     989             : 
     990             : void
     991           0 : stream_fifo_free (struct stream_fifo *fifo)
     992             : {
     993           0 :   stream_fifo_clean (fifo);
     994           0 :   XFREE (MTYPE_STREAM_FIFO, fifo);
     995           0 : }

Generated by: LCOV version 1.10