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