monitor_fdpass.c revision 192595
1192595Sdes/* $OpenBSD: monitor_fdpass.c,v 1.18 2008/11/30 11:59:26 dtucker Exp $ */
298675Sdes/*
398675Sdes * Copyright 2001 Niels Provos <provos@citi.umich.edu>
498675Sdes * All rights reserved.
598675Sdes *
698675Sdes * Redistribution and use in source and binary forms, with or without
798675Sdes * modification, are permitted provided that the following conditions
898675Sdes * are met:
998675Sdes * 1. Redistributions of source code must retain the above copyright
1098675Sdes *    notice, this list of conditions and the following disclaimer.
1198675Sdes * 2. Redistributions in binary form must reproduce the above copyright
1298675Sdes *    notice, this list of conditions and the following disclaimer in the
1398675Sdes *    documentation and/or other materials provided with the distribution.
1498675Sdes *
1598675Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1698675Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1798675Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1898675Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1998675Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2098675Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2198675Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2298675Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2398675Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2498675Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2598675Sdes */
2698675Sdes
2798675Sdes#include "includes.h"
2898675Sdes
29162852Sdes#include <sys/types.h>
30162852Sdes#include <sys/socket.h>
3198675Sdes#include <sys/uio.h>
32164146Sdes#ifdef HAVE_SYS_UN_H
33164146Sdes#include <sys/un.h>
34164146Sdes#endif
3598675Sdes
36162852Sdes#include <errno.h>
37162852Sdes#include <string.h>
38162852Sdes#include <stdarg.h>
39162852Sdes
4098675Sdes#include "log.h"
4198675Sdes#include "monitor_fdpass.h"
4298675Sdes
43181111Sdesint
44137015Sdesmm_send_fd(int sock, int fd)
4598675Sdes{
4698937Sdes#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
4798675Sdes	struct msghdr msg;
4898937Sdes#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
49180989Sdes	union {
50180989Sdes		struct cmsghdr hdr;
51180989Sdes		char buf[CMSG_SPACE(sizeof(int))];
52180989Sdes	} cmsgbuf;
5398937Sdes	struct cmsghdr *cmsg;
5498937Sdes#endif
55192595Sdes	struct iovec vec;
56192595Sdes	char ch = '\0';
57192595Sdes	ssize_t n;
5898675Sdes
5998675Sdes	memset(&msg, 0, sizeof(msg));
6098937Sdes#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
6198937Sdes	msg.msg_accrights = (caddr_t)&fd;
6298937Sdes	msg.msg_accrightslen = sizeof(fd);
6398937Sdes#else
64180989Sdes	msg.msg_control = (caddr_t)&cmsgbuf.buf;
65180989Sdes	msg.msg_controllen = sizeof(cmsgbuf.buf);
6698675Sdes	cmsg = CMSG_FIRSTHDR(&msg);
6798675Sdes	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
6898675Sdes	cmsg->cmsg_level = SOL_SOCKET;
6998675Sdes	cmsg->cmsg_type = SCM_RIGHTS;
7098675Sdes	*(int *)CMSG_DATA(cmsg) = fd;
7198937Sdes#endif
7298675Sdes
7398675Sdes	vec.iov_base = &ch;
7498675Sdes	vec.iov_len = 1;
7598675Sdes	msg.msg_iov = &vec;
7698675Sdes	msg.msg_iovlen = 1;
7798675Sdes
78192595Sdes	while ((n = sendmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN ||
79192595Sdes	    errno == EINTR))
80192595Sdes		debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno));
81192595Sdes	if (n == -1) {
82181111Sdes		error("%s: sendmsg(%d): %s", __func__, fd,
8398675Sdes		    strerror(errno));
84181111Sdes		return -1;
85181111Sdes	}
86181111Sdes
87181111Sdes	if (n != 1) {
88181111Sdes		error("%s: sendmsg: expected sent 1 got %ld",
89106121Sdes		    __func__, (long)n);
90181111Sdes		return -1;
91181111Sdes	}
92181111Sdes	return 0;
9398937Sdes#else
94181111Sdes	error("%s: file descriptor passing not supported", __func__);
95181111Sdes	return -1;
9698937Sdes#endif
9798675Sdes}
9898675Sdes
9998675Sdesint
100137015Sdesmm_receive_fd(int sock)
10198675Sdes{
10298937Sdes#if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
10398675Sdes	struct msghdr msg;
10498937Sdes#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
105180989Sdes	union {
106180989Sdes		struct cmsghdr hdr;
107180989Sdes		char buf[CMSG_SPACE(sizeof(int))];
108180989Sdes	} cmsgbuf;
10998937Sdes	struct cmsghdr *cmsg;
11098937Sdes#endif
111192595Sdes	struct iovec vec;
112192595Sdes	ssize_t n;
113192595Sdes	char ch;
114192595Sdes	int fd;
11598675Sdes
11698675Sdes	memset(&msg, 0, sizeof(msg));
11798675Sdes	vec.iov_base = &ch;
11898675Sdes	vec.iov_len = 1;
11998675Sdes	msg.msg_iov = &vec;
12098675Sdes	msg.msg_iovlen = 1;
12198937Sdes#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
12298937Sdes	msg.msg_accrights = (caddr_t)&fd;
12398937Sdes	msg.msg_accrightslen = sizeof(fd);
12498937Sdes#else
125180989Sdes	msg.msg_control = &cmsgbuf.buf;
126180989Sdes	msg.msg_controllen = sizeof(cmsgbuf.buf);
12798937Sdes#endif
12898675Sdes
129192595Sdes	while ((n = recvmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN ||
130192595Sdes	    errno == EINTR))
131192595Sdes		debug3("%s: recvmsg: %s", __func__, strerror(errno));
132192595Sdes	if (n == -1) {
133181111Sdes		error("%s: recvmsg: %s", __func__, strerror(errno));
134181111Sdes		return -1;
135181111Sdes	}
136192595Sdes
137181111Sdes	if (n != 1) {
138181111Sdes		error("%s: recvmsg: expected received 1 got %ld",
139106121Sdes		    __func__, (long)n);
140181111Sdes		return -1;
141181111Sdes	}
14298675Sdes
14398937Sdes#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
144181111Sdes	if (msg.msg_accrightslen != sizeof(fd)) {
145181111Sdes		error("%s: no fd", __func__);
146181111Sdes		return -1;
147181111Sdes	}
14898937Sdes#else
14998675Sdes	cmsg = CMSG_FIRSTHDR(&msg);
150181111Sdes	if (cmsg == NULL) {
151181111Sdes		error("%s: no message header", __func__);
152181111Sdes		return -1;
153181111Sdes	}
154192595Sdes
155124208Sdes#ifndef BROKEN_CMSG_TYPE
156181111Sdes	if (cmsg->cmsg_type != SCM_RIGHTS) {
157181111Sdes		error("%s: expected type %d got %d", __func__,
15898675Sdes		    SCM_RIGHTS, cmsg->cmsg_type);
159181111Sdes		return -1;
160181111Sdes	}
161124208Sdes#endif
16298675Sdes	fd = (*(int *)CMSG_DATA(cmsg));
16398937Sdes#endif
16498675Sdes	return fd;
16598937Sdes#else
166181111Sdes	error("%s: file descriptor passing not supported", __func__);
167181111Sdes	return -1;
16898937Sdes#endif
16998675Sdes}
170