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 * 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 * 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 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 }