back to topotato report
topotato coverage report
Current view: top level - lib - imsg-buffer.c (source / functions) Hit Total Coverage
Test: test_bgp_rmap_extcommunity_none.py::TestBGPExtCommunity Lines: 0 147 0.0 %
Date: 2023-02-24 18:37:31 Functions: 0 16 0.0 %

          Line data    Source code
       1             : /*      $OpenBSD$       */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <zebra.h>
      20             : 
      21             : #include "queue.h"
      22             : #include "imsg.h"
      23             : 
      24             : static int ibuf_realloc(struct ibuf *, size_t);
      25             : static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
      26             : static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
      27             : 
      28           0 : struct ibuf *ibuf_open(size_t len)
      29             : {
      30           0 :         struct ibuf *buf;
      31             : 
      32           0 :         if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
      33             :                 return NULL;
      34           0 :         if ((buf->buf = malloc(len)) == NULL) {
      35           0 :                 free(buf);
      36           0 :                 return NULL;
      37             :         }
      38           0 :         buf->size = buf->max = len;
      39           0 :         buf->fd = -1;
      40             : 
      41           0 :         return (buf);
      42             : }
      43             : 
      44           0 : struct ibuf *ibuf_dynamic(size_t len, size_t max)
      45             : {
      46           0 :         struct ibuf *buf;
      47             : 
      48           0 :         if (max < len)
      49             :                 return NULL;
      50             : 
      51           0 :         if ((buf = ibuf_open(len)) == NULL)
      52             :                 return NULL;
      53             : 
      54           0 :         if (max > 0)
      55           0 :                 buf->max = max;
      56             : 
      57             :         return (buf);
      58             : }
      59             : 
      60           0 : static int ibuf_realloc(struct ibuf *buf, size_t len)
      61             : {
      62           0 :         uint8_t *b;
      63             : 
      64             :         /* on static buffers max is eq size and so the following fails */
      65           0 :         if (buf->wpos + len > buf->max) {
      66           0 :                 errno = ERANGE;
      67           0 :                 return -1;
      68             :         }
      69             : 
      70           0 :         b = realloc(buf->buf, buf->wpos + len);
      71           0 :         if (b == NULL)
      72             :                 return -1;
      73           0 :         buf->buf = b;
      74           0 :         buf->size = buf->wpos + len;
      75             : 
      76           0 :         return 0;
      77             : }
      78             : 
      79           0 : int ibuf_add(struct ibuf *buf, const void *data, size_t len)
      80             : {
      81           0 :         if (buf->wpos + len > buf->size)
      82           0 :                 if (ibuf_realloc(buf, len) == -1)
      83             :                         return -1;
      84             : 
      85           0 :         memcpy(buf->buf + buf->wpos, data, len);
      86           0 :         buf->wpos += len;
      87           0 :         return 0;
      88             : }
      89             : 
      90           0 : void *ibuf_reserve(struct ibuf *buf, size_t len)
      91             : {
      92           0 :         void *b;
      93             : 
      94           0 :         if (buf->wpos + len > buf->size)
      95           0 :                 if (ibuf_realloc(buf, len) == -1)
      96             :                         return NULL;
      97             : 
      98           0 :         b = buf->buf + buf->wpos;
      99           0 :         buf->wpos += len;
     100           0 :         return (b);
     101             : }
     102             : 
     103           0 : void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
     104             : {
     105             :         /* only allowed to seek in already written parts */
     106           0 :         if (pos + len > buf->wpos)
     107             :                 return NULL;
     108             : 
     109           0 :         return (buf->buf + pos);
     110             : }
     111             : 
     112           0 : size_t ibuf_size(struct ibuf *buf)
     113             : {
     114           0 :         return (buf->wpos);
     115             : }
     116             : 
     117           0 : size_t ibuf_left(struct ibuf *buf)
     118             : {
     119           0 :         return (buf->max - buf->wpos);
     120             : }
     121             : 
     122           0 : void ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
     123             : {
     124           0 :         ibuf_enqueue(msgbuf, buf);
     125           0 : }
     126             : 
     127           0 : int ibuf_write(struct msgbuf *msgbuf)
     128             : {
     129           0 :         struct iovec iov[IOV_MAX];
     130           0 :         struct ibuf *buf;
     131           0 :         unsigned int i = 0;
     132           0 :         ssize_t n;
     133             : 
     134           0 :         memset(&iov, 0, sizeof(iov));
     135           0 :         TAILQ_FOREACH (buf, &msgbuf->bufs, entry) {
     136           0 :                 if (i >= IOV_MAX)
     137             :                         break;
     138           0 :                 iov[i].iov_base = buf->buf + buf->rpos;
     139           0 :                 iov[i].iov_len = buf->wpos - buf->rpos;
     140           0 :                 i++;
     141             :         }
     142             : 
     143           0 : again:
     144           0 :         if ((n = writev(msgbuf->fd, iov, i)) == -1) {
     145           0 :                 if (errno == EINTR)
     146           0 :                         goto again;
     147           0 :                 if (errno == ENOBUFS)
     148           0 :                         errno = EAGAIN;
     149           0 :                 return -1;
     150             :         }
     151             : 
     152           0 :         if (n == 0) { /* connection closed */
     153           0 :                 errno = 0;
     154           0 :                 return 0;
     155             :         }
     156             : 
     157           0 :         msgbuf_drain(msgbuf, n);
     158             : 
     159           0 :         return 1;
     160             : }
     161             : 
     162           0 : void ibuf_free(struct ibuf *buf)
     163             : {
     164           0 :         if (buf == NULL)
     165             :                 return;
     166           0 :         free(buf->buf);
     167           0 :         free(buf);
     168             : }
     169             : 
     170           0 : void msgbuf_init(struct msgbuf *msgbuf)
     171             : {
     172           0 :         msgbuf->queued = 0;
     173           0 :         msgbuf->fd = -1;
     174           0 :         TAILQ_INIT(&msgbuf->bufs);
     175           0 : }
     176             : 
     177           0 : void msgbuf_drain(struct msgbuf *msgbuf, size_t n)
     178             : {
     179           0 :         struct ibuf *buf, *next;
     180             : 
     181           0 :         for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
     182             :              buf = next) {
     183           0 :                 next = TAILQ_NEXT(buf, entry);
     184           0 :                 if (buf->rpos + n >= buf->wpos) {
     185           0 :                         n -= buf->wpos - buf->rpos;
     186             : 
     187           0 :                         TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
     188           0 :                         ibuf_dequeue(msgbuf, buf);
     189             :                 } else {
     190           0 :                         buf->rpos += n;
     191           0 :                         n = 0;
     192             :                 }
     193             :         }
     194           0 : }
     195             : 
     196           0 : void msgbuf_clear(struct msgbuf *msgbuf)
     197             : {
     198           0 :         struct ibuf *buf;
     199             : 
     200           0 :         while ((buf = TAILQ_POP_FIRST(&msgbuf->bufs, entry)) != NULL)
     201           0 :                 ibuf_dequeue(msgbuf, buf);
     202           0 : }
     203             : 
     204           0 : int msgbuf_write(struct msgbuf *msgbuf)
     205             : {
     206           0 :         struct iovec iov[IOV_MAX];
     207           0 :         struct ibuf *buf;
     208           0 :         unsigned int i = 0;
     209           0 :         ssize_t n;
     210           0 :         struct msghdr msg;
     211           0 :         struct cmsghdr *cmsg;
     212           0 :         union {
     213             :                 struct cmsghdr hdr;
     214             :                 char buf[CMSG_SPACE(sizeof(int))];
     215             :         } cmsgbuf;
     216             : 
     217           0 :         memset(&iov, 0, sizeof(iov));
     218           0 :         memset(&msg, 0, sizeof(msg));
     219           0 :         memset(&cmsgbuf, 0, sizeof(cmsgbuf));
     220           0 :         TAILQ_FOREACH (buf, &msgbuf->bufs, entry) {
     221           0 :                 if (i >= IOV_MAX)
     222             :                         break;
     223           0 :                 iov[i].iov_base = buf->buf + buf->rpos;
     224           0 :                 iov[i].iov_len = buf->wpos - buf->rpos;
     225           0 :                 i++;
     226           0 :                 if (buf->fd != -1)
     227             :                         break;
     228             :         }
     229             : 
     230           0 :         msg.msg_iov = iov;
     231           0 :         msg.msg_iovlen = i;
     232             : 
     233           0 :         if (buf != NULL && buf->fd != -1) {
     234           0 :                 msg.msg_control = (caddr_t)&cmsgbuf.buf;
     235           0 :                 msg.msg_controllen = sizeof(cmsgbuf.buf);
     236           0 :                 cmsg = CMSG_FIRSTHDR(&msg);
     237           0 :                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     238           0 :                 cmsg->cmsg_level = SOL_SOCKET;
     239           0 :                 cmsg->cmsg_type = SCM_RIGHTS;
     240           0 :                 memcpy(CMSG_DATA(cmsg), &buf->fd, sizeof(int));
     241             :         }
     242             : 
     243           0 : again:
     244           0 :         if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
     245           0 :                 if (errno == EINTR)
     246           0 :                         goto again;
     247           0 :                 if (errno == ENOBUFS)
     248           0 :                         errno = EAGAIN;
     249           0 :                 return -1;
     250             :         }
     251             : 
     252           0 :         if (n == 0) { /* connection closed */
     253           0 :                 errno = 0;
     254           0 :                 return 0;
     255             :         }
     256             : 
     257             :         /*
     258             :          * assumption: fd got sent if sendmsg sent anything
     259             :          * this works because fds are passed one at a time
     260             :          */
     261           0 :         if (buf != NULL && buf->fd != -1) {
     262           0 :                 close(buf->fd);
     263           0 :                 buf->fd = -1;
     264             :         }
     265             : 
     266           0 :         msgbuf_drain(msgbuf, n);
     267             : 
     268           0 :         return 1;
     269             : }
     270             : 
     271           0 : static void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
     272             : {
     273           0 :         TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
     274           0 :         msgbuf->queued++;
     275             : }
     276             : 
     277           0 : static void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
     278             : {
     279             :         /* TAILQ_REMOVE done by caller */
     280           0 :         if (buf->fd != -1)
     281           0 :                 close(buf->fd);
     282             : 
     283           0 :         msgbuf->queued--;
     284           0 :         ibuf_free(buf);
     285           0 : }

Generated by: LCOV version v1.16-topotato