mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Improved error coverage
This commit is contained in:
parent
e722eab892
commit
499d1628c7
2 changed files with 50 additions and 27 deletions
|
@ -442,7 +442,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a return value to the client for an RPC
|
* Send a 'retval' and 'errno' to the client for an RPC over connection->rpcSock
|
||||||
*/
|
*/
|
||||||
int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _errno = 0)
|
int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _errno = 0)
|
||||||
{
|
{
|
||||||
|
@ -642,8 +642,6 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
|
||||||
if(l->conn) {
|
if(l->conn) {
|
||||||
switch(err)
|
switch(err)
|
||||||
{
|
{
|
||||||
// FIXME: Check if connection is pending first?
|
|
||||||
|
|
||||||
case ERR_MEM:
|
case ERR_MEM:
|
||||||
fprintf(stderr, "nc_err(): ERR_MEM->ENOMEM\n");
|
fprintf(stderr, "nc_err(): ERR_MEM->ENOMEM\n");
|
||||||
l->tap->send_return_value(l->conn, -1, ENOMEM);
|
l->tap->send_return_value(l->conn, -1, ENOMEM);
|
||||||
|
@ -818,7 +816,7 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha
|
||||||
[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.
|
||||||
|
|
||||||
[X] ENOMEM - Insufficient kernel memory was available. ???
|
[X] ENOMEM - Insufficient kernel memory was available.
|
||||||
|
|
||||||
- The following errors are specific to UNIX domain (AF_UNIX) sockets:
|
- The following errors are specific to UNIX domain (AF_UNIX) sockets:
|
||||||
|
|
||||||
|
@ -857,9 +855,9 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||||
if(err == ERR_USE)
|
if(err == ERR_USE)
|
||||||
send_return_value(conn, -1, EADDRINUSE);
|
send_return_value(conn, -1, EADDRINUSE);
|
||||||
if(err == ERR_MEM)
|
if(err == ERR_MEM)
|
||||||
send_return_value(conn, -1, ENOMEM); // FIXME: Likely won't happen
|
|
||||||
if(err == ERR_BUF)
|
|
||||||
send_return_value(conn, -1, ENOMEM);
|
send_return_value(conn, -1, ENOMEM);
|
||||||
|
if(err == ERR_BUF)
|
||||||
|
send_return_value(conn, -1, ENOMEM); // FIXME: Closest match
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
send_return_value(conn, ERR_OK, ERR_OK); // Success
|
send_return_value(conn, ERR_OK, ERR_OK); // Success
|
||||||
|
@ -870,10 +868,10 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||||
send_return_value(conn, -1, EINVAL);
|
send_return_value(conn, -1, EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else {
|
else {
|
||||||
// fprintf(stderr, "handle_bind(): can't locate connection for PCB\n");
|
fprintf(stderr, "handle_bind(): can't locate connection for PCB\n");
|
||||||
// send_return_value(conn, -1, EBADF); // FIXME: This makes no sense
|
send_return_value(conn, -1, EBADF);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -890,7 +888,7 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||||
- := Not needed
|
- := Not needed
|
||||||
|
|
||||||
[?] EADDRINUSE - Another socket is already listening on the same port.
|
[?] EADDRINUSE - Another socket is already listening on the same port.
|
||||||
[I] EBADF - The argument sockfd is not a valid descriptor.
|
[IX] EBADF - The argument sockfd is not a valid descriptor.
|
||||||
[I] ENOTSOCK - The argument sockfd is not a socket.
|
[I] ENOTSOCK - The argument sockfd is not a socket.
|
||||||
[I] EOPNOTSUPP - The socket is not of a type that supports the listen() operation.
|
[I] EOPNOTSUPP - The socket is not of a type that supports the listen() operation.
|
||||||
|
|
||||||
|
@ -923,7 +921,13 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "handle_listen(): unable to allocate memory for new listening PCB\n");
|
fprintf(stderr, "handle_listen(): unable to allocate memory for new listening PCB\n");
|
||||||
send_return_value(conn, -1, ENOMEM); // FIXME: This does not have an equivalent errno value
|
// FIXME: This does not have an equivalent errno value
|
||||||
|
// lwip will reclaim space with a tcp_listen call since a PCB in a LISTEN
|
||||||
|
// state takes up less space. If something goes wrong during the creation of a
|
||||||
|
// new listening socket we should return an error that implies we can't use this
|
||||||
|
// socket, even if the reason isn't describing what really happened internally.
|
||||||
|
// See: http://lwip.wikia.com/wiki/Raw/TCP
|
||||||
|
send_return_value(conn, -1, EBADF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -963,12 +967,13 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
|
||||||
*/
|
*/
|
||||||
void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc)
|
void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc)
|
||||||
{
|
{
|
||||||
|
int rpc_fd = _phy.getDescriptor(sock);
|
||||||
struct tcp_pcb *newpcb = lwipstack->tcp_new();
|
struct tcp_pcb *newpcb = lwipstack->tcp_new();
|
||||||
if(newpcb != NULL) {
|
if(newpcb != NULL) {
|
||||||
ZT_PHY_SOCKFD_TYPE fds[2];
|
ZT_PHY_SOCKFD_TYPE fds[2];
|
||||||
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
|
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
|
||||||
if(errno < 0) {
|
if(errno < 0) {
|
||||||
send_return_value(_phy.getDescriptor(sock), -1, errno);
|
send_return_value(rpc_fd, -1, errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,7 +989,6 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
|
||||||
new_conn->pending = true;
|
new_conn->pending = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int rpc_fd = _phy.getDescriptor(sock);
|
|
||||||
sock_fd_write(rpc_fd, -1); // Send a bad fd, to signal error
|
sock_fd_write(rpc_fd, -1); // Send a bad fd, to signal error
|
||||||
fprintf(stderr, "handle_socket(): Memory not available for new PCB\n");
|
fprintf(stderr, "handle_socket(): Memory not available for new PCB\n");
|
||||||
send_return_value(rpc_fd, -1, ENOMEM);
|
send_return_value(rpc_fd, -1, ENOMEM);
|
||||||
|
@ -1008,20 +1012,22 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
|
||||||
|
|
||||||
[-] EACCES - For UNIX domain sockets, which are identified by pathname: Write permission is denied ...
|
[-] EACCES - For UNIX domain sockets, which are identified by pathname: Write permission is denied ...
|
||||||
[?] EACCES, EPERM - The user tried to connect to a broadcast address without having the socket broadcast flag enabled ...
|
[?] EACCES, EPERM - The user tried to connect to a broadcast address without having the socket broadcast flag enabled ...
|
||||||
[i] EADDRINUSE - Local address is already in use.
|
[X] EADDRINUSE - Local address is already in use.
|
||||||
[I] EAFNOSUPPORT - The passed address didn't have the correct address family in its sa_family field.
|
[I] EAFNOSUPPORT - The passed address didn't have the correct address family in its sa_family field.
|
||||||
[?] EAGAIN - No more free local ports or insufficient entries in the routing cache.
|
[X] EAGAIN - No more free local ports or insufficient entries in the routing cache.
|
||||||
[ ] EALREADY - The socket is nonblocking and a previous connection attempt has not yet been completed.
|
[ ] EALREADY - The socket is nonblocking and a previous connection attempt has not yet been completed.
|
||||||
[I] EBADF - The file descriptor is not a valid index in the descriptor table.
|
[IX] EBADF - The file descriptor is not a valid index in the descriptor table.
|
||||||
[ ] ECONNREFUSED - No-one listening on the remote address.
|
[ ] ECONNREFUSED - No-one listening on the remote address.
|
||||||
[i] EFAULT - The socket structure address is outside the user's address space.
|
[i] EFAULT - The socket structure address is outside the user's address space.
|
||||||
[ ] EINPROGRESS - The socket is nonblocking and the connection cannot be completed immediately.
|
[ ] EINPROGRESS - The socket is nonblocking and the connection cannot be completed immediately.
|
||||||
[-] EINTR - The system call was interrupted by a signal that was caught.
|
[-] EINTR - The system call was interrupted by a signal that was caught.
|
||||||
[X] EISCONN - The socket is already connected.
|
[X] EISCONN - The socket is already connected.
|
||||||
[?] ENETUNREACH - Network is unreachable.
|
[X] ENETUNREACH - Network is unreachable.
|
||||||
[I] ENOTSOCK - The file descriptor is not associated with a socket.
|
[I] ENOTSOCK - The file descriptor is not associated with a socket.
|
||||||
[X] ETIMEDOUT - Timeout while attempting connection.
|
[X] ETIMEDOUT - Timeout while attempting connection.
|
||||||
|
|
||||||
|
[X] EINVAL - Invalid argument, SVr4, generally makes sense to set this
|
||||||
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc)
|
void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc)
|
||||||
|
@ -1033,7 +1039,7 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
|
||||||
ip_addr_t conn_addr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr);
|
ip_addr_t conn_addr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr);
|
||||||
|
|
||||||
if(conn != NULL) {
|
if(conn != NULL) {
|
||||||
lwipstack->tcp_sent(conn->pcb, nc_sent); // FIXME: Move?
|
lwipstack->tcp_sent(conn->pcb, nc_sent);
|
||||||
lwipstack->tcp_recv(conn->pcb, nc_recved);
|
lwipstack->tcp_recv(conn->pcb, nc_recved);
|
||||||
lwipstack->tcp_err(conn->pcb, nc_err);
|
lwipstack->tcp_err(conn->pcb, nc_err);
|
||||||
lwipstack->tcp_poll(conn->pcb, nc_poll, APPLICATION_POLL_FREQ);
|
lwipstack->tcp_poll(conn->pcb, nc_poll, APPLICATION_POLL_FREQ);
|
||||||
|
@ -1042,25 +1048,41 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if((err = lwipstack->tcp_connect(conn->pcb,&conn_addr,conn_port, nc_connected)) < 0)
|
if((err = lwipstack->tcp_connect(conn->pcb,&conn_addr,conn_port, nc_connected)) < 0)
|
||||||
{
|
{
|
||||||
|
if(err == ERR_ISCONN) {
|
||||||
|
send_return_value(conn, -1, EISCONN); // Already in connected state
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(err == ERR_USE) {
|
if(err == ERR_USE) {
|
||||||
send_return_value(conn, -1, EISCONN); // Already in use
|
send_return_value(conn, -1, EADDRINUSE); // Already in use
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(err == ERR_VAL) {
|
if(err == ERR_VAL) {
|
||||||
send_return_value(conn, -1, EAFNOSUPPORT); // FIXME: Invalid arguments?
|
send_return_value(conn, -1, EINVAL); // Invalid ipaddress parameter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(err == ERR_RTE) {
|
if(err == ERR_RTE) {
|
||||||
send_return_value(conn, -1, ENETUNREACH); // FIXME: Host unreachable
|
send_return_value(conn, -1, ENETUNREACH); // No route to host
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(err == ERR_BUF)
|
if(err == ERR_BUF) {
|
||||||
{
|
send_return_value(conn, -1, EAGAIN); // No more ports available
|
||||||
// FIXME
|
return;
|
||||||
}
|
}
|
||||||
if(err == ERR_MEM)
|
if(err == ERR_MEM)
|
||||||
{
|
{
|
||||||
// FIXME: return value originates from tcp_enqueue_flags()
|
/* Can occur for the following reasons: tcp_enqueue_flags()
|
||||||
|
|
||||||
|
1) tcp_enqueue_flags is always called with either SYN or FIN in flags.
|
||||||
|
We need one available snd_buf byte to do that.
|
||||||
|
This means we can't send FIN while snd_buf==0. A better fix would be to
|
||||||
|
not include SYN and FIN sequence numbers in the snd_buf count.
|
||||||
|
|
||||||
|
2) Cannot allocate new pbuf
|
||||||
|
3) Cannot allocate new TCP segment
|
||||||
|
|
||||||
|
*/
|
||||||
|
send_return_value(conn, -1, EAGAIN); // FIXME: Doesn't describe the problem well, but closest match
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should only return a value if failure happens immediately
|
// We should only return a value if failure happens immediately
|
||||||
|
@ -1071,13 +1093,14 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
|
||||||
// - Most instances of a retval for a connect() should happen
|
// - Most instances of a retval for a connect() should happen
|
||||||
// in the nc_connect() and nc_err() callbacks!
|
// in the nc_connect() and nc_err() callbacks!
|
||||||
fprintf(stderr, "handle_connect(): unable to connect\n");
|
fprintf(stderr, "handle_connect(): unable to connect\n");
|
||||||
send_return_value(conn, -1, err); // FIXME: Only catch unhandled errors
|
send_return_value(conn, -1, EAGAIN);
|
||||||
}
|
}
|
||||||
// Everything seems to be ok, but we don't have enough info to retval
|
// Everything seems to be ok, but we don't have enough info to retval
|
||||||
conn->pending=true;
|
conn->pending=true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "could not locate PCB based on their fd\n");
|
fprintf(stderr, "could not locate PCB based on their fd\n");
|
||||||
|
send_return_value(conn, -1, EBADF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
netcon/libintercept.so.1.0
Executable file
BIN
netcon/libintercept.so.1.0
Executable file
Binary file not shown.
Loading…
Add table
Reference in a new issue