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