File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / stream.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (8 years ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    1:   /*
    2:  * Packet interface
    3:  * Copyright (C) 1999 Kunihiro Ishiguro
    4:  *
    5:  * This file is part of GNU Zebra.
    6:  *
    7:  * GNU Zebra is free software; you can redistribute it and/or modify it
    8:  * under the terms of the GNU General Public License as published by the
    9:  * Free Software Foundation; either version 2, or (at your option) any
   10:  * later version.
   11:  *
   12:  * GNU Zebra is distributed in the hope that it will be useful, but
   13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15:  * General Public License for more details.
   16:  *
   17:  * You should have received a copy of the GNU General Public License
   18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
   19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   20:  * 02111-1307, USA.  
   21:  */
   22: 
   23: #include <zebra.h>
   24: #include <stddef.h>
   25: 
   26: #include "stream.h"
   27: #include "memory.h"
   28: #include "network.h"
   29: #include "prefix.h"
   30: #include "log.h"
   31: 
   32: /* Tests whether a position is valid */ 
   33: #define GETP_VALID(S,G) \
   34:   ((G) <= (S)->endp)
   35: #define PUT_AT_VALID(S,G) GETP_VALID(S,G)
   36: #define ENDP_VALID(S,E) \
   37:   ((E) <= (S)->size)
   38: 
   39: /* asserting sanity checks. Following must be true before
   40:  * stream functions are called:
   41:  *
   42:  * Following must always be true of stream elements
   43:  * before and after calls to stream functions:
   44:  *
   45:  * getp <= endp <= size
   46:  *
   47:  * Note that after a stream function is called following may be true:
   48:  * if (getp == endp) then stream is no longer readable
   49:  * if (endp == size) then stream is no longer writeable
   50:  *
   51:  * It is valid to put to anywhere within the size of the stream, but only
   52:  * using stream_put..._at() functions.
   53:  */
   54: #define STREAM_WARN_OFFSETS(S) \
   55:   zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \
   56:              (void *)(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: 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: 
  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: }
  199: 
  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: 
  236: void
  237: stream_set_endp (struct stream *s, size_t pos)
  238: {
  239:   STREAM_VERIFY_SANE(s);
  240: 
  241:   if (!ENDP_VALID(s, pos))
  242:     {
  243:       STREAM_BOUND_WARN (s, "set endp");
  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;
  254:     }
  255: 
  256:   s->endp = pos;
  257:   STREAM_VERIFY_SANE(s);
  258: }
  259: 
  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: }
  288: 
  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: }
  495: 
  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:   
  722:   if (STREAM_WRITEABLE (s) < (psize + sizeof (u_char)))
  723:     {
  724:       STREAM_BOUND_WARN (s, "put");
  725:       return 0;
  726:     }
  727:   
  728:   s->data[s->endp++] = p->prefixlen;
  729:   memcpy (s->data + s->endp, &p->u.prefix, psize);
  730:   s->endp += psize;
  731:   
  732:   return psize;
  733: }
  734: 
  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: }
  914: 
  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: 
  955:       fifo->count--;
  956:     }
  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>