diff options
Diffstat (limited to 'net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c')
-rw-r--r-- | net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c new file mode 100644 index 000000000000..3db0ec22abe8 --- /dev/null +++ b/net/openbgpd/files/patch-openbsd-compat_imsg-buffer.c @@ -0,0 +1,312 @@ +Index: openbsd-compat/imsg-buffer.c +=================================================================== +RCS file: openbsd-compat/imsg-buffer.c +diff -N openbsd-compat/imsg-buffer.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ openbsd-compat/imsg-buffer.c 8 Dec 2012 20:17:59 -0000 1.2 +@@ -0,0 +1,305 @@ ++/* $OpenBSD: imsg-buffer.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */ ++ ++/* ++ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include <sys/param.h> ++#include <sys/queue.h> ++#include <sys/socket.h> ++#include <sys/uio.h> ++ ++#include <errno.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include "imsg.h" ++ ++int ibuf_realloc(struct ibuf *, size_t); ++void ibuf_enqueue(struct msgbuf *, struct ibuf *); ++void ibuf_dequeue(struct msgbuf *, struct ibuf *); ++ ++struct ibuf * ++ibuf_open(size_t len) ++{ ++ struct ibuf *buf; ++ ++ if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) ++ return (NULL); ++ if ((buf->buf = malloc(len)) == NULL) { ++ free(buf); ++ return (NULL); ++ } ++ buf->size = buf->max = len; ++ buf->fd = -1; ++ ++ return (buf); ++} ++ ++struct ibuf * ++ibuf_dynamic(size_t len, size_t max) ++{ ++ struct ibuf *buf; ++ ++ if (max < len) ++ return (NULL); ++ ++ if ((buf = ibuf_open(len)) == NULL) ++ return (NULL); ++ ++ if (max > 0) ++ buf->max = max; ++ ++ return (buf); ++} ++ ++int ++ibuf_realloc(struct ibuf *buf, size_t len) ++{ ++ u_char *b; ++ ++ /* on static buffers max is eq size and so the following fails */ ++ if (buf->wpos + len > buf->max) { ++ errno = ENOMEM; ++ return (-1); ++ } ++ ++ b = realloc(buf->buf, buf->wpos + len); ++ if (b == NULL) ++ return (-1); ++ buf->buf = b; ++ buf->size = buf->wpos + len; ++ ++ return (0); ++} ++ ++int ++ibuf_add(struct ibuf *buf, const void *data, size_t len) ++{ ++ if (buf->wpos + len > buf->size) ++ if (ibuf_realloc(buf, len) == -1) ++ return (-1); ++ ++ memcpy(buf->buf + buf->wpos, data, len); ++ buf->wpos += len; ++ return (0); ++} ++ ++void * ++ibuf_reserve(struct ibuf *buf, size_t len) ++{ ++ void *b; ++ ++ if (buf->wpos + len > buf->size) ++ if (ibuf_realloc(buf, len) == -1) ++ return (NULL); ++ ++ b = buf->buf + buf->wpos; ++ buf->wpos += len; ++ return (b); ++} ++ ++void * ++ibuf_seek(struct ibuf *buf, size_t pos, size_t len) ++{ ++ /* only allowed to seek in already written parts */ ++ if (pos + len > buf->wpos) ++ return (NULL); ++ ++ return (buf->buf + pos); ++} ++ ++size_t ++ibuf_size(struct ibuf *buf) ++{ ++ return (buf->wpos); ++} ++ ++size_t ++ibuf_left(struct ibuf *buf) ++{ ++ return (buf->max - buf->wpos); ++} ++ ++void ++ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ ibuf_enqueue(msgbuf, buf); ++} ++ ++int ++ibuf_write(struct msgbuf *msgbuf) ++{ ++ struct iovec iov[IOV_MAX]; ++ struct ibuf *buf; ++ unsigned int i = 0; ++ ssize_t n; ++ ++ bzero(&iov, sizeof(iov)); ++ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { ++ if (i >= IOV_MAX) ++ break; ++ iov[i].iov_base = buf->buf + buf->rpos; ++ iov[i].iov_len = buf->wpos - buf->rpos; ++ i++; ++ } ++ ++again: ++ if ((n = writev(msgbuf->fd, iov, i)) == -1) { ++ if (errno == EAGAIN || errno == EINTR) ++ goto again; ++ if (errno == ENOBUFS) ++ errno = EAGAIN; ++ return (-1); ++ } ++ ++ if (n == 0) { /* connection closed */ ++ errno = 0; ++ return (0); ++ } ++ ++ msgbuf_drain(msgbuf, n); ++ ++ return (1); ++} ++ ++void ++ibuf_free(struct ibuf *buf) ++{ ++ free(buf->buf); ++ free(buf); ++} ++ ++void ++msgbuf_init(struct msgbuf *msgbuf) ++{ ++ msgbuf->queued = 0; ++ msgbuf->fd = -1; ++ TAILQ_INIT(&msgbuf->bufs); ++} ++ ++void ++msgbuf_drain(struct msgbuf *msgbuf, size_t n) ++{ ++ struct ibuf *buf, *next; ++ ++ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; ++ buf = next) { ++ next = TAILQ_NEXT(buf, entry); ++ if (buf->rpos + n >= buf->wpos) { ++ n -= buf->wpos - buf->rpos; ++ ibuf_dequeue(msgbuf, buf); ++ } else { ++ buf->rpos += n; ++ n = 0; ++ } ++ } ++} ++ ++void ++msgbuf_clear(struct msgbuf *msgbuf) ++{ ++ struct ibuf *buf; ++ ++ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) ++ ibuf_dequeue(msgbuf, buf); ++} ++ ++int ++msgbuf_write(struct msgbuf *msgbuf) ++{ ++ struct iovec iov[IOV_MAX]; ++ struct ibuf *buf; ++ unsigned int i = 0; ++ ssize_t n; ++ struct msghdr msg; ++ struct cmsghdr *cmsg; ++ union { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int))]; ++ } cmsgbuf; ++ ++ bzero(&iov, sizeof(iov)); ++ bzero(&msg, sizeof(msg)); ++ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { ++ if (i >= IOV_MAX) ++ break; ++ iov[i].iov_base = buf->buf + buf->rpos; ++ iov[i].iov_len = buf->wpos - buf->rpos; ++ i++; ++ if (buf->fd != -1) ++ break; ++ } ++ ++ msg.msg_iov = iov; ++ msg.msg_iovlen = i; ++ ++ if (buf != NULL && buf->fd != -1) { ++ msg.msg_control = (caddr_t)&cmsgbuf.buf; ++ msg.msg_controllen = sizeof(cmsgbuf.buf); ++ cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg->cmsg_len = CMSG_LEN(sizeof(int)); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ *(int *)CMSG_DATA(cmsg) = buf->fd; ++ } ++ ++again: ++ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) { ++ if (errno == EAGAIN || errno == EINTR) ++ goto again; ++ if (errno == ENOBUFS) ++ errno = EAGAIN; ++ return (-1); ++ } ++ ++ if (n == 0) { /* connection closed */ ++ errno = 0; ++ return (0); ++ } ++ ++ /* ++ * assumption: fd got sent if sendmsg sent anything ++ * this works because fds are passed one at a time ++ */ ++ if (buf != NULL && buf->fd != -1) { ++ close(buf->fd); ++ buf->fd = -1; ++ } ++ ++ msgbuf_drain(msgbuf, n); ++ ++ return (1); ++} ++ ++void ++ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); ++ msgbuf->queued++; ++} ++ ++void ++ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) ++{ ++ TAILQ_REMOVE(&msgbuf->bufs, buf, entry); ++ ++ if (buf->fd != -1) ++ close(buf->fd); ++ ++ msgbuf->queued--; ++ ibuf_free(buf); ++} |