1#include "protocol.h"
2
3#include <stdio.h>
4#include <string.h>
5#include <sys/socket.h>
6
7ssize_t
8send_fd(int socket, int fd, struct iovec *iov, int iovlen)
9{
10 char control[CMSG_SPACE(sizeof(fd))];
11 struct msghdr message = {
12 .msg_name = NULL,
13 .msg_namelen = 0,
14 .msg_iov = iov,
15 .msg_iovlen = iovlen,
16 };
17 struct cmsghdr *cmsg;
18
19 if (fd != -1) {
20 message.msg_control = control, message.msg_controllen = sizeof(control);
21
22 cmsg = CMSG_FIRSTHDR(&message);
23 cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
24 cmsg->cmsg_level = SOL_SOCKET;
25 cmsg->cmsg_type = SCM_RIGHTS;
26
27 memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
28 } else {
29 message.msg_control = NULL;
30 message.msg_controllen = 0;
31 }
32
33 return sendmsg(socket, &message, 0);
34}
35
36ssize_t
37receive_fd(int socket, int *fd, struct iovec *iov, int iovlen)
38{
39 ssize_t size;
40 char control[CMSG_SPACE(sizeof(*fd))];
41 struct msghdr message = {
42 .msg_name = NULL,
43 .msg_namelen = 0,
44 .msg_iov = iov,
45 .msg_iovlen = iovlen,
46 };
47 struct cmsghdr *cmsg;
48
49 if (fd) {
50 *fd = -1;
51 message.msg_control = &control;
52 message.msg_controllen = sizeof(control);
53 }
54
55 size = recvmsg(socket, &message, MSG_CMSG_CLOEXEC);
56 if (size < 0) {
57 return -1;
58 }
59
60 cmsg = CMSG_FIRSTHDR(&message);
61 if (fd && cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(*fd)) &&
62 cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
63 memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
64 }
65
66 return size;
67}