mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Improved bind() logic, added more error handling to accept()
This commit is contained in:
parent
8a05efa365
commit
aa6ff039c4
3 changed files with 48 additions and 23 deletions
|
@ -490,6 +490,12 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
|
||||||
* @param error code
|
* @param error code
|
||||||
* @return ERR_OK if everything is ok, -1 otherwise
|
* @return ERR_OK if everything is ok, -1 otherwise
|
||||||
|
|
||||||
|
i := should be implemented in intercept lib
|
||||||
|
I := is implemented in intercept lib
|
||||||
|
X := is implemented in service
|
||||||
|
? := required treatment Unknown
|
||||||
|
- := Not needed
|
||||||
|
|
||||||
[ ] EAGAIN or EWOULDBLOCK - The socket is marked nonblocking and no connections are present
|
[ ] EAGAIN or EWOULDBLOCK - The socket is marked nonblocking and no connections are present
|
||||||
to be accepted. POSIX.1-2001 allows either error to be returned for
|
to be accepted. POSIX.1-2001 allows either error to be returned for
|
||||||
this case, and does not require these constants to have the same value,
|
this case, and does not require these constants to have the same value,
|
||||||
|
@ -499,12 +505,12 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
|
||||||
[i] EFAULT - The addr argument is not in a writable part of the user address space.
|
[i] EFAULT - The addr argument is not in a writable part of the user address space.
|
||||||
[ ] EINTR - The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
[ ] EINTR - The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
||||||
[ ] EINVAL - Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
[ ] EINVAL - Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
||||||
[ ] EINVAL - (accept4()) invalid value in flags.
|
[I] EINVAL - (accept4()) invalid value in flags.
|
||||||
[I] EMFILE - The per-process limit of open file descriptors has been reached.
|
[I] EMFILE - The per-process limit of open file descriptors has been reached.
|
||||||
[ ] ENFILE - The system limit on the total number of open files has been reached.
|
[ ] ENFILE - The system limit on the total number of open files has been reached.
|
||||||
[ ] ENOBUFS, ENOMEM - Not enough free memory. This often means that the memory allocation is
|
[ ] ENOBUFS, ENOMEM - Not enough free memory. This often means that the memory allocation is
|
||||||
limited by the socket buffer limits, not by the system memory.
|
limited by the socket buffer limits, not by the system memory.
|
||||||
[i] ENOTSOCK - The descriptor references a file, not a socket.
|
[I] ENOTSOCK - The descriptor references a file, not a socket.
|
||||||
[I] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM.
|
[I] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM.
|
||||||
[ ] EPROTO - Protocol error.
|
[ ] EPROTO - Protocol error.
|
||||||
|
|
||||||
|
@ -802,10 +808,12 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha
|
||||||
|
|
||||||
[ ] EACCES - The address is protected, and the user is not the superuser.
|
[ ] EACCES - The address is protected, and the user is not the superuser.
|
||||||
[X] EADDRINUSE - The given address is already in use.
|
[X] EADDRINUSE - The given address is already in use.
|
||||||
[X] EBADF - sockfd is not a valid descriptor.
|
[I] EBADF - sockfd is not a valid descriptor.
|
||||||
[X] EINVAL - The socket is already bound to an address.
|
[X] EINVAL - The socket is already bound to an address.
|
||||||
[i] ENOTSOCK - sockfd is a descriptor for a file, not a socket.
|
[I] ENOTSOCK - sockfd is a descriptor for a file, not a socket.
|
||||||
[-] The following errors are specific to UNIX domain (AF_UNIX) sockets:
|
|
||||||
|
- The following errors are specific to UNIX domain (AF_UNIX) sockets:
|
||||||
|
|
||||||
[-] EACCES - Search permission is denied on a component of the path prefix. (See also path_resolution(7).)
|
[-] EACCES - Search permission is denied on a component of the path prefix. (See also path_resolution(7).)
|
||||||
[-] EADDRNOTAVAIL - A nonexistent interface was requested or the requested address was not local.
|
[-] EADDRNOTAVAIL - A nonexistent interface was requested or the requested address was not local.
|
||||||
[-] EFAULT - addr points outside the user's accessible address space.
|
[-] EFAULT - addr points outside the user's accessible address space.
|
||||||
|
|
|
@ -688,6 +688,21 @@ int poll(POLL_SIG)
|
||||||
bind() intercept function */
|
bind() intercept function */
|
||||||
int bind(BIND_SIG)
|
int bind(BIND_SIG)
|
||||||
{
|
{
|
||||||
|
#ifdef CHECKS
|
||||||
|
/* Check that this is a valid fd */
|
||||||
|
if(fcntl(sockfd, F_GETFD) < 0) {
|
||||||
|
return -1;
|
||||||
|
errno = EBADF;
|
||||||
|
}
|
||||||
|
/* Check that it is a socket */
|
||||||
|
int sock_type = -1;
|
||||||
|
socklen_t sock_type_len = sizeof(sock_type);
|
||||||
|
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
|
||||||
|
errno = ENOTSOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
#ifdef DUMMY
|
#ifdef DUMMY
|
||||||
dwr("bind(%d)\n", sockfd);
|
dwr("bind(%d)\n", sockfd);
|
||||||
|
@ -697,28 +712,23 @@ int bind(BIND_SIG)
|
||||||
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
|
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
|
||||||
return(realbind(sockfd, addr, addrlen));
|
return(realbind(sockfd, addr, addrlen));
|
||||||
|
|
||||||
int sock_type = -1;
|
/* If local, just use normal syscall */
|
||||||
socklen_t sock_type_len = sizeof(sock_type);
|
|
||||||
struct sockaddr_in *connaddr;
|
struct sockaddr_in *connaddr;
|
||||||
connaddr = (struct sockaddr_in *) addr;
|
connaddr = (struct sockaddr_in *) addr;
|
||||||
|
|
||||||
getsockopt(sockfd, SOL_SOCKET, SO_TYPE,
|
|
||||||
(void *) &sock_type, &sock_type_len);
|
|
||||||
|
|
||||||
if (addr != NULL && (connaddr->sin_family == AF_LOCAL
|
if (addr != NULL && (connaddr->sin_family == AF_LOCAL
|
||||||
|| connaddr->sin_family == PF_NETLINK
|
|| connaddr->sin_family == PF_NETLINK
|
||||||
|| connaddr->sin_family == AF_NETLINK
|
|| connaddr->sin_family == AF_NETLINK
|
||||||
|| connaddr->sin_family == AF_UNIX)) {
|
|| connaddr->sin_family == AF_UNIX))
|
||||||
return(realbind(sockfd, addr, addrlen));
|
{
|
||||||
|
if(realbind == NULL) {
|
||||||
|
dwr("Unresolved symbol: bind(). Library is exiting.\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return(realbind(sockfd, addr, addrlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
char cmd[BUF_SZ];
|
|
||||||
if(realbind == NULL) {
|
|
||||||
dwr("Unresolved symbol: bind()\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assemble and route command */
|
/* Assemble and route command */
|
||||||
|
char cmd[BUF_SZ];
|
||||||
struct bind_st rpc_st;
|
struct bind_st rpc_st;
|
||||||
rpc_st.sockfd = sockfd;
|
rpc_st.sockfd = sockfd;
|
||||||
rpc_st.__tid = syscall(SYS_gettid);
|
rpc_st.__tid = syscall(SYS_gettid);
|
||||||
|
@ -768,16 +778,22 @@ int accept(ACCEPT_SIG)
|
||||||
#ifdef CHECKS
|
#ifdef CHECKS
|
||||||
/* Check that this is a valid fd */
|
/* Check that this is a valid fd */
|
||||||
if(fcntl(sockfd, F_GETFD) < 0) {
|
if(fcntl(sockfd, F_GETFD) < 0) {
|
||||||
|
dwr("EBADF\n");
|
||||||
return -1;
|
return -1;
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
}
|
}
|
||||||
int sock_type = -1;
|
/* Check that it is a socket */
|
||||||
|
int sock_type;
|
||||||
socklen_t sock_type_len = sizeof(sock_type);
|
socklen_t sock_type_len = sizeof(sock_type);
|
||||||
getsockopt(sockfd, SOL_SOCKET, SO_TYPE,
|
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
|
||||||
(void *) &sock_type, &sock_type_len);
|
errno = ENOTSOCK;
|
||||||
|
dwr("ENOTSOCK\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* Check that this socket supports accept() */
|
/* Check that this socket supports accept() */
|
||||||
if(!(sock_type & (SOCK_STREAM | SOCK_SEQPACKET))) {
|
if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
|
||||||
errno = EOPNOTSUPP;
|
errno = EOPNOTSUPP;
|
||||||
|
dwr("EOPNOTSUPP\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Check that we haven't hit the soft-limit file descriptors allowed */
|
/* Check that we haven't hit the soft-limit file descriptors allowed */
|
||||||
|
@ -785,6 +801,7 @@ int accept(ACCEPT_SIG)
|
||||||
getrlimit(RLIMIT_NOFILE, &rl);
|
getrlimit(RLIMIT_NOFILE, &rl);
|
||||||
if(sockfd >= rl.rlim_cur){
|
if(sockfd >= rl.rlim_cur){
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
|
dwr("EMFILE\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue