summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/imsg.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/relayd/imsg.c')
-rw-r--r--usr.sbin/relayd/imsg.c54
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);
+}