From db473beb480aecf4373a8d3a77b59cddc4d580df Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Fri, 30 Oct 2015 17:00:30 -0700 Subject: [PATCH] Fixed accept return value / errno bug, also fdret_sock return bug --- netcon/Intercept.c | 53 ++++++---- netcon/NetconEthernetTap.cpp | 182 +++++++++++++++++++---------------- netcon/NetconEthernetTap.hpp | 2 +- netcon/NetconUtilities.cpp | 4 +- netcon/libintercept.so.1.0 | Bin 56400 -> 0 bytes 5 files changed, 137 insertions(+), 104 deletions(-) delete mode 100755 netcon/libintercept.so.1.0 diff --git a/netcon/Intercept.c b/netcon/Intercept.c index 27e57c76f..a124ccb6e 100755 --- a/netcon/Intercept.c +++ b/netcon/Intercept.c @@ -331,6 +331,11 @@ int setsockopt(SETSOCKOPT_SIG) { dwr("setsockopt(%d)\n", socket); //return(realsetsockopt(socket, level, option_name, option_value, option_len)); + if(level == SOL_IPV6 && option_name == IPV6_V6ONLY) + return 0; + + if(level == SOL_IP && option_name == IP_TTL) + return 0; if(level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE)){ return 0; @@ -353,7 +358,7 @@ int setsockopt(SETSOCKOPT_SIG) /* int sockfd, int level, int optname, void *optval, socklen_t *optlen */ int getsockopt(GETSOCKOPT_SIG) { - dwr("setsockopt(%d)\n", sockfd); + dwr("getsockopt(%d)\n", sockfd); int err = realgetsockopt(sockfd, level, optname, optval, optlen); // FIXME: this condition will need a little more intelligence later on // -- we will need to know if this fd is a local we are spoofing, or a true local @@ -385,19 +390,19 @@ int socket(SOCKET_SIG) int flags = socket_type & ~SOCK_TYPE_MASK; if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { errno = EINVAL; - handle_error("socket", "", -1); + handle_error("socket1", "", -1); return -1; } socket_type &= SOCK_TYPE_MASK; /* Check protocol is in range */ if (socket_family < 0 || socket_family >= NPROTO){ errno = EAFNOSUPPORT; - handle_error("socket", "", -1); + handle_error("socket2", "", -1); return -1; } if (socket_type < 0 || socket_type >= SOCK_MAX) { errno = EINVAL; - handle_error("socket", "", -1); + handle_error("socket3", "", -1); return -1; } /* Check that we haven't hit the soft-limit file descriptors allowed */ @@ -416,7 +421,7 @@ int socket(SOCKET_SIG) fdret_sock = !is_initialized ? init_service_connection() : fdret_sock; if(fdret_sock < 0) { dwr("BAD service connection. exiting.\n"); - handle_error("socket", "", -1); + handle_error("socket4", "", -1); exit(-1); } @@ -425,7 +430,7 @@ int socket(SOCKET_SIG) || socket_family == AF_UNIX) { int err = realsocket(socket_family, socket_type, protocol); dwr("realsocket, err = %d\n", err); - handle_error("socket", "", err); + handle_error("socket5", "", err); return err; } @@ -447,6 +452,7 @@ int socket(SOCKET_SIG) /* get new fd */ char rbuf[16]; ssize_t sz = sock_fd_read(fdret_sock, rbuf, sizeof(rbuf), &newfd); + dwr("read %d bytes (%s)\n", sz, &rbuf); if(sz > 0) { /* send our local-fd number back to service so @@ -455,27 +461,27 @@ int socket(SOCKET_SIG) cmd[0] = RPC_MAP; memcpy(&cmd[1], &newfd, sizeof(newfd)); - //if(newfd > -1) { + if(newfd > -1) { // FIXME: check logic send_command(fdret_sock, cmd); pthread_mutex_unlock(&lock); errno = ERR_OK; // OK - handle_error("socket", "", newfd); + handle_error("socket6", "", newfd); return newfd; - //} - /* + } else { // Try to read retval+errno since we RXed a bad fd dwr("Error, service sent bad fd.\n"); err = get_retval(); pthread_mutex_unlock(&lock); + handle_error("socket7", "", -1); return err; } - */ + } else { dwr("Error while receiving new FD.\n"); err = get_retval(); pthread_mutex_unlock(&lock); - handle_error("socket", "", -1); + handle_error("socket8", "", -1); return err; } } @@ -764,9 +770,9 @@ int accept(ACCEPT_SIG) return -1; } } - errno = EAGAIN; /* necessary? */ - handle_error("accept", "EAGAIN - Error reading signal byte from service", -1); - return -EAGAIN; + errno = EBADF; /* necessary? */ + handle_error("accept", "EBADF - Error reading signal byte from service", -1); + return -1; } @@ -825,7 +831,7 @@ int listen(LISTEN_SIG) memcpy(&cmd[1], &rpc_st, sizeof(struct listen_st)); pthread_mutex_lock(&lock); send_command(fdret_sock, cmd); - //err = get_retval(); + int err = get_retval(); pthread_mutex_unlock(&lock); handle_error("listen", "", ERR_OK); return ERR_OK; @@ -866,7 +872,8 @@ int poll(POLL_SIG) long syscall(SYSCALL_SIG) { - //dwr("syscall(%u, ...):\n", number); + dwr("syscall(%u, ...):\n", number); + va_list ap; uintptr_t a,b,c,d,e,f; va_start(ap, number); @@ -891,7 +898,17 @@ long syscall(SYSCALL_SIG) struct sockaddr * addr = (struct sockaddr*)b; socklen_t * addrlen = (socklen_t*)c; int flags = d; - return accept4(sockfd, addr, addrlen, flags); + int old_errno = errno; + int err = accept4(sockfd, addr, addrlen, flags); + errno = old_errno; + + if(err == -EBADF) { + //errno = EAGAIN; + err = -EAGAIN; + //exit(0); + } + + return err; } #endif return realsyscall(number,a,b,c,d,e,f); diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index dd49a1862..70eb511a6 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -82,7 +82,7 @@ NetconEthernetTap::NetconEthernetTap( _dev = sockPath; lwipstack = new LWIPStack("ext/bin/lwip/liblwip.so"); // ext/bin/liblwip.so.debug for debug symbols - if(!lwipstack) // TODO double check this check + if(!lwipstack) throw std::runtime_error("unable to load lwip lib."); lwipstack->lwip_init(); @@ -261,14 +261,33 @@ TcpConnection *NetconEthernetTap::getConnectionByTheirFD(PhySocket *sock, int fd void NetconEthernetTap::compact_dump() { /* - //clearscreen(); + // refresh(); clear(); gotoxy(0,0); + */ + clearscreen(); + gotoxy(0,0); + fprintf(stderr, "ZeroTier - Network Containers Service [State Dump]\n\r"); fprintf(stderr, " RPC Sockets = %d\n\r", rpc_sockets.size()); fprintf(stderr, " TCP Connections = %d\n\r", tcp_connections.size()); - */ + + for(size_t i=0; ipid); + if(tcp_connections[j]->rpcSock==rpc_sockets[i]) { + fprintf(stderr, "\t\tpath\t\t= %s\n", buf); + } + } + } } /* @@ -331,7 +350,7 @@ void NetconEthernetTap::die(int exret) { */ void NetconEthernetTap::closeConnection(TcpConnection *conn) { - fprintf(stderr, " closeConnection(%x, %d)\n", conn->pcb, _phy.getDescriptor(conn->dataSock)); + dwr(" closeConnection(%x, %d)\n", conn->pcb, _phy.getDescriptor(conn->dataSock)); //lwipstack->_tcp_sent(conn->pcb, NULL); //lwipstack->_tcp_recv(conn->pcb, NULL); @@ -524,7 +543,7 @@ void NetconEthernetTap::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr, } /* - * Add a new PhySocket for the client connection + * Add a new PhySocket for the client connections */ void NetconEthernetTap::phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) { if(find(rpc_sockets.begin(), rpc_sockets.end(), sockN) != rpc_sockets.end()){ @@ -549,9 +568,10 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns pid_t pid; memcpy(&pid, &buf[1], sizeof(pid_t)); // PID for client RPC tracking (only for debug) memcpy(&socket_rpc, &buf[64], sizeof(struct socket_st)); - if(handle_socket(sock, uptr, &socket_rpc) >= 0) { - fprintf(stderr, "pidmap[...] = %d\n", pid); + TcpConnection * new_conn; + if(new_conn = handle_socket(sock, uptr, &socket_rpc)) { pidmap[sock] = pid; + new_conn->pid = pid; } break; case RPC_LISTEN: @@ -621,12 +641,14 @@ int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _e int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0) { + fprintf(stderr, "send_return_value(): fd = %d, retval = %d, errno = %d\n", fd, retval, _errno); int sz = sizeof(char) + sizeof(retval) + sizeof(errno); 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)); + fprintf(stderr, "send_return_value(): retmsg = %s, sizeof(retmsg) = %d\n", &retmsg, sizeof(retmsg)); return write(fd, &retmsg, sz); } @@ -804,76 +826,71 @@ void NetconEthernetTap::nc_err(void *arg, err_t err) if(!l->conn) dwr("nc_err(): Connection is NULL!\n"); - if(l->conn) { - switch(err) - { - case ERR_MEM: - dwr("nc_err(): ERR_MEM->ENOMEM\n"); - l->tap->send_return_value(l->conn, -1, ENOMEM); - break; - case ERR_BUF: - dwr("nc_err(): ERR_BUF->ENOBUFS\n"); - l->tap->send_return_value(l->conn, -1, ENOBUFS); - break; - case ERR_TIMEOUT: - dwr("nc_err(): ERR_TIMEOUT->ETIMEDOUT\n"); - l->tap->send_return_value(l->conn, -1, ETIMEDOUT); - break; - case ERR_RTE: - dwr("nc_err(): ERR_RTE->ENETUNREACH\n"); - l->tap->send_return_value(l->conn, -1, ENETUNREACH); - break; - case ERR_INPROGRESS: - dwr("nc_err(): ERR_INPROGRESS->EINPROGRESS\n"); - l->tap->send_return_value(l->conn, -1, EINPROGRESS); - break; - case ERR_VAL: - dwr("nc_err(): ERR_VAL->EINVAL\n"); - l->tap->send_return_value(l->conn, -1, EINVAL); - break; - case ERR_WOULDBLOCK: - dwr("nc_err(): ERR_WOULDBLOCK->EWOULDBLOCK\n"); - l->tap->send_return_value(l->conn, -1, EWOULDBLOCK); - break; - case ERR_USE: - dwr("nc_err(): ERR_USE->EADDRINUSE\n"); - l->tap->send_return_value(l->conn, -1, EADDRINUSE); - break; - case ERR_ISCONN: - dwr("nc_err(): ERR_ISCONN->EISCONN\n"); - l->tap->send_return_value(l->conn, -1, EISCONN); - break; - case ERR_ABRT: - dwr("nc_err(): ERR_ABRT->ECONNREFUSED\n"); - l->tap->send_return_value(l->conn, -1, ECONNREFUSED); - break; + switch(err) + { + case ERR_MEM: + dwr("nc_err(): ERR_MEM->ENOMEM\n"); + l->tap->send_return_value(l->conn, -1, ENOMEM); + break; + case ERR_BUF: + dwr("nc_err(): ERR_BUF->ENOBUFS\n"); + l->tap->send_return_value(l->conn, -1, ENOBUFS); + break; + case ERR_TIMEOUT: + dwr("nc_err(): ERR_TIMEOUT->ETIMEDOUT\n"); + l->tap->send_return_value(l->conn, -1, ETIMEDOUT); + break; + case ERR_RTE: + dwr("nc_err(): ERR_RTE->ENETUNREACH\n"); + l->tap->send_return_value(l->conn, -1, ENETUNREACH); + break; + case ERR_INPROGRESS: + dwr("nc_err(): ERR_INPROGRESS->EINPROGRESS\n"); + l->tap->send_return_value(l->conn, -1, EINPROGRESS); + break; + case ERR_VAL: + dwr("nc_err(): ERR_VAL->EINVAL\n"); + l->tap->send_return_value(l->conn, -1, EINVAL); + break; + case ERR_WOULDBLOCK: + dwr("nc_err(): ERR_WOULDBLOCK->EWOULDBLOCK\n"); + l->tap->send_return_value(l->conn, -1, EWOULDBLOCK); + break; + case ERR_USE: + dwr("nc_err(): ERR_USE->EADDRINUSE\n"); + l->tap->send_return_value(l->conn, -1, EADDRINUSE); + break; + case ERR_ISCONN: + dwr("nc_err(): ERR_ISCONN->EISCONN\n"); + l->tap->send_return_value(l->conn, -1, EISCONN); + break; + case ERR_ABRT: + dwr("nc_err(): ERR_ABRT->ECONNREFUSED\n"); + l->tap->send_return_value(l->conn, -1, ECONNREFUSED); + break; - // FIXME: Below are errors which don't have a standard errno correlate + // FIXME: Below are errors which don't have a standard errno correlate - case ERR_RST: - l->tap->send_return_value(l->conn, -1, -1); - break; - case ERR_CLSD: - l->tap->send_return_value(l->conn, -1, -1); - break; - case ERR_CONN: - l->tap->send_return_value(l->conn, -1, -1); - break; - case ERR_ARG: - l->tap->send_return_value(l->conn, -1, -1); - break; - case ERR_IF: - l->tap->send_return_value(l->conn, -1, -1); - break; - default: - break; - } - dwr("nc_err(): closing connection\n"); - l->tap->closeConnection(l->conn); - } - else { - dwr("nc_err(): can't locate connection object for PCB\n"); - } + case ERR_RST: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_CLSD: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_CONN: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_ARG: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_IF: + l->tap->send_return_value(l->conn, -1, -1); + break; + default: + break; + } + dwr("nc_err(): closing connection\n"); + l->tap->closeConnection(l->conn); } /* @@ -912,10 +929,8 @@ err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *tpcb) */ err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *tpcb, u16_t len) { - //fprintf(stderr, " nc_sent()\n"); Larg *l = (Larg*)arg; if(len) { - //fprintf(stderr, " nc_sent(): ACKING len = %d, setting read-notify = true, (sndbuf = %d)\n", len, l->conn->pcb->snd_buf); l->tap->_phy.setNotifyReadable(l->conn->dataSock, true); l->tap->_phy.whack(); } @@ -1146,7 +1161,7 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste } else { /* - fprintf(stderr, "handle_listen(): unable to allocate memory for new listening PCB\n"); + dwr"handle_listen(): unable to allocate memory for new listening PCB\n"); // 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 @@ -1186,7 +1201,7 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste [?] EPROTONOSUPPORT - The protocol type or the specified protocol is not supported within this domain. */ -int NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) +TcpConnection * 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(); @@ -1198,7 +1213,7 @@ int NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socket if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) { if(errno < 0) { send_return_value(rpc_fd, -1, errno); - return -1; + return NULL; } } dwr(" handle_socket(): socketpair = {%d, %d}\n", fds[0], fds[1]); @@ -1209,17 +1224,18 @@ int NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socket new_conn->pcb = newpcb; new_conn->their_fd = fds[1]; tcp_connections.push_back(new_conn); - sock_fd_write(_phy.getDescriptor(sock), fds[1]); + int n = sock_fd_write(_phy.getDescriptor(sock), fds[1]); + dwr("wrote %d bytes\n", n); close(fds[1]); // close other end of socketpair // Once the client tells us what its fd is on the other end, we can then complete the mapping new_conn->pending = true; - return 0; + return new_conn; } else { sock_fd_write(rpc_fd, -1); // Send a bad fd, to signal error dwr(" handle_socket(): Memory not available for new PCB\n"); send_return_value(rpc_fd, -1, ENOMEM); - return -1; + return NULL; } } diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp index 930807a50..885f34a7a 100644 --- a/netcon/NetconEthernetTap.hpp +++ b/netcon/NetconEthernetTap.hpp @@ -109,7 +109,7 @@ private: void handle_map_request(PhySocket *sock, void **uptr, unsigned char* buf); void handle_i_am(PhySocket *sock, void **uptr, unsigned char* buf); void handle_retval(PhySocket *sock, void **uptr, unsigned char* buf); - int handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc); + TcpConnection * handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc); void handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc); void handle_write(TcpConnection *conn); diff --git a/netcon/NetconUtilities.cpp b/netcon/NetconUtilities.cpp index 45332512f..83e3c1d29 100644 --- a/netcon/NetconUtilities.cpp +++ b/netcon/NetconUtilities.cpp @@ -44,13 +44,13 @@ namespace ZeroTier { void dwr(char *fmt, ... ) { -//#ifdef ZT_DEBUG + va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fflush(stderr); va_end(ap); -//#endif + } void clearscreen() diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0 deleted file mode 100755 index 46a1f0248b7a4f13fe292e9bda2830d7d4acde10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56400 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 c`3)+QVQCkl5<;Fh522gT3M`O)5E%#w09sf