136 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <errno.h>
 | |
| #include <stdio.h>
 | |
| #include <fcntl.h>
 | |
| #include <net/ioctl.h>
 | |
| #include <net/netlib.h>
 | |
| #include <sys/socket.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/un.h>
 | |
| 
 | |
| #define DEBUG 0
 | |
| 
 | |
| static int _uds_socketpair(int type, int protocol, int sv[2]);
 | |
| 
 | |
| /*
 | |
|  * Create a pair of connected sockets
 | |
|  */
 | |
| int socketpair(int domain, int type, int protocol, int sv[2]) {
 | |
| 
 | |
| #if DEBUG
 | |
| 	fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n",
 | |
| 		domain, type, protocol);
 | |
| #endif
 | |
| 
 | |
| 	if (domain != AF_UNIX)
 | |
| 	{
 | |
| 		errno = EAFNOSUPPORT;
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	if (domain == AF_UNIX &&
 | |
| 			(type == SOCK_STREAM || type == SOCK_SEQPACKET))
 | |
| 		return _uds_socketpair(type, protocol, sv);
 | |
| 
 | |
| #if DEBUG
 | |
| 	fprintf(stderr,
 | |
| 		"socketpair: nothing for domain %d, type %d, protocol %d\n",
 | |
| 		domain, type, protocol);
 | |
| #endif
 | |
| 
 | |
| 	errno= EPROTOTYPE;
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| static int _uds_socketpair(int type, int protocol, int sv[2])
 | |
| {
 | |
| 	dev_t dev;
 | |
| 	int r, i;
 | |
| 	struct stat sbuf;
 | |
| 
 | |
| 	if (protocol != 0)
 | |
| 	{
 | |
| #if DEBUG
 | |
| 		fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol);
 | |
| #endif
 | |
| 		errno= EPROTONOSUPPORT;
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* in this 'for' loop two unconnected sockets are created */
 | |
| 	for (i = 0; i < 2; i++) {
 | |
| 		sv[i]= open(UDS_DEVICE, O_RDWR);
 | |
| 		if (sv[i] == -1) {
 | |
| 			int open_errno = errno;
 | |
| 
 | |
| 			if (i == 1) {
 | |
| 				/* if we failed to open() the 2nd 
 | |
| 				 * socket, we need to close the 1st
 | |
| 				 */
 | |
| 				close(sv[0]);
 | |
| 				errno = open_errno;
 | |
| 			}
 | |
| 
 | |
| 			return -1;
 | |
| 		}
 | |
| 
 | |
| 		/* set the type for the socket via ioctl
 | |
| 		 * (SOCK_STREAM, SOCK_SEQPACKET, etc)
 | |
| 		 */
 | |
| 		r= ioctl(sv[i], NWIOSUDSTYPE, &type);
 | |
| 		if (r == -1) {
 | |
| 			int ioctl_errno;
 | |
| 
 | |
| 			/* if that failed rollback socket creation */
 | |
| 			ioctl_errno= errno;
 | |
| 			close(sv[i]);
 | |
| 
 | |
| 			if (i == 1) {
 | |
| 				/* if we just closed the 2nd socket, we 
 | |
| 				 * need to close the 1st
 | |
| 				 */
 | |
| 				close(sv[0]);
 | |
| 			}
 | |
| 
 | |
| 			/* return the error thrown by the call to ioctl */
 | |
| 			errno= ioctl_errno;
 | |
| 			return -1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	r= fstat(sv[1], &sbuf);
 | |
| 	if (r == -1) {
 | |
| 		int fstat_errno;
 | |
| 
 | |
| 		/* if that failed rollback socket creation */
 | |
| 		fstat_errno= errno;
 | |
| 
 | |
| 		close(sv[0]);
 | |
| 		close(sv[1]);
 | |
| 
 | |
| 		/* return the error thrown by the call to fstat */
 | |
| 		errno= fstat_errno;
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	dev = sbuf.st_dev;
 | |
| 
 | |
| 	/* connect the sockets sv[0] and sv[1] */
 | |
| 	r= ioctl(sv[0], NWIOSUDSPAIR, &dev);
 | |
| 	if (r == -1) {
 | |
| 		int ioctl_errno;
 | |
| 
 | |
| 		/* if that failed rollback socket creation */
 | |
| 		ioctl_errno= errno;
 | |
| 
 | |
| 		close(sv[0]);
 | |
| 		close(sv[1]);
 | |
| 
 | |
| 		/* return the error thrown by the call to ioctl */
 | |
| 		errno= ioctl_errno;
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	return 0;
 | |
| }
 | 
