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

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 <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) \
1.1.1.2   misho      55:   zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
1.1       misho      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: 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: 
                    157: size_t
                    158: stream_resize (struct stream *s, size_t newsize)
                    159: {
                    160:   u_char *newdata;
                    161:   STREAM_VERIFY_SANE (s);
                    162:   
                    163:   newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
                    164:   
                    165:   if (newdata == NULL)
                    166:     return s->size;
                    167:   
                    168:   s->data = newdata;
                    169:   s->size = newsize;
                    170:   
                    171:   if (s->endp > s->size)
                    172:     s->endp = s->size;
                    173:   if (s->getp > s->endp)
                    174:     s->getp = s->endp;
                    175:   
                    176:   STREAM_VERIFY_SANE (s);
                    177:   
                    178:   return s->size;
                    179: }
                    180: 
                    181: size_t
                    182: stream_get_getp (struct stream *s)
                    183: {
                    184:   STREAM_VERIFY_SANE(s);
                    185:   return s->getp;
                    186: }
                    187: 
                    188: size_t
                    189: stream_get_endp (struct stream *s)
                    190: {
                    191:   STREAM_VERIFY_SANE(s);
                    192:   return s->endp;
                    193: }
                    194: 
                    195: size_t
                    196: stream_get_size (struct stream *s)
                    197: {
                    198:   STREAM_VERIFY_SANE(s);
                    199:   return s->size;
                    200: }
                    201: 
                    202: /* Stream structre' stream pointer related functions.  */
                    203: void
                    204: stream_set_getp (struct stream *s, size_t pos)
                    205: {
                    206:   STREAM_VERIFY_SANE(s);
                    207:   
                    208:   if (!GETP_VALID (s, pos))
                    209:     {
                    210:       STREAM_BOUND_WARN (s, "set getp");
                    211:       pos = s->endp;
                    212:     }
                    213: 
                    214:   s->getp = pos;
                    215: }
                    216: 
1.1.1.2   misho     217: void
                    218: stream_set_endp (struct stream *s, size_t pos)
                    219: {
                    220:   STREAM_VERIFY_SANE(s);
                    221: 
1.1.1.3 ! misho     222:   if (!ENDP_VALID(s, pos))
1.1.1.2   misho     223:     {
                    224:       STREAM_BOUND_WARN (s, "set endp");
1.1.1.3 ! misho     225:       return;
        !           226:     }
        !           227: 
        !           228:   /*
        !           229:    * Make sure the current read pointer is not beyond the new endp.
        !           230:    */
        !           231:   if (s->getp > pos)
        !           232:     {
        !           233:       STREAM_BOUND_WARN(s, "set endp");
        !           234:       return;
1.1.1.2   misho     235:     }
                    236: 
                    237:   s->endp = pos;
1.1.1.3 ! misho     238:   STREAM_VERIFY_SANE(s);
1.1.1.2   misho     239: }
                    240: 
