1 /* $OpenBSD: monitor_fdpass.c,v 1.5 2012/04/04 17:24:49 deraadt 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 30 void 31 send_fd(int sock, int fd) 32 { 33 struct msghdr msg; 34 union { 35 struct cmsghdr hdr; 36 char buf[CMSG_SPACE(sizeof(int))]; 37 } cmsgbuf; 38 struct cmsghdr *cmsg; 39 struct iovec vec; 40 int result = 0; 41 ssize_t n; 42 43 memset(&msg, 0, sizeof(msg)); 44 45 if (fd >= 0) { 46 msg.msg_control = (caddr_t)&cmsgbuf.buf; 47 msg.msg_controllen = sizeof(cmsgbuf.buf); 48 cmsg = CMSG_FIRSTHDR(&msg); 49 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 50 cmsg->cmsg_level = SOL_SOCKET; 51 cmsg->cmsg_type = SCM_RIGHTS; 52 *(int *)CMSG_DATA(cmsg) = fd; 53 } else 54 result = errno; 55 56 vec.iov_base = &result; 57 vec.iov_len = sizeof(int); 58 msg.msg_iov = &vec; 59 msg.msg_iovlen = 1; 60 61 if ((n = sendmsg(sock, &msg, 0)) == -1) 62 syslog(LOG_WARNING, "send_fd: sendmsg(%d): %m", sock); 63 if (n != sizeof(int)) 64 syslog(LOG_WARNING, "send_fd: sendmsg: expected sent 1 got %ld", 65 (long)n); 66 } 67 68 int 69 recv_fd(int sock) 70 { 71 struct msghdr msg; 72 union { 73 struct cmsghdr hdr; 74 char buf[CMSG_SPACE(sizeof(int))]; 75 } cmsgbuf; 76 struct cmsghdr *cmsg; 77 struct iovec vec; 78 ssize_t n; 79 int result; 80 int fd; 81 82 memset(&msg, 0, sizeof(msg)); 83 vec.iov_base = &result; 84 vec.iov_len = sizeof(int); 85 msg.msg_iov = &vec; 86 msg.msg_iovlen = 1; 87 msg.msg_control = &cmsgbuf.buf; 88 msg.msg_controllen = sizeof(cmsgbuf.buf); 89 90 if ((n = recvmsg(sock, &msg, 0)) == -1) { 91 syslog(LOG_WARNING, "recv_fd: recvmsg(%d): %m", sock); 92 return -1; 93 } 94 if (n != sizeof(int)) 95 syslog(LOG_WARNING, 96 "recv_fd: recvmsg: expected received 1 got %ld", (long)n); 97 if (result == 0) { 98 cmsg = CMSG_FIRSTHDR(&msg); 99 if (cmsg == NULL) { 100 syslog(LOG_WARNING, "recv_fd: no message header"); 101 return (-1); 102 } 103 if (cmsg->cmsg_type != SCM_RIGHTS) 104 syslog(LOG_WARNING, "recv_fd: expected type %d got %d", 105 SCM_RIGHTS, cmsg->cmsg_type); 106 fd = (*(int *)CMSG_DATA(cmsg)); 107 return (fd); 108 } else { 109 errno = result; 110 return (-1); 111 } 112 } 113