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