bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] sendfd, recvf pass file descriptors along Unix domain socket


From: Bastien ROUCARIES
Subject: [PATCH 2/3] sendfd, recvf pass file descriptors along Unix domain sockets
Date: Wed, 2 Feb 2011 15:33:35 +0100

Recvfd and sendfd can be used to pass an open file descriptor over a Unix 
domain socket from one process to another.
---
 lib/passfd.c   |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/passfd.h   |   22 +++++++++
 modules/passfd |   28 +++++++++++
 3 files changed, 193 insertions(+), 0 deletions(-)
 create mode 100644 lib/passfd.c
 create mode 100644 lib/passfd.h
 create mode 100644 modules/passfd

diff --git a/lib/passfd.c b/lib/passfd.c
new file mode 100644
index 0000000..fc8965f
--- /dev/null
+++ b/lib/passfd.c
@@ -0,0 +1,143 @@
+/* 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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#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
+   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: */
+   (*(int *) CMSG_DATA(cmsg)) = fd;
+   msg.msg_controllen = cmsg->cmsg_len;
+#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43
+   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;
+  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
+   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: */
+   (*(int *) CMSG_DATA(cmsg)) = -1;
+   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;
+     }
+   
+   fd = *(int*)CMSG_DATA(cmsg);
+   return fd;
+#elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43
+   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 0000000..4d0bfab
--- /dev/null
+++ b/lib/passfd.h
@@ -0,0 +1,22 @@
+/* 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 <http://www.gnu.org/licenses/>.  */
+#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 0000000..2c4854d
--- /dev/null
+++ b/modules/passfd
@@ -0,0 +1,28 @@
+Description:
+Passfile descriptors along Unix (socket/stream) file descriptors
+
+Files:
+m4/sockpfaf.m4
+m4/afunix.m4
+lib/passfd.c
+
+Depends-on:
+errno
+sys_socket
+extensions
+
+configure.ac:
+gl_SOCKET_AFUNIX
+
+Makefile.am:
+lib_SOURCES += passfd.c
+
+Include:
+<sys/socket.h>
+<sys/un.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Bastien ROUCARI�S
-- 
1.7.2.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]