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