mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-11 04:59:54 +00:00
Additional retval+errno handling
This commit is contained in:
parent
6b1a38f14c
commit
5dffa43201
@ -130,7 +130,7 @@
|
||||
* MEMP_NUM_RAW_PCB: Number of raw connection PCBs
|
||||
* (requires the LWIP_RAW option)
|
||||
*/
|
||||
#define MEMP_NUM_RAW_PCB 32
|
||||
#define MEMP_NUM_RAW_PCB 128
|
||||
|
||||
/**
|
||||
* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
|
||||
|
@ -1,29 +0,0 @@
|
||||
SHCC=gcc
|
||||
|
||||
# intercept-specific
|
||||
intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -D_GNU_SOURCE -DNETCON_INTERCEPT
|
||||
LIB_NAME = intercept
|
||||
SHLIB_EXT=dylib
|
||||
SHLIB_MAJOR = 1
|
||||
SHLIB_MINOR = 8
|
||||
COMMON = common
|
||||
OBJS= netcon/intercept.o
|
||||
SHLIB = ${LIB_NAME}.${SHLIB_EXT}.${SHLIB_MAJOR}.${SHLIB_MINOR}
|
||||
SHLDFLAGS = -g -O2 -Wall -I. -nostdlib -shared
|
||||
LIBS = -ldl -lc -lrt -lpthread
|
||||
|
||||
lib:
|
||||
${SHCC} $(intercept_CFLAGS) -I. netcon/intercept.c -o netcon/intercept.o
|
||||
${SHCC} $(intercept_CFLAGS) -I. netcon/common.c -o netcon/common.o
|
||||
${SHCC} $(intercept_CFLAGS) -I. netcon/sendfd.c -o netcon/sendfd.o
|
||||
${SHCC} $(SHLDFLAGS) netcon/intercept.o netcon/common.o netcon/sendfd.o -o netcon/libintercept.so.1.0 $(LIBS)
|
||||
|
||||
install:
|
||||
cp netcon/libintercept.so.1.0 /lib/libintercept.so.1.0
|
||||
ln -sf /lib/libintercept.so.1.0 /lib/libintercept
|
||||
/usr/bin/install -c netcon/intercept /usr/bin
|
||||
|
||||
uninstall:
|
||||
rm -r /lib/libintercept.so.1.0
|
||||
rm -r /lib/libintercept
|
||||
rm -r /usr/bin/intercept
|
@ -446,21 +446,29 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
||||
* Send a return value to the client for an RPC
|
||||
*/
|
||||
int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _errno = 0)
|
||||
{
|
||||
if(conn) {
|
||||
int n = send_return_value(_phy.getDescriptor(conn->rpcSock), retval, _errno);
|
||||
if(n > 0)
|
||||
conn->pending = false;
|
||||
else {
|
||||
fprintf(stderr, "Unable to send return value to the intercept. Closing connection\n");
|
||||
closeConnection(conn);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
|
||||
{
|
||||
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
|
||||
char retmsg[sz];
|
||||
memset(&retmsg, '\0', sizeof(retmsg));
|
||||
retmsg[0]=RPC_RETVAL;
|
||||
char retmsg[sz];
|
||||
memset(&retmsg, '\0', sizeof(retmsg));
|
||||
retmsg[0]=RPC_RETVAL;
|
||||
memcpy(&retmsg[1], &retval, sizeof(retval));
|
||||
memcpy(&retmsg[1]+sizeof(retval), &_errno, sizeof(_errno));
|
||||
int n = write(_phy.getDescriptor(conn->rpcSock), &retmsg, sz);
|
||||
if(n > 0)
|
||||
conn->pending = false;
|
||||
else {
|
||||
fprintf(stderr, "Unable to send return value to the intercept. Closing connection\n");
|
||||
closeConnection(conn);
|
||||
}
|
||||
return n;
|
||||
return write(fd, &retmsg, sz);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -484,6 +492,24 @@ int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _e
|
||||
* @param newly allocated PCB
|
||||
* @param error code
|
||||
* @return ERR_OK if everything is ok, -1 otherwise
|
||||
|
||||
[ ] 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
|
||||
this case, and does not require these constants to have the same value,
|
||||
so a portable application should check for both possibilities.
|
||||
[ ] EBADF - The descriptor is invalid.
|
||||
[?] ECONNABORTED - A connection has been aborted.
|
||||
[ ] 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).
|
||||
[ ] EINVAL - Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
||||
[ ] EINVAL - (accept4()) invalid value in flags.
|
||||
[ ] 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.
|
||||
[ ] 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.
|
||||
[ ] ENOTSOCK - The descriptor references a file, not a socket.
|
||||
[ ] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM.
|
||||
[ ] EPROTO - Protocol error.
|
||||
|
||||
*
|
||||
*/
|
||||
err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
@ -507,11 +533,10 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
|
||||
int send_fd = tap->_phy.getDescriptor(conn->rpcSock);
|
||||
|
||||
int n = write(larg_fd, "z", 1);
|
||||
int n = write(larg_fd, "z", 1); // accept() in library waits for this byte
|
||||
if(n > 0) {
|
||||
if(sock_fd_write(send_fd, fds[1]) > 0) {
|
||||
new_tcp_conn->pending = true;
|
||||
fprintf(stderr, "nc_accept(): socketpair = { our=%d, their=%d}\n", fds[0], fds[1]);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "nc_accept(%d): unable to send fd to client\n", larg_fd);
|
||||
@ -526,7 +551,7 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
tap->lwipstack->_tcp_err(newpcb, nc_err);
|
||||
tap->lwipstack->_tcp_sent(newpcb, nc_sent);
|
||||
tap->lwipstack->_tcp_poll(newpcb, nc_poll, 0.5);
|
||||
tcp_accepted(conn->pcb);
|
||||
tcp_accepted(conn->pcb); // Let lwIP know that it can queue additional incoming connections
|
||||
return ERR_OK;
|
||||
}
|
||||
else {
|
||||
@ -691,8 +716,6 @@ err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err
|
||||
* @param structure containing the data and parameters for this client's RPC
|
||||
*
|
||||
|
||||
TODO: set errno appropriately
|
||||
|
||||
[ ] EACCES - The address is protected, and the user is not the superuser.
|
||||
[X] EADDRINUSE - The given address is already in use.
|
||||
[X] EBADF - sockfd is not a valid descriptor.
|
||||
@ -718,7 +741,6 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||
int conn_port = lwipstack->ntohs(connaddr->sin_port);
|
||||
ip_addr_t conn_addr;
|
||||
conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
|
||||
|
||||
TcpConnection *conn = getConnectionByTheirFD(bind_rpc->sockfd);
|
||||
|
||||
if(conn) {
|
||||
@ -738,14 +760,18 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||
send_return_value(conn, -1, ENOMEM);
|
||||
}
|
||||
else {
|
||||
send_return_value(conn, ERR_OK, 0); // OK
|
||||
send_return_value(conn, ERR_OK, ERR_OK); // Success
|
||||
}
|
||||
}
|
||||
else fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n");
|
||||
send_return_value(conn, -1, EINVAL);
|
||||
else {
|
||||
fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n");
|
||||
send_return_value(conn, -1, EINVAL);
|
||||
}
|
||||
}
|
||||
else fprintf(stderr, "handle_bind(): can't locate connection for PCB\n");
|
||||
send_return_value(conn, -1, EBADF);
|
||||
else {
|
||||
fprintf(stderr, "handle_bind(): can't locate connection for PCB\n");
|
||||
send_return_value(conn, -1, EBADF); // FIXME: This makes no sense
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -754,6 +780,12 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||
* @param Client that is making the RPC
|
||||
* @param structure containing the data and parameters for this client's RPC
|
||||
*
|
||||
|
||||
[ ] EADDRINUSE - Another socket is already listening on the same port.
|
||||
[X] EBADF - The argument sockfd is not a valid descriptor.
|
||||
[ ] ENOTSOCK - The argument sockfd is not a socket.
|
||||
[ ] EOPNOTSUPP - The socket is not of a type that supports the listen() operation.
|
||||
|
||||
*/
|
||||
void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc)
|
||||
{
|
||||
@ -771,13 +803,16 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
|
||||
/* we need to wait for the client to send us the fd allocated on their end
|
||||
for this listening socket */
|
||||
conn->pending = true;
|
||||
send_return_value(conn, ERR_OK, ERR_OK);
|
||||
}
|
||||
else {
|
||||
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
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "handle_listen(): can't locate connection for PCB\n");
|
||||
send_return_value(conn, -1, EBADF);
|
||||
}
|
||||
}
|
||||
|
||||
@ -838,13 +873,16 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
|
||||
new_conn->their_fd = fds[1];
|
||||
tcp_connections.push_back(new_conn);
|
||||
sock_fd_write(_phy.getDescriptor(sock), fds[1]);
|
||||
//fprintf(stderr, "handle_socket(): socketpair = { our=%d, their=%d}\n", fds[0], fds[1]);
|
||||
/* Once the client tells us what its fd is for the other end,
|
||||
we can then complete the mapping */
|
||||
// Once the client tells us what its fd is for the other end, we can then complete the mapping
|
||||
new_conn->pending = true;
|
||||
}
|
||||
else {
|
||||
int rpc_fd = _phy.getDescriptor(sock);
|
||||
sock_fd_write(rpc_fd, -1); // Send a bad fd, to signal error
|
||||
fprintf(stderr, "handle_socket(): Memory not available for new PCB\n");
|
||||
if(send_return_value(rpc_fd, -1, ENOMEM) < 0) {
|
||||
fprintf(stderr, "handle_socket(): Unable to send return value\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,7 @@ private:
|
||||
void handle_write(TcpConnection *conn);
|
||||
|
||||
int send_return_value(TcpConnection *conn, int retval, int _errno);
|
||||
int send_return_value(int fd, int retval, int _errno);
|
||||
|
||||
void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *from,void *data,unsigned long len);
|
||||
void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
|
||||
|
@ -121,6 +121,8 @@ it conflicts with our overriden symbols for read/write */
|
||||
#define BUF_SZ 1024
|
||||
#define SERVICE_CONNECT_ATTEMPTS 30
|
||||
|
||||
#define ERR_OK 0
|
||||
|
||||
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
|
||||
|
||||
/* threading */
|
||||
@ -535,20 +537,30 @@ int socket(SOCKET_SIG)
|
||||
ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &newfd);
|
||||
if(size > 0)
|
||||
{
|
||||
dwr("socket(): RXed FD = %d\n", newfd);
|
||||
/* send our local-fd number back to service so
|
||||
it can complete its mapping table entry */
|
||||
memset(cmd, '\0', BUF_SZ);
|
||||
cmd[0] = RPC_FD_MAP_COMPLETION;
|
||||
memcpy(&cmd[1], &newfd, sizeof(newfd));
|
||||
write(fdret_sock, cmd, BUF_SZ);
|
||||
pthread_mutex_unlock(&lock);
|
||||
return newfd;
|
||||
if(newfd > -1) {
|
||||
int n_write = write(fdret_sock, cmd, BUF_SZ);
|
||||
if(n_write < 0) {
|
||||
dwr("Error writing perceived FD to service.\n");
|
||||
return get_retval();
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
errno = ERR_OK;
|
||||
return newfd;
|
||||
}
|
||||
else { // Try to read retval+errno since we RXed a bad fd
|
||||
dwr("Error, service sent bad fd.\n");
|
||||
return get_retval();
|
||||
}
|
||||
}
|
||||
else {
|
||||
dwr("Error while receiving new FD.\n");
|
||||
pthread_mutex_unlock(&lock);
|
||||
return -1;
|
||||
return get_retval();
|
||||
}
|
||||
return realsocket(socket_family, socket_type, protocol);
|
||||
#endif
|
||||
@ -704,7 +716,7 @@ int bind(BIND_SIG)
|
||||
pthread_mutex_lock(&lock);
|
||||
write(fdret_sock, cmd, BUF_SZ);
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
errno = ERR_OK;
|
||||
return get_retval();
|
||||
#endif
|
||||
}
|
||||
@ -769,24 +781,31 @@ int accept(ACCEPT_SIG)
|
||||
ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &new_conn_socket);
|
||||
if(size > 0)
|
||||
{
|
||||
dwr("accept(): RXed FD = %d\n", new_conn_socket);
|
||||
/* Send our local-fd number back to service so it can complete its mapping table */
|
||||
memset(cmd, '\0', BUF_SZ);
|
||||
cmd[0] = RPC_FD_MAP_COMPLETION;
|
||||
memcpy(&cmd[1], &new_conn_socket, sizeof(new_conn_socket));
|
||||
pthread_mutex_lock(&lock);
|
||||
write(fdret_sock, cmd, BUF_SZ);
|
||||
int n_write = write(fdret_sock, cmd, BUF_SZ);
|
||||
if(n_write < 0) {
|
||||
dwr("Error sending perceived FD to service. Service might be down.\n");
|
||||
errno = ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
return new_conn_socket;
|
||||
errno = ERR_OK;
|
||||
return new_conn_socket; // OK
|
||||
}
|
||||
else {
|
||||
dwr("Error while receiving new FD.\n");
|
||||
dwr("Error receiving new FD from service. Service might be down.\n");
|
||||
errno = ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
errno = EWOULDBLOCK;
|
||||
dwr("Error reading signal byte from service. Service might be down.\n");
|
||||
//errno = EWOULDBLOCK;
|
||||
errno = ECONNABORTED;
|
||||
return -1;
|
||||
/* TODO/FIXME: Set errno */
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -822,9 +841,7 @@ int listen(LISTEN_SIG)
|
||||
pthread_mutex_lock(&lock);
|
||||
write(fdret_sock,cmd, BUF_SZ);
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
return 0;
|
||||
/* FIXME: get real return value (should be 0 / -1) */
|
||||
/* FIXME: Also set errno */
|
||||
errno = ERR_OK;
|
||||
return get_retval();
|
||||
#endif
|
||||
}
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user