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