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 }
219