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

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

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