1433d6423SLionel Sambuc #include <sys/cdefs.h> 2433d6423SLionel Sambuc #include "namespace.h" 3*c38dbb97SDavid van Moolenbroek #include <lib.h> 4433d6423SLionel Sambuc 5*c38dbb97SDavid van Moolenbroek #include <string.h> 6433d6423SLionel Sambuc #include <errno.h> 7433d6423SLionel Sambuc #include <stdio.h> 8433d6423SLionel Sambuc #include <fcntl.h> 9433d6423SLionel Sambuc #include <unistd.h> 10433d6423SLionel Sambuc #include <net/netlib.h> 115dd8da10SDavid van Moolenbroek #include <sys/ioctl.h> 12433d6423SLionel Sambuc #include <sys/ioc_net.h> 13433d6423SLionel Sambuc #include <sys/socket.h> 14433d6423SLionel Sambuc #include <sys/stat.h> 15433d6423SLionel Sambuc #include <sys/un.h> 16433d6423SLionel Sambuc 17433d6423SLionel Sambuc #define DEBUG 0 18433d6423SLionel Sambuc 19433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2]); 20433d6423SLionel Sambuc 21433d6423SLionel Sambuc /* 22*c38dbb97SDavid van Moolenbroek * Create a pair of connected sockets. 23433d6423SLionel Sambuc */ 24*c38dbb97SDavid van Moolenbroek static int 25*c38dbb97SDavid van Moolenbroek __socketpair(int domain, int type, int protocol, int sv[2]) 26*c38dbb97SDavid van Moolenbroek { 27*c38dbb97SDavid van Moolenbroek message m; 28*c38dbb97SDavid van Moolenbroek 29*c38dbb97SDavid van Moolenbroek memset(&m, 0, sizeof(m)); 30*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_socket.domain = domain; 31*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_socket.type = type; 32*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_socket.protocol = protocol; 33*c38dbb97SDavid van Moolenbroek 34*c38dbb97SDavid van Moolenbroek if (_syscall(VFS_PROC_NR, VFS_SOCKETPAIR, &m) < 0) 35*c38dbb97SDavid van Moolenbroek return -1; 36*c38dbb97SDavid van Moolenbroek 37*c38dbb97SDavid van Moolenbroek sv[0] = m.m_vfs_lc_fdpair.fd0; 38*c38dbb97SDavid van Moolenbroek sv[1] = m.m_vfs_lc_fdpair.fd1; 39*c38dbb97SDavid van Moolenbroek return 0; 40*c38dbb97SDavid van Moolenbroek } 41*c38dbb97SDavid van Moolenbroek 42*c38dbb97SDavid van Moolenbroek int 43*c38dbb97SDavid van Moolenbroek socketpair(int domain, int type, int protocol, int sv[2]) 44*c38dbb97SDavid van Moolenbroek { 45*c38dbb97SDavid van Moolenbroek int r; 46*c38dbb97SDavid van Moolenbroek 47*c38dbb97SDavid van Moolenbroek r = __socketpair(domain, type, protocol, sv); 48*c38dbb97SDavid van Moolenbroek if (r != -1 || errno != EAFNOSUPPORT) 49*c38dbb97SDavid van Moolenbroek return r; 50433d6423SLionel Sambuc 51433d6423SLionel Sambuc #if DEBUG 52433d6423SLionel Sambuc fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n", 53433d6423SLionel Sambuc domain, type, protocol); 54433d6423SLionel Sambuc #endif 55433d6423SLionel Sambuc 56*c38dbb97SDavid van Moolenbroek if (domain == AF_UNIX) 57433d6423SLionel Sambuc return _uds_socketpair(type, protocol, sv); 58433d6423SLionel Sambuc 59*c38dbb97SDavid van Moolenbroek errno = EAFNOSUPPORT; 60433d6423SLionel Sambuc return -1; 61433d6423SLionel Sambuc } 62433d6423SLionel Sambuc 63433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2]) 64433d6423SLionel Sambuc { 65433d6423SLionel Sambuc dev_t dev; 66433d6423SLionel Sambuc int r, i; 67433d6423SLionel Sambuc struct stat sbuf; 68433d6423SLionel Sambuc 69*c38dbb97SDavid van Moolenbroek if (type != SOCK_STREAM && type != SOCK_SEQPACKET) { 70*c38dbb97SDavid van Moolenbroek errno = EPROTOTYPE; 71*c38dbb97SDavid van Moolenbroek return -1; 72*c38dbb97SDavid van Moolenbroek } 73*c38dbb97SDavid van Moolenbroek 74433d6423SLionel Sambuc if (protocol != 0) 75433d6423SLionel Sambuc { 76433d6423SLionel Sambuc #if DEBUG 77433d6423SLionel Sambuc fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol); 78433d6423SLionel Sambuc #endif 79433d6423SLionel Sambuc errno= EPROTONOSUPPORT; 80433d6423SLionel Sambuc return -1; 81433d6423SLionel Sambuc } 82433d6423SLionel Sambuc 83433d6423SLionel Sambuc /* in this 'for' loop two unconnected sockets are created */ 84433d6423SLionel Sambuc for (i = 0; i < 2; i++) { 85433d6423SLionel Sambuc sv[i]= open(UDS_DEVICE, O_RDWR); 86433d6423SLionel Sambuc if (sv[i] == -1) { 87433d6423SLionel Sambuc int open_errno = errno; 88433d6423SLionel Sambuc 89433d6423SLionel Sambuc if (i == 1) { 90433d6423SLionel Sambuc /* if we failed to open() the 2nd 91433d6423SLionel Sambuc * socket, we need to close the 1st 92433d6423SLionel Sambuc */ 93433d6423SLionel Sambuc close(sv[0]); 94433d6423SLionel Sambuc errno = open_errno; 95433d6423SLionel Sambuc } 96433d6423SLionel Sambuc 97433d6423SLionel Sambuc return -1; 98433d6423SLionel Sambuc } 99433d6423SLionel Sambuc 100433d6423SLionel Sambuc /* set the type for the socket via ioctl 101433d6423SLionel Sambuc * (SOCK_STREAM, SOCK_SEQPACKET, etc) 102433d6423SLionel Sambuc */ 103433d6423SLionel Sambuc r= ioctl(sv[i], NWIOSUDSTYPE, &type); 104433d6423SLionel Sambuc if (r == -1) { 105433d6423SLionel Sambuc int ioctl_errno; 106433d6423SLionel Sambuc 107433d6423SLionel Sambuc /* if that failed rollback socket creation */ 108433d6423SLionel Sambuc ioctl_errno= errno; 109433d6423SLionel Sambuc close(sv[i]); 110433d6423SLionel Sambuc 111433d6423SLionel Sambuc if (i == 1) { 112433d6423SLionel Sambuc /* if we just closed the 2nd socket, we 113433d6423SLionel Sambuc * need to close the 1st 114433d6423SLionel Sambuc */ 115433d6423SLionel Sambuc close(sv[0]); 116433d6423SLionel Sambuc } 117433d6423SLionel Sambuc 118433d6423SLionel Sambuc /* return the error thrown by the call to ioctl */ 119433d6423SLionel Sambuc errno= ioctl_errno; 120433d6423SLionel Sambuc return -1; 121433d6423SLionel Sambuc } 122433d6423SLionel Sambuc } 123433d6423SLionel Sambuc 124433d6423SLionel Sambuc r= fstat(sv[1], &sbuf); 125433d6423SLionel Sambuc if (r == -1) { 126433d6423SLionel Sambuc int fstat_errno; 127433d6423SLionel Sambuc 128433d6423SLionel Sambuc /* if that failed rollback socket creation */ 129433d6423SLionel Sambuc fstat_errno= errno; 130433d6423SLionel Sambuc 131433d6423SLionel Sambuc close(sv[0]); 132433d6423SLionel Sambuc close(sv[1]); 133433d6423SLionel Sambuc 134433d6423SLionel Sambuc /* return the error thrown by the call to fstat */ 135433d6423SLionel Sambuc errno= fstat_errno; 136433d6423SLionel Sambuc return -1; 137433d6423SLionel Sambuc } 138433d6423SLionel Sambuc 1392e89653eSDavid van Moolenbroek dev = sbuf.st_rdev; 140433d6423SLionel Sambuc 141433d6423SLionel Sambuc /* connect the sockets sv[0] and sv[1] */ 142433d6423SLionel Sambuc r= ioctl(sv[0], NWIOSUDSPAIR, &dev); 143433d6423SLionel Sambuc if (r == -1) { 144433d6423SLionel Sambuc int ioctl_errno; 145433d6423SLionel Sambuc 146433d6423SLionel Sambuc /* if that failed rollback socket creation */ 147433d6423SLionel Sambuc ioctl_errno= errno; 148433d6423SLionel Sambuc 149433d6423SLionel Sambuc close(sv[0]); 150433d6423SLionel Sambuc close(sv[1]); 151433d6423SLionel Sambuc 152433d6423SLionel Sambuc /* return the error thrown by the call to ioctl */ 153433d6423SLionel Sambuc errno= ioctl_errno; 154433d6423SLionel Sambuc return -1; 155433d6423SLionel Sambuc } 156433d6423SLionel Sambuc 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc return 0; 159433d6423SLionel Sambuc } 160