etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / accept.c
blobe1eeed821dc436d0fb1b09db2289e74e85a000ed
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/socket.h>
13 #include <sys/un.h>
15 #include <net/netlib.h>
16 #include <net/gen/in.h>
17 #include <net/gen/tcp.h>
18 #include <net/gen/tcp_io.h>
19 #include <net/gen/udp.h>
20 #include <net/gen/udp_io.h>
22 static int _tcp_accept(int sock, struct sockaddr *__restrict address,
23 socklen_t *__restrict address_len);
25 static int _uds_accept(int sock, struct sockaddr *__restrict address,
26 socklen_t *__restrict address_len);
29 * Accept a connection on a listening socket, creating a new socket.
31 static int
32 __accept(int fd, struct sockaddr * __restrict address,
33 socklen_t * __restrict address_len)
35 message m;
36 int r;
38 if (address != NULL && address_len == NULL) {
39 errno = EFAULT;
40 return -1;
43 memset(&m, 0, sizeof(m));
44 m.m_lc_vfs_sockaddr.fd = fd;
45 m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
46 m.m_lc_vfs_sockaddr.addr_len = (address != NULL) ? *address_len : 0;
48 if ((r = _syscall(VFS_PROC_NR, VFS_ACCEPT, &m)) < 0)
49 return -1;
51 if (address != NULL)
52 *address_len = m.m_vfs_lc_socklen.len;
53 return r;
56 int accept(int sock, struct sockaddr *__restrict address,
57 socklen_t *__restrict address_len)
59 int r;
60 nwio_udpopt_t udpopt;
62 r = __accept(sock, address, address_len);
63 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
64 return r;
66 r= _tcp_accept(sock, address, address_len);
67 if (r != -1 || errno != ENOTTY)
68 return r;
70 r= _uds_accept(sock, address, address_len);
71 if (r != -1 || errno != ENOTTY)
72 return r;
74 /* Unfortunately, we have to return EOPNOTSUPP for a socket that
75 * does not support accept (such as a UDP socket) and ENOTSOCK for
76 * filedescriptors that do not refer to a socket.
78 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
79 if (r == 0 || (r == -1 && errno != ENOTTY)) {
80 /* UDP socket */
81 errno= EOPNOTSUPP;
82 return -1;
85 errno = ENOTSOCK;
86 return -1;
89 static int _tcp_accept(int sock, struct sockaddr *__restrict address,
90 socklen_t *__restrict address_len)
92 int r, s1, t_errno;
93 tcp_cookie_t cookie;
95 s1= open(TCP_DEVICE, O_RDWR);
96 if (s1 == -1)
97 return s1;
98 r= ioctl(s1, NWIOGTCPCOOKIE, &cookie);
99 if (r == -1)
101 t_errno= errno;
102 close(s1);
103 errno= t_errno;
104 return -1;
106 r= ioctl(sock, NWIOTCPACCEPTTO, &cookie);
107 if (r == -1)
109 t_errno= errno;
110 close(s1);
111 errno= t_errno;
112 return -1;
114 if (address != NULL)
115 getpeername(s1, address, address_len);
116 return s1;
119 static int _uds_accept(int sock, struct sockaddr *__restrict address,
120 socklen_t *__restrict address_len)
122 int s1;
123 int r;
124 struct sockaddr_un uds_addr;
125 socklen_t len;
127 memset(&uds_addr, '\0', sizeof(struct sockaddr_un));
129 r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
130 if (r == -1) {
131 return r;
134 if (uds_addr.sun_family != AF_UNIX) {
135 errno= EINVAL;
136 return -1;
139 len= *address_len;
140 if (len > sizeof(struct sockaddr_un))
141 len = sizeof(struct sockaddr_un);
143 memcpy(address, &uds_addr, len);
144 *address_len= len;
146 s1= open(UDS_DEVICE, O_RDWR);
147 if (s1 == -1)
148 return s1;
150 /* Copy file descriptor flags from the listening socket. */
151 fcntl(s1, F_SETFL, fcntl(sock, F_GETFL));
153 r= ioctl(s1, NWIOSUDSACCEPT, address);
154 if (r == -1) {
155 int ioctl_errno = errno;
156 close(s1);
157 errno = ioctl_errno;
158 return r;
161 return s1;