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 static void *
server(void * varg)37 server(void *varg)
38 {
39 	struct sockaddr_un *addr = varg;
40 	int ret;
41 	int sock;
42 	unsigned int i;
43 
44 	/* Child. */
45 	sock = socket(AF_UNIX, SOCK_DGRAM, 0);
46 	if (sock == -1) {
47 		fprintf(stderr, "server - socket fail %s\n", strerror(errno));
48 		exit(1);
49 	}
50 
51 	ret = bind(sock, (struct sockaddr *)addr, sizeof (*addr));
52 
53 	if (ret == -1) {
54 		fprintf(stderr, "server - bind fail %s\n", strerror(errno));
55 		exit(1);
56 	}
57 
58 	for (i = 0; i < 5; i++) {
59 		struct iovec iov;
60 		struct msghdr msg;
61 		uint8_t buf[4096];
62 
63 		iov = (struct iovec) {
64 			.iov_base = buf,
65 			.iov_len = sizeof (buf)
66 		};
67 
68 		msg = (struct msghdr) {
69 			.msg_iov = &iov,
70 			.msg_iovlen = 1,
71 		};
72 
73 		ret = recvmsg(sock, &msg, 0);
74 		if (ret == -1) {
75 			fprintf(stderr, "server - recvmsg fail %s\n",
76 			    strerror(errno));
77 			exit(1);
78 		}
79 
80 		printf("SERVER:%s\n", (char *)msg.msg_iov->iov_base);
81 		fflush(stdout);
82 	}
83 
84 	exit(0);
85 }
86 
87 /*
88  * This should be a place only root is allowed to write.
89  * The test will create and destroy this directory.
90  */
91 char testdir[100] = "/var/run/os-tests-sockfs";
92 struct sockaddr_un addr;
93 int test_uid = UID_NOBODY;
94 
95 int
main(int argc,char ** argv)96 main(int argc, char **argv)
97 {
98 	int ret;
99 	int sock;
100 	unsigned int i;
101 
102 	if (argc > 1) {
103 		ret = strlcpy(testdir, argv[1], sizeof (testdir));
104 		if (ret >= sizeof (testdir)) {
105 			fprintf(stderr, "%s: too long\n", argv[1]);
106 			exit(1);
107 		}
108 	}
109 
110 	addr.sun_family = AF_UNIX;
111 	(void) sprintf(addr.sun_path, "%s/s", testdir);
112 
113 	if (mkdir(testdir, 0700) != 0) {
114 		switch (errno) {
115 		case EEXIST:
116 		case EISDIR:
117 			break;
118 		default:
119 			perror(testdir);
120 			exit(1);
121 		}
122 	}
123 	(void) unlink(addr.sun_path);
124 
125 	/* Set up the server. */
126 	ret = pthread_create(NULL, NULL, server, &addr);
127 	if (ret == -1) {
128 		fprintf(stderr, "%s - thread create fail %s\n",
129 		    argv[0], strerror(errno));
130 		exit(1);
131 	}
132 
133 	sleep(1);
134 
135 	/* Create and connect the socket endpoint. */
136 
137 	sock = socket(AF_UNIX, SOCK_DGRAM, 0);
138 	if (sock == -1) {
139 		fprintf(stderr, "%s - socket fail %s\n",
140 		    argv[0], strerror(errno));
141 		exit(1);
142 	}
143 
144 	/* Send some messages */
145 	for (i = 0; i < 5; i++) {
146 		struct iovec iov;
147 		struct msghdr msg;
148 		uint8_t buf[4096];
149 
150 		memcpy(buf, "TEST0", sizeof ("TEST0"));
151 		buf[4] = '0' + i;
152 
153 		printf("CLIENT:%s\n", buf);
154 
155 		iov = (struct iovec) {
156 			.iov_base = buf,
157 			.iov_len = sizeof (buf),
158 		};
159 
160 		msg = (struct msghdr) {
161 			/* sendto */
162 			.msg_name = &addr,
163 			.msg_namelen = sizeof (addr),
164 			.msg_iov = &iov,
165 			.msg_iovlen = 1,
166 		};
167 
168 		ret = sendmsg(sock, &msg, 0);
169 
170 		if (ret == -1) {
171 			fprintf(stderr, "%s - sendmsg fail %s\n",
172 			    argv[0], strerror(errno));
173 			exit(1);
174 		}
175 
176 		fflush(stdout);
177 		sleep(1);
178 	}
179 
180 	close(sock);
181 	return (0);
182 }
183