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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