11 #include <sys/ioctl.h>
12 #include <sys/socket.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.
32 __accept(int fd
, struct sockaddr
* __restrict address
,
33 socklen_t
* __restrict address_len
)
38 if (address
!= NULL
&& address_len
== NULL
) {
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)
52 *address_len
= m
.m_vfs_lc_socklen
.len
;
56 int accept(int sock
, struct sockaddr
*__restrict address
,
57 socklen_t
*__restrict address_len
)
62 r
= __accept(sock
, address
, address_len
);
63 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
66 r
= _tcp_accept(sock
, address
, address_len
);
67 if (r
!= -1 || errno
!= ENOTTY
)
70 r
= _uds_accept(sock
, address
, address_len
);
71 if (r
!= -1 || errno
!= ENOTTY
)
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
)) {
89 static int _tcp_accept(int sock
, struct sockaddr
*__restrict address
,
90 socklen_t
*__restrict address_len
)
95 s1
= open(TCP_DEVICE
, O_RDWR
);
98 r
= ioctl(s1
, NWIOGTCPCOOKIE
, &cookie
);
106 r
= ioctl(sock
, NWIOTCPACCEPTTO
, &cookie
);
115 getpeername(s1
, address
, address_len
);
119 static int _uds_accept(int sock
, struct sockaddr
*__restrict address
,
120 socklen_t
*__restrict address_len
)
124 struct sockaddr_un uds_addr
;
127 memset(&uds_addr
, '\0', sizeof(struct sockaddr_un
));
129 r
= ioctl(sock
, NWIOGUDSADDR
, &uds_addr
);
134 if (uds_addr
.sun_family
!= AF_UNIX
) {
140 if (len
> sizeof(struct sockaddr_un
))
141 len
= sizeof(struct sockaddr_un
);
143 memcpy(address
, &uds_addr
, len
);
146 s1
= open(UDS_DEVICE
, O_RDWR
);
150 /* Copy file descriptor flags from the listening socket. */
151 fcntl(s1
, F_SETFL
, fcntl(sock
, F_GETFL
));
153 r
= ioctl(s1
, NWIOSUDSACCEPT
, address
);
155 int ioctl_errno
= errno
;