1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #define _POSIX_C_SOURCE 200112L
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30
31
32
33
34 ssize_t send_fd(int sock, const char *buf, size_t len, int fd);
35
36
37
38
39 ssize_t recv_fd(int sock, char *buf, size_t len, int *fd);
40
41 void child_process();
42
43 const char *socket_path = "fd.sock";
44
45 int main(int argc, char **argv) {
46
47 struct sockaddr_un addr;
48 memset(&addr, 0, sizeof(struct sockaddr_un));
49 addr.sun_family = AF_UNIX;
50 strcpy(addr.sun_path, socket_path);
51
52 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
53 if(sock == -1) {
54 perror("socket");
55 return -1;
56 }
57
58 if(bind(sock, (struct sockaddr*)&addr, sizeof(addr))) {
59 perror("bind");
60 return -1;
61 }
62
63 if(listen(sock, 8) == -1) {
64 perror("listen");
65 return -1;
66 }
67
68
69 pid_t pid = fork();
70 if(pid == 0) {
71 close(sock);
72 child_process();
73 return 0;
74 }
75
76
77 int fd = accept(sock, NULL, 0);
78 if(fd == -1) {
79 perror("accept");
80 return -1;
81 }
82
83 printf("client connected\n");
84
85
86 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
87 int file = open("testfile", O_WRONLY | O_CREAT, mode);
88 printf("testfile fd = %d\n", file);
89
90
91 const char *msg = "Hello World!";
92 send_fd(fd, msg, strlen(msg), file);
93
94 int status;
95 waitpid(pid, &status, 0);
96
97
98 close(file);
99 close(fd);
100 close(sock);
101
102 if(unlink(socket_path)) {
103 perror("unlink");
104 }
105
106 return 0;
107 }
108
109 void child_process() {
110
111 struct sockaddr_un addr;
112 memset(&addr, 0, sizeof(addr));
113 addr.sun_family = AF_UNIX;
114 strcpy(addr.sun_path, socket_path);
115
116 int client = socket(AF_UNIX, SOCK_STREAM, 0);
117 if(client == -1) {
118 perror("client: socket");
119 return;
120 }
121
122 if(connect(client, (struct sockaddr*)&addr, sizeof(addr))) {
123 perror("client: connect");
124 return;
125 }
126
127 printf("client connected\n");
128
129
130 char buf[1024];
131 int fd;
132 ssize_t r = recv_fd(client, buf, 1024, &fd);
133 printf("msg: {%.*s}\n", (int)r, buf);
134 printf("fd: %d\n", fd);
135
136 if(r > 0 && fd != -1) {
137 printf("write msg to fd\n");
138 write(fd, buf, r);
139 close(fd);
140 }
141
142 close(client);
143 }
144
145 ssize_t send_fd(int sock, const char *buf, size_t len, int fd) {
146 struct msghdr msg;
147 msg.msg_name = NULL;
148 msg.msg_namelen = 0;
149
150
151 struct iovec iov[1] ;
152 iov[0].iov_base = (void*)buf;
153 iov[0].iov_len = len;
154
155 msg.msg_iov = iov;
156 msg.msg_iovlen = 1;
157
158
159
160
161
162
163
164
165 char cmsg_buf[CMSG_SPACE(sizeof(int))];
166
167 struct cmsghdr *cmsg = (struct cmsghdr*)cmsg_buf;
168 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
169 cmsg->cmsg_level = SOL_SOCKET;
170 cmsg->cmsg_type = SCM_RIGHTS;
171
172 int *data = (int*)CMSG_DATA(cmsg);
173 *data = fd;
174
175 msg.msg_control = cmsg;
176 msg.msg_controllen = CMSG_LEN(sizeof(int));
177
178 msg.msg_flags = 0;
179
180 return sendmsg(sock, &msg, 0);
181 }
182
183 ssize_t recv_fd(int sock, char *buf, size_t len, int *fd) {
184
185 struct msghdr msg;
186 msg.msg_name = NULL;
187 msg.msg_namelen = 0;
188
189 struct iovec iov[1];
190 iov[0].iov_base = buf;
191 iov[0].iov_len = len;
192
193 msg.msg_iov = iov;
194 msg.msg_iovlen = 1;
195
196 char cmsg_buf[CMSG_SPACE(sizeof(int))];
197 memset(cmsg_buf, 0, CMSG_SPACE(sizeof(int)));
198
199 struct cmsghdr *cmsg = (struct cmsghdr*)cmsg_buf;
200 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
201 cmsg->cmsg_level = SOL_SOCKET;
202 cmsg->cmsg_type = SCM_RIGHTS;
203
204 msg.msg_control = cmsg;
205 msg.msg_controllen = CMSG_LEN(sizeof(int));
206
207 msg.msg_flags = 0;
208
209 ssize_t r = recvmsg(sock, &msg, 0);
210 if(r != -1) {
211
212 int *data = (int*)CMSG_DATA(cmsg);
213 *fd = *data;
214 } else {
215 *fd = -1;
216 }
217 return r;
218 }