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 /*
24 * Copyright 2019 Joyent, Inc.
25 */
26
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <pthread.h>
39
40 extern const char *__progname;
41
42 static void *
server(void * varg)43 server(void *varg)
44 {
45 int ret;
46 int sock = (int)varg;
47 unsigned int i;
48
49 for (i = 0; i < 5; i++) {
50 struct iovec iov;
51 struct msghdr msg;
52 uint8_t buf[4096];
53
54 iov = (struct iovec) {
55 .iov_base = buf,
56 .iov_len = sizeof (buf)
57 };
58
59 msg = (struct msghdr) {
60 .msg_iov = &iov,
61 .msg_iovlen = 1,
62 };
63
64 ret = recvmsg(sock, &msg, 0);
65 if (ret == -1) {
66 fprintf(stderr, "server - recvmsg fail %s\n",
67 strerror(errno));
68 exit(1);
69 }
70
71 printf("SERVER:%s\n", (char *)msg.msg_iov->iov_base);
72 fflush(stdout);
73 }
74
75 exit(0);
76 }
77
78 static void *
listener(void * varg)79 listener(void *varg)
80 {
81 struct sockaddr_un *addr = varg;
82 int ret;
83 int lsock;
84 int asock;
85
86 /* Child. */
87 lsock = socket(AF_UNIX, SOCK_STREAM, 0);
88 if (lsock == -1) {
89 fprintf(stderr, "listener - socket fail %s\n", strerror(errno));
90 exit(1);
91 }
92
93 ret = bind(lsock, (struct sockaddr *)addr, sizeof (*addr));
94 if (ret == -1) {
95 fprintf(stderr, "listener - bind fail %s\n", strerror(errno));
96 exit(1);
97 }
98
99 ret = listen(lsock, 5);
100 if (ret == -1) {
101 fprintf(stderr, "listener - listen fail %s\n", strerror(errno));
102 exit(1);
103 }
104
105 for (;;) {
106 asock = accept(lsock, NULL, 0);
107 if (asock == -1) {
108 fprintf(stderr, "listener - accept fail %s\n",
109 strerror(errno));
110 exit(1);
111 }
112
113 /* start worker */
114 ret = pthread_create(NULL, NULL, server, (void *)asock);
115 if (ret == -1) {
116 fprintf(stderr, "%s - thread create fail %s\n",
117 __progname, strerror(errno));
118 exit(1);
119 }
120 }
121 }
122
123 /*
124 * This should be a place only root is allowed to write.
125 * The test will create and destroy this directory.
126 */
127 char testdir[100] = "/var/run/os-tests-sockfs";
128 struct sockaddr_un addr;
129 int test_uid = UID_NOBODY;
130
131 int
main(int argc,char ** argv)132 main(int argc, char **argv)
133 {
134 int ret;
135 int sock;
136 unsigned int i;
137
138 if (argc > 1) {
139 ret = strlcpy(testdir, argv[1], sizeof (testdir));
140 if (ret >= sizeof (testdir)) {
141 fprintf(stderr, "%s: too long\n", argv[1]);
142 exit(1);
143 }
144 }
145
146 addr.sun_family = AF_UNIX;
147 (void) sprintf(addr.sun_path, "%s/s", testdir);
148
149 if (mkdir(testdir, 0700) != 0) {
150 switch (errno) {
151 case EEXIST:
152 case EISDIR:
153 break;
154 default:
155 perror(testdir);
156 exit(1);
157 }
158 }
159 (void) unlink(addr.sun_path);
160
161 /* Set up the listener. */
162 ret = pthread_create(NULL, NULL, listener, &addr);
163 if (ret == -1) {
164 fprintf(stderr, "%s - thread create fail %s\n",
165 argv[0], strerror(errno));
166 exit(1);
167 }
168
169 sleep(1);
170
171 /* Create and connect the socket endpoint. */
172
173 sock = socket(AF_UNIX, SOCK_STREAM, 0);
174 if (sock == -1) {
175 fprintf(stderr, "%s - socket fail %s\n",
176 argv[0], strerror(errno));
177 exit(1);
178 }
179
180 ret = connect(sock, (struct sockaddr *)&addr, sizeof (addr));
181 if (ret == -1) {
182 fprintf(stderr, "%s - connect fail %s\n",
183 argv[0], strerror(errno));
184 exit(1);
185 }
186
187 /* Send some messages */
188 for (i = 0; i < 5; i++) {
189 struct iovec iov;
190 struct msghdr msg;
191 uint8_t buf[4096];
192
193 memcpy(buf, "TEST0", sizeof ("TEST0"));
194 buf[4] = '0' + i;
195
196 printf("CLIENT:%s\n", buf);
197
198 iov = (struct iovec) {
199 .iov_base = buf,
200 .iov_len = sizeof (buf),
201 };
202
203 msg = (struct msghdr) {
204 .msg_iov = &iov,
205 .msg_iovlen = 1,
206 };
207
208 ret = sendmsg(sock, &msg, 0);
209
210 if (ret == -1) {
211 fprintf(stderr, "%s - sendmsg fail %s\n",
212 argv[0], strerror(errno));
213 exit(1);
214 }
215
216 fflush(stdout);
217 sleep(1);
218 }
219
220 close(sock);
221 return (0);
222 }
223