xref: /openbsd-src/libexec/ftpd/monitor_fdpass.c (revision 55c3341c6c391a0be51c19e81d32811a9a3e6a9b)
1*55c3341cSjca /*	$OpenBSD: monitor_fdpass.c,v 1.7 2016/02/29 20:22:36 jca Exp $	*/
2b96c0bc5Shenning 
3b96c0bc5Shenning /*
4b96c0bc5Shenning  * Copyright (c) 2002 Matthieu Herrb
5b96c0bc5Shenning  * Copyright (c) 2001 Niels Provos <provos@citi.umich.edu>
6b96c0bc5Shenning  *
7b96c0bc5Shenning  * Permission to use, copy, modify, and distribute this software for any
8b96c0bc5Shenning  * purpose with or without fee is hereby granted, provided that the above
9b96c0bc5Shenning  * copyright notice and this permission notice appear in all copies.
10b96c0bc5Shenning  *
11b96c0bc5Shenning  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12b96c0bc5Shenning  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13b96c0bc5Shenning  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14b96c0bc5Shenning  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15b96c0bc5Shenning  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16b96c0bc5Shenning  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17b96c0bc5Shenning  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18b96c0bc5Shenning  */
19b96c0bc5Shenning 
20b96c0bc5Shenning #include <sys/types.h>
21b96c0bc5Shenning #include <sys/socket.h>
22b96c0bc5Shenning #include <sys/uio.h>
23b96c0bc5Shenning 
24b96c0bc5Shenning #include <errno.h>
25b96c0bc5Shenning #include <fcntl.h>
26b96c0bc5Shenning #include <string.h>
27b96c0bc5Shenning #include <syslog.h>
28b96c0bc5Shenning #include <unistd.h>
2998071651Sderaadt #include "monitor.h"
30b96c0bc5Shenning 
31b96c0bc5Shenning void
send_fd(int sock,int fd)32b96c0bc5Shenning send_fd(int sock, int fd)
33b96c0bc5Shenning {
34b96c0bc5Shenning 	struct msghdr msg;
350827ab61Sderaadt 	union {
360827ab61Sderaadt 		struct cmsghdr hdr;
370827ab61Sderaadt 		char buf[CMSG_SPACE(sizeof(int))];
380827ab61Sderaadt 	} cmsgbuf;
39b96c0bc5Shenning 	struct cmsghdr *cmsg;
40b96c0bc5Shenning 	struct iovec vec;
41b96c0bc5Shenning 	int result = 0;
42b96c0bc5Shenning 	ssize_t n;
43b96c0bc5Shenning 
44b96c0bc5Shenning 	memset(&msg, 0, sizeof(msg));
45b96c0bc5Shenning 
46b96c0bc5Shenning 	if (fd >= 0) {
470827ab61Sderaadt 		msg.msg_control = (caddr_t)&cmsgbuf.buf;
48da15c7b9Sderaadt 		msg.msg_controllen = sizeof(cmsgbuf.buf);
49b96c0bc5Shenning 		cmsg = CMSG_FIRSTHDR(&msg);
50b96c0bc5Shenning 		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
51b96c0bc5Shenning 		cmsg->cmsg_level = SOL_SOCKET;
52b96c0bc5Shenning 		cmsg->cmsg_type = SCM_RIGHTS;
53b96c0bc5Shenning 		*(int *)CMSG_DATA(cmsg) = fd;
54b96c0bc5Shenning 	} else
55b96c0bc5Shenning 		result = errno;
56b96c0bc5Shenning 
57b96c0bc5Shenning 	vec.iov_base = &result;
58b96c0bc5Shenning 	vec.iov_len = sizeof(int);
59b96c0bc5Shenning 	msg.msg_iov = &vec;
60b96c0bc5Shenning 	msg.msg_iovlen = 1;
61b96c0bc5Shenning 
62b96c0bc5Shenning 	if ((n = sendmsg(sock, &msg, 0)) == -1)
63b96c0bc5Shenning 		syslog(LOG_WARNING, "send_fd: sendmsg(%d): %m", sock);
64b96c0bc5Shenning 	if (n != sizeof(int))
65*55c3341cSjca 		syslog(LOG_WARNING, "send_fd: sendmsg: expected sent 1 got %zd",
66*55c3341cSjca 		    n);
67b96c0bc5Shenning }
68b96c0bc5Shenning 
69b96c0bc5Shenning int
recv_fd(int sock)70b96c0bc5Shenning recv_fd(int sock)
71b96c0bc5Shenning {
72b96c0bc5Shenning 	struct msghdr msg;
730827ab61Sderaadt 	union {
740827ab61Sderaadt 		struct cmsghdr hdr;
750827ab61Sderaadt 		char buf[CMSG_SPACE(sizeof(int))];
760827ab61Sderaadt 	} cmsgbuf;
77b96c0bc5Shenning 	struct cmsghdr *cmsg;
78b96c0bc5Shenning 	struct iovec vec;
79b96c0bc5Shenning 	ssize_t n;
80b96c0bc5Shenning 	int result;
81b96c0bc5Shenning 	int fd;
82b96c0bc5Shenning 
83b96c0bc5Shenning 	memset(&msg, 0, sizeof(msg));
84b96c0bc5Shenning 	vec.iov_base = &result;
85b96c0bc5Shenning 	vec.iov_len = sizeof(int);
86b96c0bc5Shenning 	msg.msg_iov = &vec;
87b96c0bc5Shenning 	msg.msg_iovlen = 1;
880827ab61Sderaadt 	msg.msg_control = &cmsgbuf.buf;
89da15c7b9Sderaadt 	msg.msg_controllen = sizeof(cmsgbuf.buf);
90b96c0bc5Shenning 
91a592c95fSderaadt 	if ((n = recvmsg(sock, &msg, 0)) == -1) {
92b96c0bc5Shenning 		syslog(LOG_WARNING, "recv_fd: recvmsg(%d): %m", sock);
93a592c95fSderaadt 		return -1;
94a592c95fSderaadt 	}
95b96c0bc5Shenning 	if (n != sizeof(int))
96b96c0bc5Shenning 		syslog(LOG_WARNING,
97*55c3341cSjca 		    "recv_fd: recvmsg: expected received 1 got %zd", n);
98b96c0bc5Shenning 	if (result == 0) {
99b96c0bc5Shenning 		cmsg = CMSG_FIRSTHDR(&msg);
100b96c0bc5Shenning 		if (cmsg == NULL) {
101b96c0bc5Shenning 			syslog(LOG_WARNING, "recv_fd: no message header");
102b96c0bc5Shenning 			return (-1);
103b96c0bc5Shenning 		}
104b96c0bc5Shenning 		if (cmsg->cmsg_type != SCM_RIGHTS)
105b96c0bc5Shenning 			syslog(LOG_WARNING, "recv_fd: expected type %d got %d",
106b96c0bc5Shenning 			    SCM_RIGHTS, cmsg->cmsg_type);
107b96c0bc5Shenning 		fd = (*(int *)CMSG_DATA(cmsg));
108b96c0bc5Shenning 		return (fd);
109b96c0bc5Shenning 	} else {
110b96c0bc5Shenning 		errno = result;
111b96c0bc5Shenning 		return (-1);
112b96c0bc5Shenning 	}
113b96c0bc5Shenning }
114