monitor_fdpass.c revision 1.2
1/* $OpenBSD: monitor_fdpass.c,v 1.2 2008/03/13 01:49:52 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 30void 31send_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 68int 69recv_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 if (n != sizeof(int)) 93 syslog(LOG_WARNING, 94 "recv_fd: recvmsg: expected received 1 got %ld", (long)n); 95 if (result == 0) { 96 cmsg = CMSG_FIRSTHDR(&msg); 97 if (cmsg == NULL) { 98 syslog(LOG_WARNING, "recv_fd: no message header"); 99 return (-1); 100 } 101 if (cmsg->cmsg_type != SCM_RIGHTS) 102 syslog(LOG_WARNING, "recv_fd: expected type %d got %d", 103 SCM_RIGHTS, cmsg->cmsg_type); 104 fd = (*(int *)CMSG_DATA(cmsg)); 105 return (fd); 106 } else { 107 errno = result; 108 return (-1); 109 } 110} 111