xref: /minix3/minix/lib/libc/sys/accept.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 <fcntl.h>
6*433d6423SLionel Sambuc #include <stdio.h>
7*433d6423SLionel Sambuc #include <stdlib.h>
8*433d6423SLionel Sambuc #include <unistd.h>
9*433d6423SLionel Sambuc #include <string.h>
10*433d6423SLionel Sambuc #include <sys/ioctl.h>
11*433d6423SLionel Sambuc #include <sys/socket.h>
12*433d6423SLionel Sambuc #include <sys/un.h>
13*433d6423SLionel Sambuc 
14*433d6423SLionel Sambuc #include <net/netlib.h>
15*433d6423SLionel Sambuc #include <net/gen/in.h>
16*433d6423SLionel Sambuc #include <net/gen/tcp.h>
17*433d6423SLionel Sambuc #include <net/gen/tcp_io.h>
18*433d6423SLionel Sambuc #include <net/gen/udp.h>
19*433d6423SLionel Sambuc #include <net/gen/udp_io.h>
20*433d6423SLionel Sambuc 
21*433d6423SLionel Sambuc #define DEBUG 0
22*433d6423SLionel Sambuc 
23*433d6423SLionel Sambuc static int _tcp_accept(int sock, struct sockaddr *__restrict address,
24*433d6423SLionel Sambuc 	socklen_t *__restrict address_len);
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc static int _uds_accept(int sock, struct sockaddr *__restrict address,
27*433d6423SLionel Sambuc 	socklen_t *__restrict address_len);
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc int accept(int sock, struct sockaddr *__restrict address,
30*433d6423SLionel Sambuc 	socklen_t *__restrict address_len)
31*433d6423SLionel Sambuc {
32*433d6423SLionel Sambuc 	int r;
33*433d6423SLionel Sambuc 	nwio_udpopt_t udpopt;
34*433d6423SLionel Sambuc 
35*433d6423SLionel Sambuc 	r= _tcp_accept(sock, address, address_len);
36*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
37*433d6423SLionel Sambuc 		return r;
38*433d6423SLionel Sambuc 
39*433d6423SLionel Sambuc 	r= _uds_accept(sock, address, address_len);
40*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
41*433d6423SLionel Sambuc 		return r;
42*433d6423SLionel Sambuc 
43*433d6423SLionel Sambuc 	/* Unfortunately, we have to return EOPNOTSUPP for a socket that
44*433d6423SLionel Sambuc 	 * does not support accept (such as a UDP socket) and ENOTSOCK for
45*433d6423SLionel Sambuc 	 * filedescriptors that do not refer to a socket.
46*433d6423SLionel Sambuc 	 */
47*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGUDPOPT, &udpopt);
48*433d6423SLionel Sambuc 	if (r == 0)
49*433d6423SLionel Sambuc 	{
50*433d6423SLionel Sambuc 		/* UDP socket */
51*433d6423SLionel Sambuc 		errno= EOPNOTSUPP;
52*433d6423SLionel Sambuc 		return -1;
53*433d6423SLionel Sambuc 	}
54*433d6423SLionel Sambuc 	if (errno == ENOTTY)
55*433d6423SLionel Sambuc 	{
56*433d6423SLionel Sambuc 		errno= ENOTSOCK;
57*433d6423SLionel Sambuc 		return -1;
58*433d6423SLionel Sambuc 	}
59*433d6423SLionel Sambuc 
60*433d6423SLionel Sambuc 	return r;
61*433d6423SLionel Sambuc }
62*433d6423SLionel Sambuc 
63*433d6423SLionel Sambuc static int _tcp_accept(int sock, struct sockaddr *__restrict address,
64*433d6423SLionel Sambuc 	socklen_t *__restrict address_len)
65*433d6423SLionel Sambuc {
66*433d6423SLionel Sambuc 	int r, s1, t_errno;
67*433d6423SLionel Sambuc 	tcp_cookie_t cookie;
68*433d6423SLionel Sambuc 
69*433d6423SLionel Sambuc 	s1= open(TCP_DEVICE, O_RDWR);
70*433d6423SLionel Sambuc 	if (s1 == -1)
71*433d6423SLionel Sambuc 		return s1;
72*433d6423SLionel Sambuc 	r= ioctl(s1, NWIOGTCPCOOKIE, &cookie);
73*433d6423SLionel Sambuc 	if (r == -1)
74*433d6423SLionel Sambuc 	{
75*433d6423SLionel Sambuc 		t_errno= errno;
76*433d6423SLionel Sambuc 		close(s1);
77*433d6423SLionel Sambuc 		errno= t_errno;
78*433d6423SLionel Sambuc 		return -1;
79*433d6423SLionel Sambuc 	}
80*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOTCPACCEPTTO, &cookie);
81*433d6423SLionel Sambuc 	if (r == -1)
82*433d6423SLionel Sambuc 	{
83*433d6423SLionel Sambuc 		t_errno= errno;
84*433d6423SLionel Sambuc 		close(s1);
85*433d6423SLionel Sambuc 		errno= t_errno;
86*433d6423SLionel Sambuc 		return -1;
87*433d6423SLionel Sambuc 	}
88*433d6423SLionel Sambuc 	if (address != NULL)
89*433d6423SLionel Sambuc 		getpeername(s1, address, address_len);
90*433d6423SLionel Sambuc 	return s1;
91*433d6423SLionel Sambuc }
92*433d6423SLionel Sambuc 
93*433d6423SLionel Sambuc static int _uds_accept(int sock, struct sockaddr *__restrict address,
94*433d6423SLionel Sambuc 	socklen_t *__restrict address_len)
95*433d6423SLionel Sambuc {
96*433d6423SLionel Sambuc 	int s1;
97*433d6423SLionel Sambuc 	int r;
98*433d6423SLionel Sambuc 	struct sockaddr_un uds_addr;
99*433d6423SLionel Sambuc 	socklen_t len;
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc 	memset(&uds_addr, '\0', sizeof(struct sockaddr_un));
102*433d6423SLionel Sambuc 
103*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
104*433d6423SLionel Sambuc 	if (r == -1) {
105*433d6423SLionel Sambuc 		return r;
106*433d6423SLionel Sambuc 	}
107*433d6423SLionel Sambuc 
108*433d6423SLionel Sambuc 	if (uds_addr.sun_family != AF_UNIX) {
109*433d6423SLionel Sambuc 		errno= EINVAL;
110*433d6423SLionel Sambuc 		return -1;
111*433d6423SLionel Sambuc 	}
112*433d6423SLionel Sambuc 
113*433d6423SLionel Sambuc 	len= *address_len;
114*433d6423SLionel Sambuc 	if (len > sizeof(struct sockaddr_un))
115*433d6423SLionel Sambuc 		len = sizeof(struct sockaddr_un);
116*433d6423SLionel Sambuc 
117*433d6423SLionel Sambuc 	memcpy(address, &uds_addr, len);
118*433d6423SLionel Sambuc 	*address_len= len;
119*433d6423SLionel Sambuc 
120*433d6423SLionel Sambuc 	s1= open(UDS_DEVICE, O_RDWR);
121*433d6423SLionel Sambuc 	if (s1 == -1)
122*433d6423SLionel Sambuc 		return s1;
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc 	/* Copy file descriptor flags from the listening socket. */
125*433d6423SLionel Sambuc 	fcntl(s1, F_SETFL, fcntl(sock, F_GETFL));
126*433d6423SLionel Sambuc 
127*433d6423SLionel Sambuc 	r= ioctl(s1, NWIOSUDSACCEPT, address);
128*433d6423SLionel Sambuc 	if (r == -1) {
129*433d6423SLionel Sambuc 		int ioctl_errno = errno;
130*433d6423SLionel Sambuc 		close(s1);
131*433d6423SLionel Sambuc 		errno = ioctl_errno;
132*433d6423SLionel Sambuc 		return r;
133*433d6423SLionel Sambuc 	}
134*433d6423SLionel Sambuc 
135*433d6423SLionel Sambuc 	return s1;
136*433d6423SLionel Sambuc }
137