diff options
Diffstat (limited to 'usr.sbin/relayd/imsg.c')
-rw-r--r-- | usr.sbin/relayd/imsg.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/usr.sbin/relayd/imsg.c b/usr.sbin/relayd/imsg.c index 4b21fbe0934..b1a9a9e302f 100644 --- a/usr.sbin/relayd/imsg.c +++ b/usr.sbin/relayd/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.6 2007/03/19 10:11:59 henning Exp $ */ +/* $OpenBSD: imsg.c,v 1.7 2007/06/12 15:16:10 msf Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -47,10 +47,24 @@ imsg_init(struct imsgbuf *ibuf, int fd, void (*handler)(int, short, void *)) ssize_t imsg_read(struct imsgbuf *ibuf) { + struct msghdr msg; + struct cmsghdr *cmsg; + char cmsgbuf[CMSG_SPACE(sizeof(int) * 16)]; + struct iovec iov; ssize_t n; + int fd; + struct imsg_fd *ifd; - if ((n = recv(ibuf->fd, ibuf->r.buf + ibuf->r.wpos, - sizeof(ibuf->r.buf) - ibuf->r.wpos, 0)) == -1) { + bzero(&msg, sizeof(msg)); + + iov.iov_base = ibuf->r.buf + ibuf->r.wpos; + iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { if (errno != EINTR && errno != EAGAIN) { log_warn("imsg_read: pipe read error"); return (-1); @@ -60,6 +74,20 @@ imsg_read(struct imsgbuf *ibuf) ibuf->r.wpos += n; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + fd = (*(int *)CMSG_DATA(cmsg)); + if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) + fatal("imsg_read calloc"); + ifd->fd = fd; + TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry); + } else + log_warn("imsg_read: got unexpected ctl data level %d " + "type %d", cmsg->cmsg_level, cmsg->cmsg_type); + } + return (n); } @@ -102,7 +130,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) int imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, - pid_t pid, void *data, u_int16_t datalen) + pid_t pid, int fd, void *data, u_int16_t datalen) { struct buf *wbuf; int n; @@ -113,6 +141,8 @@ imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, if (imsg_add(wbuf, data, datalen) == -1) return (-1); + wbuf->fd = fd; + if ((n = imsg_close(ibuf, wbuf)) < 0) return (-1); @@ -181,3 +211,19 @@ imsg_free(struct imsg *imsg) { free(imsg->data); } + +int +imsg_get_fd(struct imsgbuf *ibuf) +{ + int fd; + struct imsg_fd *ifd; + + if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) + return (-1); + + fd = ifd->fd; + TAILQ_REMOVE(&ibuf->fds, ifd, entry); + free(ifd); + + return (fd); +} |