back to topotato report
topotato coverage report
Current view: top level - lib - stream.h (source / functions) Hit Total Coverage
Test: test_bgp_extended_optional_parameters_length.py::BGPExtendedOptionalParametersLength Lines: 0 16 0.0 %
Date: 2023-02-24 18:37:23 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Packet interface
       3             :  * Copyright (C) 1999 Kunihiro Ishiguro
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #ifndef _ZEBRA_STREAM_H
      23             : #define _ZEBRA_STREAM_H
      24             : 
      25             : #include <pthread.h>
      26             : 
      27             : #include "frratomic.h"
      28             : #include "mpls.h"
      29             : #include "prefix.h"
      30             : 
      31             : #ifdef __cplusplus
      32             : extern "C" {
      33             : #endif
      34             : 
      35             : /*
      36             :  * A stream is an arbitrary buffer, whose contents generally are assumed to
      37             :  * be in network order.
      38             :  *
      39             :  * A stream has the following attributes associated with it:
      40             :  *
      41             :  * - size: the allocated, invariant size of the buffer.
      42             :  *
      43             :  * - getp: the get position marker, denoting the offset in the stream where
      44             :  *         the next read (or 'get') will be from. This getp marker is
      45             :  *         automatically adjusted when data is read from the stream, the
      46             :  *         user may also manipulate this offset as they wish, within limits
      47             :  *         (see below)
      48             :  *
      49             :  * - endp: the end position marker, denoting the offset in the stream where
      50             :  *         valid data ends, and if the user attempted to write (or
      51             :  *         'put') data where that data would be written (or 'put') to.
      52             :  *
      53             :  * These attributes are all size_t values.
      54             :  *
      55             :  * Constraints:
      56             :  *
      57             :  * 1. getp can never exceed endp
      58             :  *
      59             :  * - hence if getp is equal to endp, there is no more valid data that can be
      60             :  *   gotten from the stream (though, the user may reposition getp to earlier in
      61             :  *   the stream, if they wish).
      62             :  *
      63             :  * 2. endp can never exceed size
      64             :  *
      65             :  * - hence, if endp is equal to size, then the stream is full, and no more
      66             :  *   data can be written to the stream.
      67             :  *
      68             :  * In other words the following must always be true, and the stream
      69             :  * abstraction is allowed internally to assert that the following property
      70             :  * holds true for a stream, as and when it wishes:
      71             :  *
      72             :  *        getp <= endp <= size
      73             :  *
      74             :  * It is the users responsibility to ensure this property is never violated.
      75             :  *
      76             :  * A stream therefore can be thought of like this:
      77             :  *
      78             :  *      ---------------------------------------------------
      79             :  *      |XXXXXXXXXXXXXXXXXXXXXXXX                         |
      80             :  *      ---------------------------------------------------
      81             :  *               ^               ^                        ^
      82             :  *               getp            endp                     size
      83             :  *
      84             :  * This shows a stream containing data (shown as 'X') up to the endp offset.
      85             :  * The stream is empty from endp to size. Without adjusting getp, there are
      86             :  * still endp-getp bytes of valid data to be read from the stream.
      87             :  *
      88             :  * Methods are provided to get and put to/from the stream, as well as
      89             :  * retrieve the values of the 3 markers and manipulate the getp marker.
      90             :  *
      91             :  * Note:
      92             :  * At the moment, newly allocated streams are zero filled. Hence, one can
      93             :  * use stream_forward_endp() to effectively create arbitrary zero-fill
      94             :  * padding. However, note that stream_reset() does *not* zero-out the
      95             :  * stream. This property should **not** be relied upon.
      96             :  *
      97             :  * Best practice is to use stream_put (<stream *>, NULL, <size>) to zero out
      98             :  * any part of a stream which isn't otherwise written to.
      99             :  */
     100             : 
     101             : /* Stream buffer. */
     102             : struct stream {
     103             :         struct stream *next;
     104             : 
     105             :         /*
     106             :          * Remainder is ***private*** to stream
     107             :          * direct access is frowned upon!
     108             :          * Use the appropriate functions/macros
     109             :          */
     110             :         size_t getp;           /* next get position */
     111             :         size_t endp;           /* last valid data position */
     112             :         size_t size;           /* size of data segment */
     113             :         unsigned char data[];  /* data pointer */
     114             : };
     115             : 
     116             : /* First in first out queue structure. */
     117             : struct stream_fifo {
     118             :         /* lock for mt-safe operations */
     119             :         pthread_mutex_t mtx;
     120             : 
     121             :         /* number of streams in this fifo */
     122             :         atomic_size_t count;
     123             : #if defined DEV_BUILD
     124             :         atomic_size_t max_count;
     125             : #endif
     126             : 
     127             :         struct stream *head;
     128             :         struct stream *tail;
     129             : };
     130             : 
     131             : /* Utility macros. */
     132             : #define STREAM_SIZE(S)  ((S)->size)
     133             : /* number of bytes which can still be written */
     134             : #define STREAM_WRITEABLE(S) ((S)->size - (S)->endp)
     135             : /* number of bytes still to be read */
     136             : #define STREAM_READABLE(S) ((S)->endp - (S)->getp)
     137             : 
     138             : #define STREAM_CONCAT_REMAIN(S1, S2, size) ((size) - (S1)->endp - (S2)->endp)
     139             : 
     140             : /* this macro is deprecated, but not slated for removal anytime soon */
     141             : #define STREAM_DATA(S)  ((S)->data)
     142             : 
     143             : /* Stream prototypes.
     144             :  * For stream_{put,get}S, the S suffix mean:
     145             :  *
     146             :  * c: character (unsigned byte)
     147             :  * w: word (two bytes)
     148             :  * l: long (two words)
     149             :  * q: quad (four words)
     150             :  */
     151             : extern struct stream *stream_new(size_t);
     152             : extern void stream_free(struct stream *);
     153             : /* Copy 'src' into 'dest', returns 'dest' */
     154             : extern struct stream *stream_copy(struct stream *dest,
     155             :                                   const struct stream *src);
     156             : extern struct stream *stream_dup(const struct stream *s);
     157             : 
     158             : extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
     159             : 
     160             : extern size_t stream_get_getp(const struct stream *s);
     161             : extern size_t stream_get_endp(const struct stream *s);
     162             : extern size_t stream_get_size(const struct stream *s);
     163             : 
     164             : /**
     165             :  * Create a new stream structure; copy offset bytes from s1 to the new
     166             :  * stream; copy s2 data to the new stream; copy rest of s1 data to the
     167             :  * new stream.
     168             :  */
     169             : extern struct stream *stream_dupcat(const struct stream *s1,
     170             :                                     const struct stream *s2, size_t offset);
     171             : 
     172             : extern void stream_set_getp(struct stream *, size_t);
     173             : extern void stream_set_endp(struct stream *, size_t);
     174             : extern void stream_forward_getp(struct stream *, size_t);
     175             : extern bool stream_forward_getp2(struct stream *, size_t);
     176             : extern void stream_rewind_getp(struct stream *s, size_t size);
     177             : extern bool stream_rewind_getp2(struct stream *s, size_t size);
     178             : extern void stream_forward_endp(struct stream *, size_t);
     179             : extern bool stream_forward_endp2(struct stream *, size_t);
     180             : 
     181             : /* steam_put: NULL source zeroes out size_t bytes of stream */
     182             : extern void stream_put(struct stream *, const void *, size_t);
     183             : extern int stream_putc(struct stream *, uint8_t);
     184             : extern int stream_putc_at(struct stream *, size_t, uint8_t);
     185             : extern int stream_putw(struct stream *, uint16_t);
     186             : extern int stream_putw_at(struct stream *, size_t, uint16_t);
     187             : extern int stream_put3(struct stream *, uint32_t);
     188             : extern int stream_put3_at(struct stream *, size_t, uint32_t);
     189             : extern int stream_putl(struct stream *, uint32_t);
     190             : extern int stream_putl_at(struct stream *, size_t, uint32_t);
     191             : extern int stream_putq(struct stream *, uint64_t);
     192             : extern int stream_putq_at(struct stream *, size_t, uint64_t);
     193             : extern int stream_put_ipv4(struct stream *, uint32_t);
     194             : extern int stream_put_in_addr(struct stream *s, const struct in_addr *addr);
     195             : extern bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip);
     196             : extern int stream_put_in_addr_at(struct stream *s, size_t putp,
     197             :                                  const struct in_addr *addr);
     198             : extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
     199             :                                   const struct in6_addr *addr);
     200             : extern int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
     201             :                                      bool addpath_capable,
     202             :                                      uint32_t addpath_tx_id);
     203             : extern int stream_put_prefix(struct stream *s, const struct prefix *p);
     204             : extern int stream_put_labeled_prefix(struct stream *, const struct prefix *,
     205             :                                      mpls_label_t *, bool addpath_capable,
     206             :                                      uint32_t addpath_tx_id);
     207             : extern void stream_get(void *, struct stream *, size_t);
     208             : extern bool stream_get2(void *data, struct stream *s, size_t size);
     209             : extern void stream_get_from(void *, struct stream *, size_t, size_t);
     210             : extern uint8_t stream_getc(struct stream *);
     211             : extern bool stream_getc2(struct stream *s, uint8_t *byte);
     212             : extern uint8_t stream_getc_from(struct stream *, size_t);
     213             : extern uint16_t stream_getw(struct stream *);
     214             : extern bool stream_getw2(struct stream *s, uint16_t *word);
     215             : extern uint16_t stream_getw_from(struct stream *, size_t);
     216             : extern uint32_t stream_get3(struct stream *);
     217             : extern uint32_t stream_get3_from(struct stream *, size_t);
     218             : extern uint32_t stream_getl(struct stream *);
     219             : extern bool stream_getl2(struct stream *s, uint32_t *l);
     220             : extern uint32_t stream_getl_from(struct stream *, size_t);
     221             : extern uint64_t stream_getq(struct stream *);
     222             : extern uint64_t stream_getq_from(struct stream *, size_t);
     223             : bool stream_getq2(struct stream *s, uint64_t *q);
     224             : extern uint32_t stream_get_ipv4(struct stream *);
     225             : extern bool stream_get_ipaddr(struct stream *s, struct ipaddr *ip);
     226             : 
     227             : /* IEEE-754 floats */
     228             : extern float stream_getf(struct stream *);
     229             : extern double stream_getd(struct stream *);
     230             : extern int stream_putf(struct stream *, float);
     231             : extern int stream_putd(struct stream *, double);
     232             : 
     233             : #undef stream_read
     234             : #undef stream_write
     235             : 
     236             : /* Deprecated: assumes blocking I/O.  Will be removed.
     237             :    Use stream_read_try instead.  */
     238             : extern int stream_read(struct stream *, int, size_t);
     239             : 
     240             : /* Read up to size bytes into the stream.
     241             :    Return code:
     242             :      >0: number of bytes read
     243             :      0: end-of-file
     244             :      -1: fatal error
     245             :      -2: transient error, should retry later (i.e. EAGAIN or EINTR)
     246             :    This is suitable for use with non-blocking file descriptors.
     247             :  */
     248             : extern ssize_t stream_read_try(struct stream *s, int fd, size_t size);
     249             : 
     250             : extern ssize_t stream_recvmsg(struct stream *s, int fd, struct msghdr *,
     251             :                               int flags, size_t size);
     252             : extern ssize_t stream_recvfrom(struct stream *s, int fd, size_t len, int flags,
     253             :                                struct sockaddr *from, socklen_t *fromlen);
     254             : extern size_t stream_write(struct stream *, const void *, size_t);
     255             : 
     256             : /* reset the stream. See Note above */
     257             : extern void stream_reset(struct stream *);
     258             : extern int stream_flush(struct stream *, int);
     259             : extern int stream_empty(struct stream *); /* is the stream empty? */
     260             : 
     261             : /* debugging */
     262             : extern void stream_hexdump(const struct stream *s);
     263             : 
     264             : /**
     265             :  * Reorganize the buffer data so it can fit more. This function is normally
     266             :  * called right after stream data is consumed so we can read more data
     267             :  * (the functions that consume data start with `stream_get*()` and macros
     268             :  * `STREAM_GET*()`).
     269             :  *
     270             :  * \param s stream pointer.
     271             :  */
     272             : extern void stream_pulldown(struct stream *s);
     273             : 
     274             : /* deprecated */
     275             : extern uint8_t *stream_pnt(struct stream *);
     276             : 
     277             : /*
     278             :  * Operations on struct stream_fifo.
     279             :  *
     280             :  * Each function has a safe variant, which ensures that the operation performed
     281             :  * is atomic with respect to the operations performed by all other safe
     282             :  * variants. In other words, the safe variants lock the stream_fifo's mutex
     283             :  * before performing their action. These are provided for convenience when
     284             :  * using stream_fifo in a multithreaded context, to alleviate the need for the
     285             :  * caller to implement their own synchronization around the stream_fifo.
     286             :  *
     287             :  * The following functions do not have safe variants. The caller must ensure
     288             :  * that these operations are performed safely in a multithreaded context:
     289             :  * - stream_fifo_new
     290             :  * - stream_fifo_free
     291             :  */
     292             : 
     293             : /*
     294             :  * Create a new stream_fifo.
     295             :  *
     296             :  * Returns:
     297             :  *    newly created stream_fifo
     298             :  */
     299             : extern struct stream_fifo *stream_fifo_new(void);
     300             : 
     301             : /*
     302             :  * Init or re-init an on-stack fifo. This allows use of a fifo struct without
     303             :  * requiring a malloc/free cycle.
     304             :  * Note well that the fifo must be de-inited with the 'fifo_deinit' api.
     305             :  */
     306             : void stream_fifo_init(struct stream_fifo *fifo);
     307             : 
     308             : /*
     309             :  * Deinit an on-stack fifo.
     310             :  */
     311             : void stream_fifo_deinit(struct stream_fifo *fifo);
     312             : 
     313             : /*
     314             :  * Push a stream onto a stream_fifo.
     315             :  *
     316             :  * fifo
     317             :  *    the stream_fifo to push onto
     318             :  *
     319             :  * s
     320             :  *    the stream to push onto the stream_fifo
     321             :  */
     322             : extern void stream_fifo_push(struct stream_fifo *fifo, struct stream *s);
     323             : extern void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s);
     324             : 
     325             : /*
     326             :  * Pop a stream off a stream_fifo.
     327             :  *
     328             :  * fifo
     329             :  *    the stream_fifo to pop from
     330             :  *
     331             :  * Returns:
     332             :  *    the next stream in the stream_fifo
     333             :  */
     334             : extern struct stream *stream_fifo_pop(struct stream_fifo *fifo);
     335             : extern struct stream *stream_fifo_pop_safe(struct stream_fifo *fifo);
     336             : 
     337             : /*
     338             :  * Retrieve the next stream from a stream_fifo without popping it.
     339             :  *
     340             :  * fifo
     341             :  *    the stream_fifo to operate on
     342             :  *
     343             :  * Returns:
     344             :  *    the next stream that would be returned from stream_fifo_pop
     345             :  */
     346             : extern struct stream *stream_fifo_head(struct stream_fifo *fifo);
     347             : extern struct stream *stream_fifo_head_safe(struct stream_fifo *fifo);
     348             : 
     349             : /*
     350             :  * Remove all streams from a stream_fifo.
     351             :  *
     352             :  * fifo
     353             :  *    the stream_fifo to clean
     354             :  */
     355             : extern void stream_fifo_clean(struct stream_fifo *fifo);
     356             : extern void stream_fifo_clean_safe(struct stream_fifo *fifo);
     357             : 
     358             : /*
     359             :  * Retrieve number of streams on a stream_fifo.
     360             :  *
     361             :  * fifo
     362             :  *    the stream_fifo to retrieve the count for
     363             :  *
     364             :  * Returns:
     365             :  *    the number of streams on the stream_fifo
     366             :  */
     367             : extern size_t stream_fifo_count_safe(struct stream_fifo *fifo);
     368             : 
     369             : /*
     370             :  * Free a stream_fifo.
     371             :  *
     372             :  * Calls stream_fifo_clean, then deinitializes the stream_fifo and frees it.
     373             :  *
     374             :  * fifo
     375             :  *    the stream_fifo to free
     376             :  */
     377             : extern void stream_fifo_free(struct stream_fifo *fifo);
     378             : 
     379             : /* This is here because "<< 24" is particularly problematic in C.
     380             :  * This is because the left operand of << is integer-promoted, which means
     381             :  * an uint8_t gets converted into a *signed* int.  Shifting into the sign
     382             :  * bit of a signed int is theoretically undefined behaviour, so - the left
     383             :  * operand needs to be cast to unsigned.
     384             :  *
     385             :  * This is not a problem for 16- or 8-bit values (they don't reach the sign
     386             :  * bit), for 64-bit values (you need to cast them anyway), and neither for
     387             :  * encoding (because it's downcasted.)
     388             :  */
     389           0 : static inline const uint8_t *ptr_get_be64(const uint8_t *ptr, uint64_t *out)
     390             : {
     391           0 :         uint32_t tmp1, tmp2;
     392             : 
     393           0 :         memcpy(&tmp1, ptr, sizeof(tmp1));
     394           0 :         memcpy(&tmp2, ptr + sizeof(tmp1), sizeof(tmp1));
     395             : 
     396           0 :         *out = (((uint64_t)ntohl(tmp1)) << 32) | ntohl(tmp2);
     397             : 
     398           0 :         return ptr + 8;
     399             : }
     400             : 
     401           0 : static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out)
     402             : {
     403           0 :         uint32_t tmp;
     404             : 
     405           0 :         memcpy(&tmp, ptr, sizeof(tmp));
     406           0 :         *out = ntohl(tmp);
     407           0 :         return ptr + 4;
     408             : }
     409             : 
     410           0 : static inline uint8_t *ptr_get_be16(uint8_t *ptr, uint16_t *out)
     411             : {
     412           0 :         uint16_t tmp;
     413             : 
     414           0 :         memcpy(&tmp, ptr, sizeof(tmp));
     415           0 :         *out = ntohs(tmp);
     416             : 
     417           0 :         return ptr + 2;
     418             : }
     419             : 
     420             : /*
     421             :  * so Normal stream_getX functions assert.  Which is anathema
     422             :  * to keeping a daemon up and running when something goes south
     423             :  * Provide a stream_getX2 functions that do not assert.
     424             :  * In addition provide these macro's that upon failure
     425             :  * goto stream_failure.  This is modeled upon some NL_XX
     426             :  * macros in the linux kernel.
     427             :  *
     428             :  * This change allows for proper memory freeing
     429             :  * after we've detected an error.
     430             :  *
     431             :  * In the future we will be removing the assert in
     432             :  * the stream functions but we need a transition
     433             :  * plan.
     434             :  */
     435             : #define STREAM_GETC(S, P)                                                      \
     436             :         do {                                                                   \
     437             :                 uint8_t _pval;                                                 \
     438             :                 if (!stream_getc2((S), &_pval))                                \
     439             :                         goto stream_failure;                                   \
     440             :                 (P) = _pval;                                                   \
     441             :         } while (0)
     442             : 
     443             : #define STREAM_GETW(S, P)                                                      \
     444             :         do {                                                                   \
     445             :                 uint16_t _pval;                                                \
     446             :                 if (!stream_getw2((S), &_pval))                                \
     447             :                         goto stream_failure;                                   \
     448             :                 (P) = _pval;                                                   \
     449             :         } while (0)
     450             : 
     451             : #define STREAM_GETL(S, P)                                                      \
     452             :         do {                                                                   \
     453             :                 uint32_t _pval;                                                \
     454             :                 if (!stream_getl2((S), &_pval))                                \
     455             :                         goto stream_failure;                                   \
     456             :                 (P) = _pval;                                                   \
     457             :         } while (0)
     458             : 
     459             : #define STREAM_GETF(S, P)                                                      \
     460             :         do {                                                                   \
     461             :                 union {                                                        \
     462             :                         float r;                                               \
     463             :                         uint32_t d;                                            \
     464             :                 } _pval;                                                       \
     465             :                 if (!stream_getl2((S), &_pval.d))                              \
     466             :                         goto stream_failure;                                   \
     467             :                 (P) = _pval.r;                                                 \
     468             :         } while (0)
     469             : 
     470             : #define STREAM_GETQ(S, P)                                                      \
     471             :         do {                                                                   \
     472             :                 uint64_t _pval;                                                \
     473             :                 if (!stream_getq2((S), &_pval))                                \
     474             :                         goto stream_failure;                                   \
     475             :                 (P) = _pval;                                                   \
     476             :         } while (0)
     477             : 
     478             : #define STREAM_GET_IPADDR(S, P)                                                \
     479             :         do {                                                                   \
     480             :                 if (!stream_get_ipaddr((S), (P)))                              \
     481             :                         goto stream_failure;                                   \
     482             :         } while (0)
     483             : 
     484             : #define STREAM_GET(P, STR, SIZE)                                               \
     485             :         do {                                                                   \
     486             :                 if (!stream_get2((P), (STR), (SIZE)))                          \
     487             :                         goto stream_failure;                                   \
     488             :         } while (0)
     489             : 
     490             : #define STREAM_FORWARD_GETP(STR, SIZE)                                         \
     491             :         do {                                                                   \
     492             :                 if (!stream_forward_getp2((STR), (SIZE)))                      \
     493             :                         goto stream_failure;                                   \
     494             :         } while (0)
     495             : 
     496             : #define STREAM_REWIND_GETP(STR, SIZE)                                          \
     497             :         do {                                                                   \
     498             :                 if (!stream_rewind_getp2((STR), (SIZE)))                       \
     499             :                         goto stream_failure;                                   \
     500             :         } while (0)
     501             : 
     502             : #define STREAM_FORWARD_ENDP(STR, SIZE)                                         \
     503             :         do {                                                                   \
     504             :                 if (!stream_forward_endp2((STR), (SIZE)))                      \
     505             :                         goto stream_failure;                                   \
     506             :         } while (0)
     507             : 
     508             : #ifdef __cplusplus
     509             : }
     510             : #endif
     511             : 
     512             : #endif /* _ZEBRA_STREAM_H */

Generated by: LCOV version v1.16-topotato