Annotation of embedaddon/quagga/lib/stream.c, revision 1.1.1.4

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>