1.1       misho     241: /* Forward pointer. */
                    242: void
                    243: stream_forward_getp (struct stream *s, size_t size)
                    244: {
                    245:   STREAM_VERIFY_SANE(s);
                    246:   
                    247:   if (!GETP_VALID (s, s->getp + size))
                    248:     {
                    249:       STREAM_BOUND_WARN (s, "seek getp");
                    250:       return;
                    251:     }
                    252:   
                    253:   s->getp += size;
                    254: }
                    255: 
                    256: void
                    257: stream_forward_endp (struct stream *s, size_t size)
                    258: {
                    259:   STREAM_VERIFY_SANE(s);
                    260:   
                    261:   if (!ENDP_VALID (s, s->endp + size))
                    262:     {
                    263:       STREAM_BOUND_WARN (s, "seek endp");
                    264:       return;
                    265:     }
                    266:   
                    267:   s->endp += size;
                    268: }
                    269: 
                    270: /* Copy from stream to destination. */
                    271: void
                    272: stream_get (void *dst, struct stream *s, size_t size)
                    273: {
                    274:   STREAM_VERIFY_SANE(s);
                    275:   
                    276:   if (STREAM_READABLE(s) < size)
                    277:     {
                    278:       STREAM_BOUND_WARN (s, "get");
                    279:       return;
                    280:     }
                    281:   
                    282:   memcpy (dst, s->data + s->getp, size);
                    283:   s->getp += size;
                    284: }
                    285: 
                    286: /* Get next character from the stream. */
                    287: u_char
                    288: stream_getc (struct stream *s)
                    289: {
                    290:   u_char c;
                    291:   
                    292:   STREAM_VERIFY_SANE (s);
                    293: 
                    294:   if (STREAM_READABLE(s) < sizeof (u_char))
                    295:     {
                    296:       STREAM_BOUND_WARN (s, "get char");
                    297:       return 0;
                    298:     }
                    299:   c = s->data[s->getp++];
                    300:   
                    301:   return c;
                    302: }
                    303: 
                    304: /* Get next character from the stream. */
                    305: u_char
                    306: stream_getc_from (struct stream *s, size_t from)
                    307: {
                    308:   u_char c;
                    309: 
                    310:   STREAM_VERIFY_SANE(s);
                    311:   
                    312:   if (!GETP_VALID (s, from + sizeof (u_char)))
                    313:     {
                    314:       STREAM_BOUND_WARN (s, "get char");
                    315:       return 0;
                    316:     }
                    317:   
                    318:   c = s->data[from];
                    319:   
                    320:   return c;
                    321: }
                    322: 
                    323: /* Get next word from the stream. */
                    324: u_int16_t
                    325: stream_getw (struct stream *s)
                    326: {
                    327:   u_int16_t w;
                    328: 
                    329:   STREAM_VERIFY_SANE (s);
                    330: 
                    331:   if (STREAM_READABLE (s) < sizeof (u_int16_t))
                    332:     {
                    333:       STREAM_BOUND_WARN (s, "get ");
                    334:       return 0;
                    335:     }
                    336:   
                    337:   w = s->data[s->getp++] << 8;
                    338:   w |= s->data[s->getp++];
                    339:   
                    340:   return w;
                    341: }
                    342: 
                    343: /* Get next word from the stream. */
                    344: u_int16_t
                    345: stream_getw_from (struct stream *s, size_t from)
                    346: {
                    347:   u_int16_t w;
                    348: 
                    349:   STREAM_VERIFY_SANE(s);
                    350:   
                    351:   if (!GETP_VALID (s, from + sizeof (u_int16_t)))
                    352:     {
                    353:       STREAM_BOUND_WARN (s, "get ");
                    354:       return 0;
                    355:     }
                    356:   
                    357:   w = s->data[from++] << 8;
                    358:   w |= s->data[from];
                    359:   
                    360:   return w;
                    361: }
                    362: 
                    363: /* Get next long word from the stream. */
                    364: u_int32_t
                    365: stream_getl_from (struct stream *s, size_t from)
                    366: {
                    367:   u_int32_t l;
                    368: 
                    369:   STREAM_VERIFY_SANE(s);
                    370:   
                    371:   if (!GETP_VALID (s, from + sizeof (u_int32_t)))
                    372:     {
                    373:       STREAM_BOUND_WARN (s, "get long");
                    374:       return 0;
                    375:     }
                    376:   
                    377:   l  = s->data[from++] << 24;
                    378:   l |= s->data[from++] << 16;
                    379:   l |= s->data[from++] << 8;
                    380:   l |= s->data[from];
                    381:   
                    382:   return l;
                    383: }
                    384: 
                    385: u_int32_t
                    386: stream_getl (struct stream *s)
                    387: {
                    388:   u_int32_t l;
                    389: 
                    390:   STREAM_VERIFY_SANE(s);
                    391:   
                    392:   if (STREAM_READABLE (s) < sizeof (u_int32_t))
                    393:     {
                    394:       STREAM_BOUND_WARN (s, "get long");
                    395:       return 0;
                    396:     }
                    397:   
                    398:   l  = s->data[s->getp++] << 24;
                    399:   l |= s->data[s->getp++] << 16;
                    400:   l |= s->data[s->getp++] << 8;
                    401:   l |= s->data[s->getp++];
                    402:   
                    403:   return l;
                    404: }
                    405: 
                    406: /* Get next quad word from the stream. */
                    407: uint64_t
                    408: stream_getq_from (struct stream *s, size_t from)
                    409: {
                    410:   uint64_t q;
                    411: 
                    412:   STREAM_VERIFY_SANE(s);
                    413:   
                    414:   if (!GETP_VALID (s, from + sizeof (uint64_t)))
                    415:     {
                    416:       STREAM_BOUND_WARN (s, "get quad");
                    417:       return 0;
                    418:     }
                    419:   
                    420:   q  = ((uint64_t) s->data[from++]) << 56;
                    421:   q |= ((uint64_t) s->data[from++]) << 48;
                    422:   q |= ((uint64_t) s->data[from++]) << 40;
                    423:   q |= ((uint64_t) s->data[from++]) << 32;  
                    424:   q |= ((uint64_t) s->data[from++]) << 24;
                    425:   q |= ((uint64_t) s->data[from++]) << 16;
                    426:   q |= ((uint64_t) s->data[from++]) << 8;
                    427:   q |= ((uint64_t) s->data[from++]);
                    428:   
                    429:   return q;
                    430: }
                    431: 
                    432: uint64_t
                    433: stream_getq (struct stream *s)
                    434: {
                    435:   uint64_t q;
                    436: 
                    437:   STREAM_VERIFY_SANE(s);
                    438:   
                    439:   if (STREAM_READABLE (s) < sizeof (uint64_t))
                    440:     {
                    441:       STREAM_BOUND_WARN (s, "get quad");
                    442:       return 0;
                    443:     }
                    444:   
                    445:   q  = ((uint64_t) s->data[s->getp++]) << 56;
                    446:   q |= ((uint64_t) s->data[s->getp++]) << 48;
                    447:   q |= ((uint64_t) s->data[s->getp++]) << 40;
                    448:   q |= ((uint64_t) s->data[s->getp++]) << 32;  
                    449:   q |= ((uint64_t) s->data[s->getp++]) << 24;
                    450:   q |= ((uint64_t) s->data[s->getp++]) << 16;
                    451:   q |= ((uint64_t) s->data[s->getp++]) << 8;
                    452:   q |= ((uint64_t) s->data[s->getp++]);
                    453:   
                    454:   return q;
                    455: }
                    456: 
                    457: /* Get next long word from the stream. */
                    458: u_int32_t
                    459: stream_get_ipv4 (struct stream *s)
                    460: {
                    461:   u_int32_t l;
                    462: 
                    463:   STREAM_VERIFY_SANE(s);
                    464:   
                    465:   if (STREAM_READABLE (s) < sizeof(u_int32_t))
                    466:     {
                    467:       STREAM_BOUND_WARN (s, "get ipv4");
                    468:       return 0;
                    469:     }
                    470:   
                    471:   memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
                    472:   s->getp += sizeof(u_int32_t);
                    473: 
                    474:   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: 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:   CHECK_SIZE(s, size);
                    490:   
                    491:   STREAM_VERIFY_SANE(s);
                    492:   
                    493:   if (STREAM_WRITEABLE (s) < size)
                    494:     {
                    495:       STREAM_BOUND_WARN (s, "put");
                    496:       return;
                    497:     }
                    498:   
                    499:   if (src)
                    500:     memcpy (s->data + s->endp, src, size);
                    501:   else
                    502:     memset (s->data + s->endp, 0, size);
                    503: 
                    504:   s->endp += size;
                    505: }
                    506: 
                    507: /* Put character to the stream. */
                    508: int
                    509: stream_putc (struct stream *s, u_char c)
                    510: {
                    511:   STREAM_VERIFY_SANE(s);
                    512:   
                    513:   if (STREAM_WRITEABLE (s) < sizeof(u_char))
                    514:     {
                    515:       STREAM_BOUND_WARN (s, "put");
                    516:       return 0;
                    517:     }
                    518:   
                    519:   s->data[s->endp++] = c;
                    520:   return sizeof (u_char);
                    521: }
                    522: 
                    523: /* Put word to the stream. */
                    524: int
                    525: stream_putw (struct stream *s, u_int16_t w)
                    526: {
                    527:   STREAM_VERIFY_SANE (s);
                    528: 
                    529:   if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
                    530:     {
                    531:       STREAM_BOUND_WARN (s, "put");
                    532:       return 0;
                    533:     }
                    534:   
                    535:   s->data[s->endp++] = (u_char)(w >>  8);
                    536:   s->data[s->endp++] = (u_char) w;
                    537: 
                    538:   return 2;
                    539: }
                    540: 
                    541: /* Put long word to the stream. */
                    542: int
                    543: stream_putl (struct stream *s, u_int32_t l)
                    544: {
                    545:   STREAM_VERIFY_SANE (s);
                    546: 
                    547:   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
                    548:     {
                    549:       STREAM_BOUND_WARN (s, "put");
                    550:       return 0;
                    551:     }
                    552:   
                    553:   s->data[s->endp++] = (u_char)(l >> 24);
                    554:   s->data[s->endp++] = (u_char)(l >> 16);
                    555:   s->data[s->endp++] = (u_char)(l >>  8);
                    556:   s->data[s->endp++] = (u_char)l;
                    557: 
                    558:   return 4;
                    559: }
                    560: 
                    561: /* Put quad word to the stream. */
                    562: int
                    563: stream_putq (struct stream *s, uint64_t q)
                    564: {
                    565:   STREAM_VERIFY_SANE (s);
                    566: 
                    567:   if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
                    568:     {
                    569:       STREAM_BOUND_WARN (s, "put quad");
                    570:       return 0;
                    571:     }
                    572:   
                    573:   s->data[s->endp++] = (u_char)(q >> 56);
                    574:   s->data[s->endp++] = (u_char)(q >> 48);
                    575:   s->data[s->endp++] = (u_char)(q >> 40);
                    576:   s->data[s->endp++] = (u_char)(q >> 32);
                    577:   s->data[s->endp++] = (u_char)(q >> 24);
                    578:   s->data[s->endp++] = (u_char)(q >> 16);
                    579:   s->data[s->endp++] = (u_char)(q >>  8);
                    580:   s->data[s->endp++] = (u_char)q;
                    581: 
                    582:   return 8;
                    583: }
                    584: 
                    585: int
                    586: stream_putc_at (struct stream *s, size_t putp, u_char c)
                    587: {
                    588:   STREAM_VERIFY_SANE(s);
                    589:   
                    590:   if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
                    591:     {
                    592:       STREAM_BOUND_WARN (s, "put");
                    593:       return 0;
                    594:     }
                    595:   
                    596:   s->data[putp] = c;
                    597:   
                    598:   return 1;
                    599: }
                    600: 
                    601: int
                    602: stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
                    603: {
                    604:   STREAM_VERIFY_SANE(s);
                    605:   
                    606:   if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
                    607:     {
                    608:       STREAM_BOUND_WARN (s, "put");
                    609:       return 0;
                    610:     }
                    611:   
                    612:   s->data[putp] = (u_char)(w >>  8);
                    613:   s->data[putp + 1] = (u_char) w;
                    614:   
                    615:   return 2;
                    616: }
                    617: 
                    618: int
                    619: stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
                    620: {
                    621:   STREAM_VERIFY_SANE(s);
                    622:   
                    623:   if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
                    624:     {
                    625:       STREAM_BOUND_WARN (s, "put");
                    626:       return 0;
                    627:     }
                    628:   s->data[putp] = (u_char)(l >> 24);
                    629:   s->data[putp + 1] = (u_char)(l >> 16);
                    630:   s->data[putp + 2] = (u_char)(l >>  8);
                    631:   s->data[putp + 3] = (u_char)l;
                    632:   
                    633:   return 4;
                    634: }
                    635: 
                    636: int
                    637: stream_putq_at (struct stream *s, size_t putp, uint64_t q)
                    638: {
                    639:   STREAM_VERIFY_SANE(s);
                    640:   
                    641:   if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
                    642:     {
                    643:       STREAM_BOUND_WARN (s, "put");
                    644:       return 0;
                    645:     }
                    646:   s->data[putp] =     (u_char)(q >> 56);
                    647:   s->data[putp + 1] = (u_char)(q >> 48);
                    648:   s->data[putp + 2] = (u_char)(q >> 40);
                    649:   s->data[putp + 3] = (u_char)(q >> 32);
                    650:   s->data[putp + 4] = (u_char)(q >> 24);
                    651:   s->data[putp + 5] = (u_char)(q >> 16);
                    652:   s->data[putp + 6] = (u_char)(q >>  8);
                    653:   s->data[putp + 7] = (u_char)q;
                    654:   
                    655:   return 8;
                    656: }
                    657: 
                    658: /* Put long word to the stream. */
                    659: int
                    660: stream_put_ipv4 (struct stream *s, u_int32_t l)
                    661: {
                    662:   STREAM_VERIFY_SANE(s);
                    663:   
                    664:   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
                    665:     {
                    666:       STREAM_BOUND_WARN (s, "put");
                    667:       return 0;
                    668:     }
                    669:   memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
                    670:   s->endp += sizeof (u_int32_t);
                    671: 
                    672:   return sizeof (u_int32_t);
                    673: }
                    674: 
                    675: /* Put long word to the stream. */
                    676: int
                    677: stream_put_in_addr (struct stream *s, struct in_addr *addr)
                    678: {
                    679:   STREAM_VERIFY_SANE(s);
                    680:   
                    681:   if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
                    682:     {
                    683:       STREAM_BOUND_WARN (s, "put");
                    684:       return 0;
                    685:     }
                    686: 
                    687:   memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
                    688:   s->endp += sizeof (u_int32_t);
                    689: 
                    690:   return sizeof (u_int32_t);
                    691: }
                    692: 
                    693: /* Put prefix by nlri type format. */
                    694: int
                    695: stream_put_prefix (struct stream *s, struct prefix *p)
                    696: {
                    697:   size_t psize;
                    698:   
                    699:   STREAM_VERIFY_SANE(s);
                    700:   
                    701:   psize = PSIZE (p->prefixlen);
                    702:   
                    703:   if (STREAM_WRITEABLE (s) < psize)
                    704:     {
                    705:       STREAM_BOUND_WARN (s, "put");
                    706:       return 0;
                    707:     }
                    708:   
                    709:   stream_putc (s, p->prefixlen);
                    710:   memcpy (s->data + s->endp, &p->u.prefix, psize);
                    711:   s->endp += psize;
                    712:   
                    713:   return psize;
                    714: }
                    715: 
                    716: /* Read size from fd. */
                    717: int
                    718: stream_read (struct stream *s, int fd, size_t size)
                    719: {
                    720:   int nbytes;
                    721: 
                    722:   STREAM_VERIFY_SANE(s);
                    723:   
                    724:   if (STREAM_WRITEABLE (s) < size)
                    725:     {
                    726:       STREAM_BOUND_WARN (s, "put");
                    727:       return 0;
                    728:     }
                    729:   
                    730:   nbytes = readn (fd, s->data + s->endp, size);
                    731: 
                    732:   if (nbytes > 0)
                    733:     s->endp += nbytes;
                    734:   
                    735:   return nbytes;
                    736: }
                    737: 
                    738: /* Read size from fd. */
                    739: int
                    740: stream_read_unblock (struct stream *s, int fd, size_t size)
                    741: {
                    742:   int nbytes;
                    743:   int val;
                    744:   
                    745:   STREAM_VERIFY_SANE(s);
                    746:   
                    747:   if (STREAM_WRITEABLE (s) < size)
                    748:     {
                    749:       STREAM_BOUND_WARN (s, "put");
                    750:       return 0;
                    751:     }
                    752:   
                    753:   val = fcntl (fd, F_GETFL, 0);
                    754:   fcntl (fd, F_SETFL, val|O_NONBLOCK);
                    755:   nbytes = read (fd, s->data + s->endp, size);
                    756:   fcntl (fd, F_SETFL, val);
                    757: 
                    758:   if (nbytes > 0)
                    759:     s->endp += nbytes;
                    760:   
                    761:   return nbytes;
                    762: }
                    763: 
                    764: ssize_t
                    765: stream_read_try(struct stream *s, int fd, size_t size)
                    766: {
                    767:   ssize_t nbytes;
                    768: 
                    769:   STREAM_VERIFY_SANE(s);
                    770:   
                    771:   if (STREAM_WRITEABLE(s) < size)
                    772:     {
                    773:       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:   if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
                    780:     {
                    781:       s->endp += nbytes;
                    782:       return nbytes;
                    783:     }
                    784:   /* Error: was it transient (return -2) or fatal (return -1)? */
                    785:   if (ERRNO_IO_RETRY(errno))
                    786:     return -2;
                    787:   zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
                    788:   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: 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:   STREAM_VERIFY_SANE(s);
                    801:   
                    802:   if (STREAM_WRITEABLE(s) < size)
                    803:     {
                    804:       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:   if ((nbytes = recvfrom (fd, s->data + s->endp, size, 
                    811:                           flags, from, fromlen)) >= 0)
                    812:     {
                    813:       s->endp += nbytes;
                    814:       return nbytes;
                    815:     }
                    816:   /* Error: was it transient (return -2) or fatal (return -1)? */
                    817:   if (ERRNO_IO_RETRY(errno))
                    818:     return -2;
                    819:   zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
                    820:   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: 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:   STREAM_VERIFY_SANE(s);
                    836:   assert (msgh->msg_iovlen > 0);  
                    837:   
                    838:   if (STREAM_WRITEABLE (s) < size)
                    839:     {
                    840:       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:   iov = &(msgh->msg_iov[0]);
                    847:   iov->iov_base = (s->data + s->endp);
                    848:   iov->iov_len = size;
                    849:   
                    850:   nbytes = recvmsg (fd, msgh, flags);
                    851:   
                    852:   if (nbytes > 0)
                    853:     s->endp += nbytes;
                    854:   
                    855:   return nbytes;
                    856: }
                    857:   
                    858: /* Write data to buffer. */
                    859: size_t
                    860: stream_write (struct stream *s, const void *ptr, size_t size)
                    861: {
                    862: 
                    863:   CHECK_SIZE(s, size);
                    864: 
                    865:   STREAM_VERIFY_SANE(s);
                    866:   
                    867:   if (STREAM_WRITEABLE (s) < size)
                    868:     {
                    869:       STREAM_BOUND_WARN (s, "put");
                    870:       return 0;
                    871:     }
                    872:   
                    873:   memcpy (s->data + s->endp, ptr, size);
                    874:   s->endp += size;
                    875: 
                    876:   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: stream_pnt (struct stream *s)
                    886: {
                    887:   STREAM_VERIFY_SANE(s);
                    888:   return s->data + s->getp;
                    889: }
                    890: 
                    891: /* Check does this stream empty? */
                    892: int
                    893: stream_empty (struct stream *s)
                    894: {
                    895:   STREAM_VERIFY_SANE(s);
                    896: 
                    897:   return (s->endp == 0);
                    898: }
                    899: 
                    900: /* Reset stream. */
                    901: void
                    902: stream_reset (struct stream *s)
                    903: {
                    904:   STREAM_VERIFY_SANE (s);
                    905: 
                    906:   s->getp = s->endp = 0;
                    907: }
                    908: 
                    909: /* Write stream contens to the file discriptor. */
                    910: int
                    911: stream_flush (struct stream *s, int fd)
                    912: {
                    913:   int nbytes;
                    914:   
                    915:   STREAM_VERIFY_SANE(s);
                    916:   
                    917:   nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
                    918:   
                    919:   return nbytes;
                    920: }
                    921: 
                    922: /* Stream first in first out queue. */
                    923: 
                    924: struct stream_fifo *
                    925: stream_fifo_new (void)
                    926: {
                    927:   struct stream_fifo *new;
                    928:  
                    929:   new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
                    930:   return new;
                    931: }
                    932: 
                    933: /* Add new stream to fifo. */
                    934: void
                    935: stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
                    936: {
                    937:   if (fifo->tail)
                    938:     fifo->tail->next = s;
                    939:   else
                    940:     fifo->head = s;
                    941:      
                    942:   fifo->tail = s;
                    943: 
                    944:   fifo->count++;
                    945: }
                    946: 
                    947: /* Delete first stream from fifo. */
                    948: struct stream *
                    949: stream_fifo_pop (struct stream_fifo *fifo)
                    950: {
                    951:   struct stream *s;
                    952:   
                    953:   s = fifo->head; 
                    954: 
                    955:   if (s)
                    956:     { 
                    957:       fifo->head = s->next;
                    958: 
                    959:       if (fifo->head == NULL)
                    960:        fifo->tail = NULL;
                    961: 
1.1.1.2   misho     962:       fifo->count--;
                    963:     }
1.1       misho     964: 
                    965:   return s; 
                    966: }
                    967: 
                    968: /* Return first fifo entry. */
                    969: struct stream *
                    970: stream_fifo_head (struct stream_fifo *fifo)
                    971: {
                    972:   return fifo->head;
                    973: }
                    974: 
                    975: void
                    976: stream_fifo_clean (struct stream_fifo *fifo)
                    977: {
                    978:   struct stream *s;
                    979:   struct stream *next;
                    980: 
                    981:   for (s = fifo->head; s; s = next)
                    982:     {
                    983:       next = s->next;
                    984:       stream_free (s);
                    985:     }
                    986:   fifo->head = fifo->tail = NULL;
                    987:   fifo->count = 0;
                    988: }
                    989: 
                    990: void
                    991: stream_fifo_free (struct stream_fifo *fifo)
                    992: {
                    993:   stream_fifo_clean (fifo);
                    994:   XFREE (MTYPE_STREAM_FIFO, fifo);
                    995: }

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