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