This source file includes following definitions.
- sendfd
- sendfd
- recvfd
- recvfd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <config.h>
17
18
19 #include "passfd.h"
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stddef.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include <sys/socket.h>
30
31 #include "cloexec.h"
32
33
34
35
36
37
38
39 #ifndef MSG_CMSG_CLOEXEC
40 # define MSG_CMSG_CLOEXEC 0
41 #endif
42
43 #if HAVE_SENDMSG
44
45
46
47
48
49 int
50 sendfd (int sock, int fd)
51 {
52 char byte = 0;
53 struct iovec iov;
54 struct msghdr msg;
55 # ifdef CMSG_FIRSTHDR
56 struct cmsghdr *cmsg;
57 char buf[CMSG_SPACE (sizeof fd)];
58 # endif
59
60
61 memset (&msg, 0, sizeof msg);
62 iov.iov_base = &byte;
63 iov.iov_len = 1;
64 msg.msg_iov = &iov;
65 msg.msg_iovlen = 1;
66 msg.msg_name = NULL;
67 msg.msg_namelen = 0;
68
69 # ifdef CMSG_FIRSTHDR
70 msg.msg_control = buf;
71 msg.msg_controllen = sizeof buf;
72 cmsg = CMSG_FIRSTHDR (&msg);
73 cmsg->cmsg_level = SOL_SOCKET;
74 cmsg->cmsg_type = SCM_RIGHTS;
75 cmsg->cmsg_len = CMSG_LEN (sizeof fd);
76
77 memcpy (CMSG_DATA (cmsg), &fd, sizeof fd);
78 msg.msg_controllen = cmsg->cmsg_len;
79 # elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
80 msg.msg_accrights = &fd;
81 msg.msg_accrightslen = sizeof fd;
82 # else
83 errno = ENOSYS;
84 return -1;
85 # endif
86
87 if (sendmsg (sock, &msg, 0) != iov.iov_len)
88 return -1;
89 return 0;
90 }
91 #else
92 int
93 sendfd (_GL_UNUSED int sock, _GL_UNUSED int fd)
94 {
95 errno = ENOSYS;
96 return -1;
97 }
98 #endif
99
100
101 #if HAVE_RECVMSG
102
103
104
105
106
107 int
108 recvfd (int sock, int flags)
109 {
110 char byte = 0;
111 struct iovec iov;
112 struct msghdr msg;
113 int fd = -1;
114 ssize_t len;
115 # ifdef CMSG_FIRSTHDR
116 struct cmsghdr *cmsg;
117 char buf[CMSG_SPACE (sizeof fd)];
118 int flags_recvmsg = flags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0;
119 # endif
120
121 if ((flags & ~O_CLOEXEC) != 0)
122 {
123 errno = EINVAL;
124 return -1;
125 }
126
127
128 memset (&msg, 0, sizeof msg);
129 iov.iov_base = &byte;
130 iov.iov_len = 1;
131 msg.msg_iov = &iov;
132 msg.msg_iovlen = 1;
133 msg.msg_name = NULL;
134 msg.msg_namelen = 0;
135
136 # ifdef CMSG_FIRSTHDR
137 msg.msg_control = buf;
138 msg.msg_controllen = sizeof buf;
139 cmsg = CMSG_FIRSTHDR (&msg);
140 cmsg->cmsg_level = SOL_SOCKET;
141 cmsg->cmsg_type = SCM_RIGHTS;
142 cmsg->cmsg_len = CMSG_LEN (sizeof fd);
143
144 memcpy (CMSG_DATA (cmsg), &fd, sizeof fd);
145 msg.msg_controllen = CMSG_SPACE (sizeof fd);
146
147 len = recvmsg (sock, &msg, flags_recvmsg);
148 if (len < 0)
149 return -1;
150 if (len == 0)
151 {
152
153 errno = ENOTCONN;
154 return -1;
155 }
156 cmsg = CMSG_FIRSTHDR (&msg);
157
158 if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd)
159 || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
160 {
161 errno = EACCES;
162 return -1;
163 }
164
165 memcpy (&fd, CMSG_DATA (cmsg), sizeof fd);
166
167
168 if (!MSG_CMSG_CLOEXEC && (flags & O_CLOEXEC))
169 {
170 if (set_cloexec_flag (fd, true) < 0)
171 {
172 int saved_errno = errno;
173 (void) close (fd);
174 errno = saved_errno;
175 return -1;
176 }
177 }
178
179 # elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
180 msg.msg_accrights = &fd;
181 msg.msg_accrightslen = sizeof fd;
182 if (recvmsg (sock, &msg, 0) < 0)
183 return -1;
184
185
186 if (flags & O_CLOEXEC)
187 {
188 if (set_cloexec_flag (fd, true) < 0)
189 {
190 int saved_errno = errno;
191 close (fd);
192 errno = saved_errno;
193 return -1;
194 }
195 }
196 # else
197 errno = ENOSYS;
198 # endif
199
200 return fd;
201 }
202 #else
203 int
204 recvfd (_GL_UNUSED int sock, _GL_UNUSED int flags)
205 {
206 errno = ENOSYS;
207 return -1;
208 }
209 #endif