fdpass.c revision 73393219d2d25beba4e078e434d56807c9f00a48
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch/*
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch fdpass.c - FD passing
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch Copyright (c) 2002 Timo Sirainen
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch Permission is hereby granted, free of charge, to any person obtaining
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch a copy of this software and associated documentation files (the
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch "Software"), to deal in the Software without restriction, including
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch without limitation the rights to use, copy, modify, merge, publish,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch distribute, sublicense, and/or sell copies of the Software, and to
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch permit persons to whom the Software is furnished to do so, subject to
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch the following conditions:
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch The above copyright notice and this permission notice shall be
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch included in all copies or substantial portions of the Software.
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch*/
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#define _XPG4_2
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#define _XOPEN_SOURCE_EXTENDED /* for Tru64 */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "lib.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "fdpass.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include <sys/socket.h>
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include <sys/un.h>
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include <sys/uio.h>
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#ifndef CMSG_SPACE
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch# define CMSG_ALIGN(len) \
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch# define CMSG_SPACE(len) \
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (CMSG_ALIGN(len) + CMSG_ALIGN(sizeof(struct cmsghdr)))
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch# define CMSG_LEN(len) \
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#endif
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschssize_t fd_send(int handle, int send_fd, const void *data, size_t size)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch{
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct msghdr msg;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct iovec iov;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct cmsghdr *cmsg;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch char buf[CMSG_SPACE(sizeof(int))];
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* at least one byte is required to be sent with fd passing */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch i_assert(size > 0 && size < SSIZE_T_MAX);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch memset(&msg, 0, sizeof (struct msghdr));
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch iov.iov_base = (void *) data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch iov.iov_len = size;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_iov = &iov;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_iovlen = 1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (send_fd != -1) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* set the control and controllen before CMSG_FIRSTHDR() */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_control = buf;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_controllen = sizeof(buf);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg = CMSG_FIRSTHDR(&msg);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg->cmsg_level = SOL_SOCKET;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg->cmsg_type = SCM_RIGHTS;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg->cmsg_len = CMSG_LEN(sizeof(int));
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *((int *) CMSG_DATA(cmsg)) = send_fd;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* set the real length we want to use. it's different than
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch sizeof(buf) in 64bit systems. */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_controllen = cmsg->cmsg_len;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return sendmsg(handle, &msg, 0);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschssize_t fd_read(int handle, void *data, size_t size, int *fd)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch{
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct msghdr msg;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct iovec iov;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct cmsghdr *cmsg;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch ssize_t ret;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch char buf[CMSG_SPACE(sizeof(int))];
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch i_assert(size > 0 && size < SSIZE_T_MAX);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch memset(&msg, 0, sizeof (struct msghdr));
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch iov.iov_base = data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch iov.iov_len = size;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_iov = &iov;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_iovlen = 1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch memset(buf, 0, sizeof(buf));
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_control = buf;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch msg.msg_controllen = sizeof(buf);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch ret = recvmsg(handle, &msg, 0);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (ret <= 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *fd = -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return ret;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* at least one byte transferred - we should have the fd now */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg = CMSG_FIRSTHDR(&msg);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (msg.msg_controllen < CMSG_SPACE(sizeof(int)) ||
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg == NULL || cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *fd = -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch else
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *fd = *((int *) CMSG_DATA(cmsg));
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return ret;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch