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