1*433d6423SLionel Sambuc #include <sys/cdefs.h> 2*433d6423SLionel Sambuc #include "namespace.h" 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc #include <errno.h> 5*433d6423SLionel Sambuc #include <stdio.h> 6*433d6423SLionel Sambuc #include <fcntl.h> 7*433d6423SLionel Sambuc #include <unistd.h> 8*433d6423SLionel Sambuc #include <net/netlib.h> 9*433d6423SLionel Sambuc #include <sys/ioc_net.h> 10*433d6423SLionel Sambuc #include <sys/socket.h> 11*433d6423SLionel Sambuc #include <sys/stat.h> 12*433d6423SLionel Sambuc #include <sys/un.h> 13*433d6423SLionel Sambuc 14*433d6423SLionel Sambuc #define DEBUG 0 15*433d6423SLionel Sambuc 16*433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2]); 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc /* 19*433d6423SLionel Sambuc * Create a pair of connected sockets 20*433d6423SLionel Sambuc */ 21*433d6423SLionel Sambuc int socketpair(int domain, int type, int protocol, int sv[2]) { 22*433d6423SLionel Sambuc 23*433d6423SLionel Sambuc #if DEBUG 24*433d6423SLionel Sambuc fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n", 25*433d6423SLionel Sambuc domain, type, protocol); 26*433d6423SLionel Sambuc #endif 27*433d6423SLionel Sambuc 28*433d6423SLionel Sambuc if (domain != AF_UNIX) 29*433d6423SLionel Sambuc { 30*433d6423SLionel Sambuc errno = EAFNOSUPPORT; 31*433d6423SLionel Sambuc return -1; 32*433d6423SLionel Sambuc } 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc if (domain == AF_UNIX && 35*433d6423SLionel Sambuc (type == SOCK_STREAM || type == SOCK_SEQPACKET)) 36*433d6423SLionel Sambuc return _uds_socketpair(type, protocol, sv); 37*433d6423SLionel Sambuc 38*433d6423SLionel Sambuc #if DEBUG 39*433d6423SLionel Sambuc fprintf(stderr, 40*433d6423SLionel Sambuc "socketpair: nothing for domain %d, type %d, protocol %d\n", 41*433d6423SLionel Sambuc domain, type, protocol); 42*433d6423SLionel Sambuc #endif 43*433d6423SLionel Sambuc 44*433d6423SLionel Sambuc errno= EPROTOTYPE; 45*433d6423SLionel Sambuc return -1; 46*433d6423SLionel Sambuc } 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2]) 49*433d6423SLionel Sambuc { 50*433d6423SLionel Sambuc dev_t dev; 51*433d6423SLionel Sambuc int r, i; 52*433d6423SLionel Sambuc struct stat sbuf; 53*433d6423SLionel Sambuc 54*433d6423SLionel Sambuc if (protocol != 0) 55*433d6423SLionel Sambuc { 56*433d6423SLionel Sambuc #if DEBUG 57*433d6423SLionel Sambuc fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol); 58*433d6423SLionel Sambuc #endif 59*433d6423SLionel Sambuc errno= EPROTONOSUPPORT; 60*433d6423SLionel Sambuc return -1; 61*433d6423SLionel Sambuc } 62*433d6423SLionel Sambuc 63*433d6423SLionel Sambuc /* in this 'for' loop two unconnected sockets are created */ 64*433d6423SLionel Sambuc for (i = 0; i < 2; i++) { 65*433d6423SLionel Sambuc sv[i]= open(UDS_DEVICE, O_RDWR); 66*433d6423SLionel Sambuc if (sv[i] == -1) { 67*433d6423SLionel Sambuc int open_errno = errno; 68*433d6423SLionel Sambuc 69*433d6423SLionel Sambuc if (i == 1) { 70*433d6423SLionel Sambuc /* if we failed to open() the 2nd 71*433d6423SLionel Sambuc * socket, we need to close the 1st 72*433d6423SLionel Sambuc */ 73*433d6423SLionel Sambuc close(sv[0]); 74*433d6423SLionel Sambuc errno = open_errno; 75*433d6423SLionel Sambuc } 76*433d6423SLionel Sambuc 77*433d6423SLionel Sambuc return -1; 78*433d6423SLionel Sambuc } 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc /* set the type for the socket via ioctl 81*433d6423SLionel Sambuc * (SOCK_STREAM, SOCK_SEQPACKET, etc) 82*433d6423SLionel Sambuc */ 83*433d6423SLionel Sambuc r= ioctl(sv[i], NWIOSUDSTYPE, &type); 84*433d6423SLionel Sambuc if (r == -1) { 85*433d6423SLionel Sambuc int ioctl_errno; 86*433d6423SLionel Sambuc 87*433d6423SLionel Sambuc /* if that failed rollback socket creation */ 88*433d6423SLionel Sambuc ioctl_errno= errno; 89*433d6423SLionel Sambuc close(sv[i]); 90*433d6423SLionel Sambuc 91*433d6423SLionel Sambuc if (i == 1) { 92*433d6423SLionel Sambuc /* if we just closed the 2nd socket, we 93*433d6423SLionel Sambuc * need to close the 1st 94*433d6423SLionel Sambuc */ 95*433d6423SLionel Sambuc close(sv[0]); 96*433d6423SLionel Sambuc } 97*433d6423SLionel Sambuc 98*433d6423SLionel Sambuc /* return the error thrown by the call to ioctl */ 99*433d6423SLionel Sambuc errno= ioctl_errno; 100*433d6423SLionel Sambuc return -1; 101*433d6423SLionel Sambuc } 102*433d6423SLionel Sambuc } 103*433d6423SLionel Sambuc 104*433d6423SLionel Sambuc r= fstat(sv[1], &sbuf); 105*433d6423SLionel Sambuc if (r == -1) { 106*433d6423SLionel Sambuc int fstat_errno; 107*433d6423SLionel Sambuc 108*433d6423SLionel Sambuc /* if that failed rollback socket creation */ 109*433d6423SLionel Sambuc fstat_errno= errno; 110*433d6423SLionel Sambuc 111*433d6423SLionel Sambuc close(sv[0]); 112*433d6423SLionel Sambuc close(sv[1]); 113*433d6423SLionel Sambuc 114*433d6423SLionel Sambuc /* return the error thrown by the call to fstat */ 115*433d6423SLionel Sambuc errno= fstat_errno; 116*433d6423SLionel Sambuc return -1; 117*433d6423SLionel Sambuc } 118*433d6423SLionel Sambuc 119*433d6423SLionel Sambuc dev = sbuf.st_dev; 120*433d6423SLionel Sambuc 121*433d6423SLionel Sambuc /* connect the sockets sv[0] and sv[1] */ 122*433d6423SLionel Sambuc r= ioctl(sv[0], NWIOSUDSPAIR, &dev); 123*433d6423SLionel Sambuc if (r == -1) { 124*433d6423SLionel Sambuc int ioctl_errno; 125*433d6423SLionel Sambuc 126*433d6423SLionel Sambuc /* if that failed rollback socket creation */ 127*433d6423SLionel Sambuc ioctl_errno= errno; 128*433d6423SLionel Sambuc 129*433d6423SLionel Sambuc close(sv[0]); 130*433d6423SLionel Sambuc close(sv[1]); 131*433d6423SLionel Sambuc 132*433d6423SLionel Sambuc /* return the error thrown by the call to ioctl */ 133*433d6423SLionel Sambuc errno= ioctl_errno; 134*433d6423SLionel Sambuc return -1; 135*433d6423SLionel Sambuc } 136*433d6423SLionel Sambuc 137*433d6423SLionel Sambuc 138*433d6423SLionel Sambuc return 0; 139*433d6423SLionel Sambuc } 140