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