xref: /minix3/minix/lib/libc/sys/socketpair.c (revision 84ed480ef770e26a28565a26c8ef94ba01312a41)
1433d6423SLionel Sambuc #include <sys/cdefs.h>
2433d6423SLionel Sambuc #include "namespace.h"
3c38dbb97SDavid van Moolenbroek #include <lib.h>
4433d6423SLionel Sambuc 
5c38dbb97SDavid van Moolenbroek #include <string.h>
6433d6423SLionel Sambuc #include <errno.h>
7433d6423SLionel Sambuc #include <stdio.h>
8433d6423SLionel Sambuc #include <fcntl.h>
9433d6423SLionel Sambuc #include <unistd.h>
10433d6423SLionel Sambuc #include <net/netlib.h>
115dd8da10SDavid van Moolenbroek #include <sys/ioctl.h>
12433d6423SLionel Sambuc #include <sys/ioc_net.h>
13433d6423SLionel Sambuc #include <sys/socket.h>
14433d6423SLionel Sambuc #include <sys/stat.h>
15433d6423SLionel Sambuc #include <sys/un.h>
16433d6423SLionel Sambuc 
17433d6423SLionel Sambuc #define DEBUG 0
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2]);
20433d6423SLionel Sambuc 
21433d6423SLionel Sambuc /*
22c38dbb97SDavid van Moolenbroek  * Create a pair of connected sockets.
23433d6423SLionel Sambuc  */
24c38dbb97SDavid van Moolenbroek static int
__socketpair(int domain,int type,int protocol,int sv[2])25c38dbb97SDavid van Moolenbroek __socketpair(int domain, int type, int protocol, int sv[2])
26c38dbb97SDavid van Moolenbroek {
27c38dbb97SDavid van Moolenbroek 	message m;
28c38dbb97SDavid van Moolenbroek 
29c38dbb97SDavid van Moolenbroek 	memset(&m, 0, sizeof(m));
30c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_socket.domain = domain;
31c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_socket.type = type;
32c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_socket.protocol = protocol;
33c38dbb97SDavid van Moolenbroek 
34c38dbb97SDavid van Moolenbroek 	if (_syscall(VFS_PROC_NR, VFS_SOCKETPAIR, &m) < 0)
35c38dbb97SDavid van Moolenbroek 		return -1;
36c38dbb97SDavid van Moolenbroek 
37c38dbb97SDavid van Moolenbroek 	sv[0] = m.m_vfs_lc_fdpair.fd0;
38c38dbb97SDavid van Moolenbroek 	sv[1] = m.m_vfs_lc_fdpair.fd1;
39c38dbb97SDavid van Moolenbroek 	return 0;
40c38dbb97SDavid van Moolenbroek }
41c38dbb97SDavid van Moolenbroek 
42c38dbb97SDavid van Moolenbroek int
socketpair(int domain,int type,int protocol,int sv[2])43c38dbb97SDavid van Moolenbroek socketpair(int domain, int type, int protocol, int sv[2])
44c38dbb97SDavid van Moolenbroek {
45c38dbb97SDavid van Moolenbroek 	int r;
46c38dbb97SDavid van Moolenbroek 
47c38dbb97SDavid van Moolenbroek 	r = __socketpair(domain, type, protocol, sv);
48*84ed480eSDavid van Moolenbroek 	if (r != -1 || (errno != EAFNOSUPPORT && errno != ENOSYS))
49c38dbb97SDavid van Moolenbroek 		return r;
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc #if DEBUG
52433d6423SLionel Sambuc 	fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n",
53433d6423SLionel Sambuc 		domain, type, protocol);
54433d6423SLionel Sambuc #endif
55433d6423SLionel Sambuc 
56c38dbb97SDavid van Moolenbroek 	if (domain == AF_UNIX)
57433d6423SLionel Sambuc 		return _uds_socketpair(type, protocol, sv);
58433d6423SLionel Sambuc 
59c38dbb97SDavid van Moolenbroek 	errno = EAFNOSUPPORT;
60433d6423SLionel Sambuc 	return -1;
61433d6423SLionel Sambuc }
62433d6423SLionel Sambuc 
_uds_socketpair(int type,int protocol,int sv[2])63433d6423SLionel Sambuc static int _uds_socketpair(int type, int protocol, int sv[2])
64433d6423SLionel Sambuc {
65433d6423SLionel Sambuc 	dev_t dev;
66433d6423SLionel Sambuc 	int r, i;
67433d6423SLionel Sambuc 	struct stat sbuf;
68433d6423SLionel Sambuc 
69c38dbb97SDavid van Moolenbroek 	if (type != SOCK_STREAM && type != SOCK_SEQPACKET) {
70c38dbb97SDavid van Moolenbroek 		errno = EPROTOTYPE;
71c38dbb97SDavid van Moolenbroek 		return -1;
72c38dbb97SDavid van Moolenbroek 	}
73c38dbb97SDavid van Moolenbroek 
74433d6423SLionel Sambuc 	if (protocol != 0)
75433d6423SLionel Sambuc 	{
76433d6423SLionel Sambuc #if DEBUG
77433d6423SLionel Sambuc 		fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol);
78433d6423SLionel Sambuc #endif
79433d6423SLionel Sambuc 		errno= EPROTONOSUPPORT;
80433d6423SLionel Sambuc 		return -1;
81433d6423SLionel Sambuc 	}
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc 	/* in this 'for' loop two unconnected sockets are created */
84433d6423SLionel Sambuc 	for (i = 0; i < 2; i++) {
85433d6423SLionel Sambuc 		sv[i]= open(UDS_DEVICE, O_RDWR);
86433d6423SLionel Sambuc 		if (sv[i] == -1) {
87433d6423SLionel Sambuc 			int open_errno = errno;
88433d6423SLionel Sambuc 
89433d6423SLionel Sambuc 			if (i == 1) {
90433d6423SLionel Sambuc 				/* if we failed to open() the 2nd
91433d6423SLionel Sambuc 				 * socket, we need to close the 1st
92433d6423SLionel Sambuc 				 */
93433d6423SLionel Sambuc 				close(sv[0]);
94433d6423SLionel Sambuc 				errno = open_errno;
95433d6423SLionel Sambuc 			}
96433d6423SLionel Sambuc 
97433d6423SLionel Sambuc 			return -1;
98433d6423SLionel Sambuc 		}
99433d6423SLionel Sambuc 
100433d6423SLionel Sambuc 		/* set the type for the socket via ioctl
101433d6423SLionel Sambuc 		 * (SOCK_STREAM, SOCK_SEQPACKET, etc)
102433d6423SLionel Sambuc 		 */
103433d6423SLionel Sambuc 		r= ioctl(sv[i], NWIOSUDSTYPE, &type);
104433d6423SLionel Sambuc 		if (r == -1) {
105433d6423SLionel Sambuc 			int ioctl_errno;
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc 			/* if that failed rollback socket creation */
108433d6423SLionel Sambuc 			ioctl_errno= errno;
109433d6423SLionel Sambuc 			close(sv[i]);
110433d6423SLionel Sambuc 
111433d6423SLionel Sambuc 			if (i == 1) {
112433d6423SLionel Sambuc 				/* if we just closed the 2nd socket, we
113433d6423SLionel Sambuc 				 * need to close the 1st
114433d6423SLionel Sambuc 				 */
115433d6423SLionel Sambuc 				close(sv[0]);
116433d6423SLionel Sambuc 			}
117433d6423SLionel Sambuc 
118433d6423SLionel Sambuc 			/* return the error thrown by the call to ioctl */
119433d6423SLionel Sambuc 			errno= ioctl_errno;
120433d6423SLionel Sambuc 			return -1;
121433d6423SLionel Sambuc 		}
122433d6423SLionel Sambuc 	}
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc 	r= fstat(sv[1], &sbuf);
125433d6423SLionel Sambuc 	if (r == -1) {
126433d6423SLionel Sambuc 		int fstat_errno;
127433d6423SLionel Sambuc 
128433d6423SLionel Sambuc 		/* if that failed rollback socket creation */
129433d6423SLionel Sambuc 		fstat_errno= errno;
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc 		close(sv[0]);
132433d6423SLionel Sambuc 		close(sv[1]);
133433d6423SLionel Sambuc 
134433d6423SLionel Sambuc 		/* return the error thrown by the call to fstat */
135433d6423SLionel Sambuc 		errno= fstat_errno;
136433d6423SLionel Sambuc 		return -1;
137433d6423SLionel Sambuc 	}
138433d6423SLionel Sambuc 
1392e89653eSDavid van Moolenbroek 	dev = sbuf.st_rdev;
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc 	/* connect the sockets sv[0] and sv[1] */
142433d6423SLionel Sambuc 	r= ioctl(sv[0], NWIOSUDSPAIR, &dev);
143433d6423SLionel Sambuc 	if (r == -1) {
144433d6423SLionel Sambuc 		int ioctl_errno;
145433d6423SLionel Sambuc 
146433d6423SLionel Sambuc 		/* if that failed rollback socket creation */
147433d6423SLionel Sambuc 		ioctl_errno= errno;
148433d6423SLionel Sambuc 
149433d6423SLionel Sambuc 		close(sv[0]);
150433d6423SLionel Sambuc 		close(sv[1]);
151433d6423SLionel Sambuc 
152433d6423SLionel Sambuc 		/* return the error thrown by the call to ioctl */
153433d6423SLionel Sambuc 		errno= ioctl_errno;
154433d6423SLionel Sambuc 		return -1;
155433d6423SLionel Sambuc 	}
156433d6423SLionel Sambuc 
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc 	return 0;
159433d6423SLionel Sambuc }
160