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