From ee195dafe32fed7ec44fb0cbf775e1638e668b9b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bastien=20Roucari=C3=A8s?= Date: Sun, 13 Mar 2011 15:06:52 +0100 Subject: [PATCH] passfd module, part 2. * modules/passfd: New file. * lib/passfd.h: New file. * lib/passfd.c: New file. --- ChangeLog | 7 +++ lib/passfd.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/passfd.h | 21 +++++++ modules/passfd | 30 ++++++++++ 4 files changed, 205 insertions(+) create mode 100644 lib/passfd.c create mode 100644 lib/passfd.h create mode 100644 modules/passfd diff --git a/ChangeLog b/ChangeLog index a3ddcef231..c95ab68426 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-03-07 Bastien Roucariès + + passfd module, part 2. + * modules/passfd: New file. + * lib/passfd.h: New file. + * lib/passfd.c: New file. + 2011-03-12 Bruno Haible wcswidth, mbswidth: Avoid integer overflow. diff --git a/lib/passfd.c b/lib/passfd.c new file mode 100644 index 0000000000..2f84a13637 --- /dev/null +++ b/lib/passfd.c @@ -0,0 +1,147 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_WINSOCK2_H +#include +#endif + +/* Sendfd sends the file descriptor fd along the socket + to a process calling recvfd on the other end. + + return -1 in case of error, 0 on success +*/ +int +sendfd (int sock, int fd) +{ + char send = 0; + struct iovec iov[1]; + struct msghdr msg; + + /* send at least one char */ + iov[0].iov_base = &send; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = 0; + msg.msg_namelen = 0; + + { +#ifdef HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof (fd))]; + + msg.msg_control = buf; + msg.msg_controllen = sizeof (buf); + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (int)); + /* Initialize the payload: */ + memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); + msg.msg_controllen = cmsg->cmsg_len; +#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof (fd); +#else + errno = ENOSYS; + return -1; +#endif + } + + if (sendmsg (sock, &msg, 0) != iov[0].iov_len) + return -1; + return 0; +} + +/* Sendfd sends the file descriptor fd along the socket + to a process calling recvfd on the other end. + + return -1 in case of error, fd on success +*/ +int +recvfd (int sock) +{ + char recv = 0; + const int mone = -1; + int fd; + struct iovec iov[1]; + struct msghdr msg; + + /* send at least one char */ + iov[0].iov_base = &recv; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = 0; + msg.msg_namelen = 0; + + { +#ifdef HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44_WAY + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof (fd))]; + + msg.msg_control = buf; + msg.msg_controllen = sizeof (buf); + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (int)); + /* Initialize the payload: */ + memcpy (CMSG_DATA (cmsg), &mone, sizeof (mone)); + msg.msg_controllen = cmsg->cmsg_len; + + if (recvmsg (sock, &msg, 0) < 0) + return -1; + + cmsg = CMSG_FIRSTHDR (&msg); + /* be paranoiac */ + if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof (int)) + || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) + { + /* fake errno: at end the file is not available */ + errno = EACCES; + return -1; + } + + memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd)); + return fd; +#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43_WAY + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof (fd); + if (recvmsg (sock, &msg, 0) < 0) + return -1; + return fd; +#else + errno = ENOSYS; + return -1; +#endif + } +} diff --git a/lib/passfd.h b/lib/passfd.h new file mode 100644 index 0000000000..13eb3b1dfb --- /dev/null +++ b/lib/passfd.h @@ -0,0 +1,21 @@ +/* passfd.h -- definitions and prototypes for passfd.c + + Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ +#ifndef PASSFD_H_ +#define PASSFD_H_ 1 +int sendfd (int sock, int fd); +int recvfd (int sock); +#endif diff --git a/modules/passfd b/modules/passfd new file mode 100644 index 0000000000..43922e17d0 --- /dev/null +++ b/modules/passfd @@ -0,0 +1,30 @@ +Description: +Passfile descriptors along Unix (socket/stream) file descriptors + +Files: +m4/sockpfaf.m4 +m4/afunix.m4 +lib/passfd.c +lib/passfd.h + +Depends-on: +errno +sys_socket +extensions + +configure.ac: +gl_SOCKET_AFUNIX + +Makefile.am: +lib_SOURCES += passfd.c + +Include: + + +"passfd.h" + +License: +LGPLv2+ + +Maintainer: +Bastien ROUCARIÈS -- 2.30.2