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