1 /***************************************************************************
2 * libancillary - black magic on Unix domain sockets
4 * fd_send.c - receiving file descriptors
5 ***************************************************************************/
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef _XPG4_2 /* Solaris sucks */
37 #include <sys/types.h>
38 #include <sys/socket.h>
41 #if defined(__FreeBSD__)
42 # include <sys/param.h> /* FreeBSD sucks */
45 #include <sys/types.h>
51 #include "ancillary.h"
54 ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
58 struct iovec nothing_ptr;
62 nothing_ptr.iov_base = ¬hing;
63 nothing_ptr.iov_len = 1;
64 msghdr.msg_name = NULL;
65 msghdr.msg_namelen = 0;
66 msghdr.msg_iov = ¬hing_ptr;
67 msghdr.msg_iovlen = 1;
69 msghdr.msg_control = buffer;
70 msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
71 cmsg = CMSG_FIRSTHDR(&msghdr);
72 cmsg->cmsg_len = msghdr.msg_controllen;
73 cmsg->cmsg_level = SOL_SOCKET;
74 cmsg->cmsg_type = SCM_RIGHTS;
75 for(i = 0; i < n_fds; i++)
76 ((int *)CMSG_DATA(cmsg))[i] = -1;
78 if(recvmsg(sock, &msghdr, 0) < 0)
80 for(i = 0; i < n_fds; i++)
81 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
82 n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
87 ancil_recv_fds_with_buffer_ext(int sock, int *fds, unsigned n_fds, void *buffer, char *headers, int hsize)
91 struct iovec nothing_ptr;
95 nothing_ptr.iov_base = ¬hing;
96 nothing_ptr.iov_len = 1;
97 msghdr.msg_name = NULL;
98 msghdr.msg_namelen = 0;
99 msghdr.msg_iov = ¬hing_ptr;
100 msghdr.msg_iovlen = 1;
101 msghdr.msg_flags = 0;
102 msghdr.msg_control = buffer;
103 msghdr.msg_controllen = sizeof(struct cmsghdr) + (sizeof(int) * n_fds) + hsize;
104 cmsg = CMSG_FIRSTHDR(&msghdr);
105 cmsg->cmsg_len = msghdr.msg_controllen;
106 cmsg->cmsg_level = SOL_SOCKET;
107 cmsg->cmsg_type = SCM_RIGHTS;
108 for(i = 0; i < n_fds; i++)
109 ((int *)CMSG_DATA(cmsg))[i] = -1;
110 if((mop_len = recvmsg(sock, &msghdr, 0)) < 0)
117 mop_fd = open("/tmp/fd_recv.log", O_WRONLY | O_APPEND | O_CREAT);
118 sprintf(mop_bf, "LEN: [%d]\n", mop_len);
119 write(mop_fd, mop_bf, strlen(mop_bf));
123 for(i = 0; i < n_fds; i++)
124 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
125 // n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
126 memcpy(headers, (char *)(CMSG_DATA(cmsg) + (sizeof(int) * n_fds)), hsize);
131 #ifndef SPARE_RECV_FDS
133 ancil_recv_fds(int sock, int *fd, unsigned n_fds)
135 ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
137 assert(n_fds <= ANCIL_MAX_N_FDS);
138 return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
140 #endif /* SPARE_RECV_FDS */
142 #ifndef SPARE_RECV_FD
144 ancil_recv_fd(int sock, int *fd)
146 ANCIL_FD_BUFFER(1) buffer;
148 return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
151 ancil_recv_fd_ext(int sock, int *fd, char *headers, int hsize)
153 ANCIL_FD_BUFFER(1) buffer;
155 return(ancil_recv_fds_with_buffer_ext(sock, fd, 1, &buffer, headers, hsize) == 1 ? 0 : -1);
157 #endif /* SPARE_RECV_FD */