1 /*
2 * Copyright 2016 Jeremy Allison
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <pthread.h>
35
36 extern const char *__progname;
37
38 static void *
server(void * varg)39 server(void *varg)
40 {
41 int ret;
42 int sock = (int)varg;
43 unsigned int i;
44
45 for (i = 0; i < 5; i++) {
46 struct iovec iov;
47 struct msghdr msg;
48 uint8_t buf[4096];
49
50 iov = (struct iovec) {
51 .iov_base = buf,
52 .iov_len = sizeof (buf)
53 };
54
55 msg = (struct msghdr) {
56 .msg_iov = &iov,
57 .msg_iovlen = 1,
58 };
59
60 ret = recvmsg(sock, &msg, 0);
61 if (ret == -1) {
62 fprintf(stderr, "server - recvmsg fail %s\n",
63 strerror(errno));
64 exit(1);
65 }
66
67 printf("SERVER:%s\n", (char *)msg.msg_iov->iov_base);
68 fflush(stdout);
69 }
70
71 exit(0);
72 }
73
74 static void *
listener(void * varg)75 listener(void *varg)
76 {
77 struct sockaddr_un *addr = varg;
78 int ret;
79 int lsock;
80 int asock;
81
82 /* Child. */
83 lsock = socket(AF_UNIX, SOCK_STREAM, 0);
84 if (lsock == -1) {
85 fprintf(stderr, "listener - socket fail %s\n", strerror(errno));
86 exit(1);
87 }
88
89 ret = bind(lsock, (struct sockaddr *)addr, sizeof (*addr));
90 if (ret == -1) {
91 fprintf(stderr, "listener - bind fail %s\n", strerror(errno));
92 exit(1);
93 }
94
95 ret = listen(lsock, 5);
96 if (ret == -1) {
97 fprintf(stderr, "listener - listen fail %s\n", strerror(errno));
98 exit(1);
99 }
100
101 for (;;) {
102 asock = accept(lsock, NULL, 0);
103 if (asock == -1) {
104 fprintf(stderr, "listener - accept fail %s\n",
105 strerror(errno));
106 exit(1);
107 }
108
109 /* start worker */
110 ret = pthread_create(NULL, NULL, server, (void *)asock);
111 if (ret == -1) {
112 fprintf(stderr, "%s - thread create fail %s\n",
113 __progname, strerror(errno));
114 exit(1);
115 }
116 }
117
118 exit(0);
119 }
120
121 /*
122 * This should be a place only root is allowed to write.
123 * The test will create and destroy this directory.
124 */
125 char testdir[100] = "/var/run/os-tests-sockfs";
126 struct sockaddr_un addr;
127 int test_uid = UID_NOBODY;
128
129 int
main(int argc,char ** argv)130 main(int argc, char **argv)
131 {
132 int ret;
133 int sock;
134 unsigned int i;
135
136 if (argc > 1) {
137 ret = strlcpy(testdir, argv[1], sizeof (testdir));
138 if (ret >= sizeof (testdir)) {
139 fprintf(stderr, "%s: too long\n", argv[1]);
140 exit(1);
141 }
142 }
143
144 addr.sun_family = AF_UNIX;
145 (void) sprintf(addr.sun_path, "%s/s", testdir);
146
147 if (mkdir(testdir, 0700) != 0) {
148 switch (errno) {
149 case EEXIST:
150 case EISDIR:
151 break;
152 default:
153 perror(testdir);
154 exit(1);
155 }
156 }
157 (void) unlink(addr.sun_path);
158
159 /* Set up the listener. */
160 ret = pthread_create(NULL, NULL, listener, &addr);
161 if (ret == -1) {
162 fprintf(stderr, "%s - thread create fail %s\n",
163 argv[0], strerror(errno));
164 exit(1);
165 }
166
167 sleep(1);
168
169 /* Create and connect the socket endpoint. */
170
171 sock = socket(AF_UNIX, SOCK_STREAM, 0);
172 if (sock == -1) {
173 fprintf(stderr, "%s - socket fail %s\n",
174 argv[0], strerror(errno));
175 exit(1);
176 }
177
178 ret = connect(sock, (struct sockaddr *)&addr, sizeof (addr));
179 if (ret == -1) {
180 fprintf(stderr, "%s - connect fail %s\n",
181 argv[0], strerror(errno));
182 exit(1);
183 }
184
185 /* Send some messages */
186 for (i = 0; i < 5; i++) {
187 struct iovec iov;
188 struct msghdr msg;
189 uint8_t buf[4096];
190
191 memcpy(buf, "TEST0", sizeof ("TEST0"));
192 buf[4] = '0' + i;
193
194 printf("CLIENT:%s\n", buf);
195
196 iov = (struct iovec) {
197 .iov_base = buf,
198 .iov_len = sizeof (buf),
199 };
200
201 msg = (struct msghdr) {
202 .msg_iov = &iov,
203 .msg_iovlen = 1,
204 };
205
206 ret = sendmsg(sock, &msg, 0);
207
208 if (ret == -1) {
209 fprintf(stderr, "%s - sendmsg fail %s\n",
210 argv[0], strerror(errno));
211 exit(1);
212 }
213
214 fflush(stdout);
215 sleep(1);
216 }
217
218 close(sock);
219 return (0);
220 }
221