1 /* $NetBSD: unix_send_fd.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $ */
7 /* send file descriptor
9 /* #include <iostuff.h>
11 /* int unix_send_fd(fd, sendfd)
15 /* unix_send_fd() sends a file descriptor over the specified
16 /* UNIX-domain socket.
22 /* Another file descriptor.
24 /* unix_send_fd() returns -1 upon failure.
28 /* The Secure Mailer license must be distributed with this software.
31 /* IBM T.J. Watson Research
33 /* Yorktown Heights, NY 10598, USA
38 #include <sys_defs.h> /* includes <sys/types.h> */
39 #include <sys/socket.h>
43 /* Utility library. */
48 /* unix_send_fd - send file descriptor */
50 int unix_send_fd(int fd
, int sendfd
)
54 * This code does not work with version <2.2 Linux kernels, and it does
55 * not compile with version <2 Linux libraries.
57 #ifdef CANT_USE_SEND_RECV_MSG
58 const char *myname
= "unix_send_fd";
60 msg_warn("%s: your system has no support for file descriptor passing",
68 * Adapted from: W. Richard Stevens, UNIX Network Programming, Volume 1,
69 * Second edition. Except that we use CMSG_LEN instead of CMSG_SPACE; the
70 * latter breaks on LP64 systems.
72 #if defined(CMSG_SPACE) && !defined(NO_MSGHDR_MSG_CONTROL)
74 struct cmsghdr just_for_alignment
;
75 char control
[CMSG_SPACE(sizeof(sendfd
))];
77 struct cmsghdr
*cmptr
;
79 memset((char *) &msg
, 0, sizeof(msg
)); /* Fix 200512 */
80 msg
.msg_control
= control_un
.control
;
81 msg
.msg_controllen
= sizeof(control_un
.control
); /* Fix 200506 */
83 cmptr
= CMSG_FIRSTHDR(&msg
);
84 cmptr
->cmsg_len
= CMSG_LEN(sizeof(sendfd
));
85 cmptr
->cmsg_level
= SOL_SOCKET
;
86 cmptr
->cmsg_type
= SCM_RIGHTS
;
87 *(int *) CMSG_DATA(cmptr
) = sendfd
;
89 msg
.msg_accrights
= (char *) &sendfd
;
90 msg
.msg_accrightslen
= sizeof(sendfd
);
97 * XXX We don't want to pass any data, just a file descriptor. However,
98 * setting msg.msg_iov = 0 and msg.msg_iovlen = 0 causes trouble. See the
99 * comments in the unix_recv_fd() routine.
106 return (sendmsg(fd
, &msg
, 0));
113 * Proof-of-concept program. Open a file and send the descriptor, presumably
114 * to the unix_recv_fd test program.
120 #include <split_at.h>
123 int main(int argc
, char **argv
)
132 || (endpoint
= split_at(transport
= argv
[1], ':')) == 0
133 || *endpoint
== 0 || *transport
== 0)
134 msg_fatal("usage: %s transport:endpoint file...", argv
[0]);
136 if (strcmp(transport
, "unix") == 0) {
137 server_sock
= unix_connect(endpoint
, BLOCKING
, 0);
139 msg_fatal("invalid transport name: %s", transport
);
142 msg_fatal("connect %s:%s: %m", transport
, endpoint
);
145 while ((path
= *argv
++) != 0) {
146 if ((client_fd
= open(path
, O_RDONLY
, 0)) < 0)
147 msg_fatal("open %s: %m", path
);
148 msg_info("path=%s fd=%d", path
, client_fd
);
149 if (unix_send_fd(server_sock
, client_fd
) < 0)
150 msg_fatal("send file descriptor: %m");
151 if (close(client_fd
) != 0)
152 msg_fatal("close(%d): %m", client_fd
);