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