diff --git a/docker-test/httpd_demo/lib/libintercept.so.1.0 b/docker-test/httpd_demo/lib/libintercept.so.1.0 deleted file mode 100755 index 618266419..000000000 Binary files a/docker-test/httpd_demo/lib/libintercept.so.1.0 and /dev/null differ diff --git a/docker-test/throughput/libintercept.so.1.0 b/docker-test/throughput/libintercept.so.1.0 deleted file mode 100755 index 7a4514080..000000000 Binary files a/docker-test/throughput/libintercept.so.1.0 and /dev/null differ diff --git a/docker-test/throughput/liblwip.so b/docker-test/throughput/liblwip.so deleted file mode 100755 index 158169f1b..000000000 Binary files a/docker-test/throughput/liblwip.so and /dev/null differ diff --git a/docker-test/throughput/zerotier-cli b/docker-test/throughput/zerotier-cli deleted file mode 100755 index 6e659e7a3..000000000 Binary files a/docker-test/throughput/zerotier-cli and /dev/null differ diff --git a/docker-test/throughput/zerotier-one b/docker-test/throughput/zerotier-one deleted file mode 100755 index 6e659e7a3..000000000 Binary files a/docker-test/throughput/zerotier-one and /dev/null differ diff --git a/docker-test/throughput/Dockerfile b/docker-test/throughput_httpd_2.4.16/Dockerfile similarity index 100% rename from docker-test/throughput/Dockerfile rename to docker-test/throughput_httpd_2.4.16/Dockerfile diff --git a/docker-test/throughput/build.sh b/docker-test/throughput_httpd_2.4.16/build.sh similarity index 100% rename from docker-test/throughput/build.sh rename to docker-test/throughput_httpd_2.4.16/build.sh diff --git a/docker-test/throughput/entrypoint.sh b/docker-test/throughput_httpd_2.4.16/entrypoint.sh similarity index 100% rename from docker-test/throughput/entrypoint.sh rename to docker-test/throughput_httpd_2.4.16/entrypoint.sh diff --git a/docker-test/throughput/generate_file.sh b/docker-test/throughput_httpd_2.4.16/generate_file.sh similarity index 100% rename from docker-test/throughput/generate_file.sh rename to docker-test/throughput_httpd_2.4.16/generate_file.sh diff --git a/docker-test/throughput/intercept b/docker-test/throughput_httpd_2.4.16/intercept similarity index 100% rename from docker-test/throughput/intercept rename to docker-test/throughput_httpd_2.4.16/intercept diff --git a/docker-test/throughput_httpd_2.4.17/Dockerfile b/docker-test/throughput_httpd_2.4.17/Dockerfile new file mode 100644 index 000000000..77a1a26a0 --- /dev/null +++ b/docker-test/throughput_httpd_2.4.17/Dockerfile @@ -0,0 +1,40 @@ +# ZT Netcon Throughput test +FROM fedora:23 +MAINTAINER https://www.zerotier.com/ + +# Install apps +RUN yum -y update +RUN yum -y install httpd-2.4.17-3.fc23 +RUN yum -y install nano +RUN yum -y install strace +RUN yum clean all + +EXPOSE 9993/udp 9992/udp 9991/udp 9990/udp + +# Install sys-call intercept library +ADD intercept / +ADD libintercept.so.1.0 / +RUN cp libintercept.so.1.0 lib/libintercept.so.1.0 +RUN cp libintercept.so.1.0 /lib/libintercept.so.1.0 +RUN ln -sf /lib/libintercept.so.1.0 /lib/libintercept +RUN /usr/bin/install -c intercept /usr/bin + +# Add ZT files +RUN mkdir -p /var/lib/zerotier-one/networks.d +RUN touch /var/lib/zerotier-one/networks.d/e5cd7a9e1c5311ab.conf +ADD zerotier-one / +ADD zerotier-cli / + +# Install test-setup scripts +ADD generate_file.sh /generate_file.sh +RUN chmod -v +x /generate_file.sh +ADD entrypoint.sh /entrypoint.sh +RUN chmod -v +x /entrypoint.sh + +# Install LWIP library used by service +ADD liblwip.so / +RUN mkdir -p ext/bin/lwip +RUN cp liblwip.so ext/bin/lwip/liblwip.so + +# Start ZeroTier-One +CMD ["./entrypoint.sh"] diff --git a/docker-test/throughput_httpd_2.4.17/build.sh b/docker-test/throughput_httpd_2.4.17/build.sh new file mode 100755 index 000000000..14f5b44ad --- /dev/null +++ b/docker-test/throughput_httpd_2.4.17/build.sh @@ -0,0 +1,17 @@ +cd ../../ +make clean +make +cd netcon +make -f make-intercept.mk lib +rm *.o +rm liblwip.so +make -f make-liblwip.mk + +cd ../docker-test/throughput_httpd_2.4.17 + +cp ../../zerotier-one zerotier-one +cp ../../zerotier-cli zerotier-cli + +cp ../../netcon/liblwip.so liblwip.so +cp ../../netcon/libintercept.so.1.0 libintercept.so.1.0 + diff --git a/docker-test/throughput_httpd_2.4.17/entrypoint.sh b/docker-test/throughput_httpd_2.4.17/entrypoint.sh new file mode 100644 index 000000000..00fdd2be6 --- /dev/null +++ b/docker-test/throughput_httpd_2.4.17/entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/ + +echo '***' +echo '*** ZeroTier Network Containers Test Image' +echo '*** https://www.zerotier.com/' +echo '***' + +./zerotier-one & +./zerotier-cli join e5cd7a9e1c5311ab +./zerotier-cli listnetworks + + diff --git a/docker-test/throughput_httpd_2.4.17/generate_file.sh b/docker-test/throughput_httpd_2.4.17/generate_file.sh new file mode 100644 index 000000000..ac5b24338 --- /dev/null +++ b/docker-test/throughput_httpd_2.4.17/generate_file.sh @@ -0,0 +1 @@ +dd if=/dev/urandom of=/var/www/html/big bs=100M count=1 diff --git a/docker-test/throughput_httpd_2.4.17/intercept b/docker-test/throughput_httpd_2.4.17/intercept new file mode 100755 index 000000000..3eb27ff7b --- /dev/null +++ b/docker-test/throughput_httpd_2.4.17/intercept @@ -0,0 +1,54 @@ +#!/bin/sh +# usage: +# /usr/bin/intercept program + +if [ $# = 0 ] ; then + echo "$0: insufficient arguments" + exit +fi + +case "$1" in + on) + if [ -z "$LD_PRELOAD" ] + then + export LD_PRELOAD="/lib/libintercept.so.1.0" + else + echo $LD_PRELOAD | grep -q "/lib/libintercept\.so.1.0" || \ + export LD_PRELOAD="/lib/libintercept.so $LD_PRELOAD" + fi + ;; + off) + export LD_PRELOAD=`echo -n $LD_PRELOAD | sed 's/\/lib\/libintercept.so.1.0 \?//'` + if [ -z "$LD_PRELOAD" ] + then + unset LD_PRELOAD + fi + ;; + show|sh) + echo "LD_PRELOAD=\"$LD_PRELOAD\"" + ;; + -h|-?) + echo "" + ;; + *) + if [ -z "$LD_PRELOAD" ] + then + export LD_PRELOAD="/lib/libintercept.so.1.0" + else + echo $LD_PRELOAD | grep -q "/lib/libintercept\.so.1.0" || \ + export LD_PRELOAD="/lib/libintercept.so.1.0 $LD_PRELOAD" + fi + + if [ $# = 0 ] + then + ${SHELL:-/bin/sh} + fi + + if [ $# -gt 0 ] + then + exec "$@" + fi + ;; +esac + +#EOF diff --git a/make-linux.mk b/make-linux.mk index 2f60597c8..bcc67eafb 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -112,6 +112,10 @@ installer: one FORCE clean: rm -rf *.o + find docker-test/ -name "*.1.0" -type f -delete + find docker-test/ -name "*.so" -type f -delete + find docker-test/ -name "zerotier-one" -type f -delete + find docker-test/ -name "zerotier-cli" -type f -delete rm -rf netcon/*.o netcon/*.so netcon/*.1.0 rm -rf node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm diff --git a/netcon/Intercept.c b/netcon/Intercept.c index e91a14cc9..0dbc56146 100755 --- a/netcon/Intercept.c +++ b/netcon/Intercept.c @@ -79,14 +79,16 @@ static int (*realsetsockopt)(SETSOCKOPT_SIG); static int (*realgetsockopt)(GETSOCKOPT_SIG); static int (*realaccept4)(ACCEPT4_SIG); static long (*realsyscall)(SYSCALL_SIG); +static int (*realclose)(CLOSE_SIG); //static int (*realclone)(CLONE_SIG); //static int (*realpoll)(POLL_SIG); +static int (*realdup2)(DUP2_SIG); +static int (*realdup3)(DUP3_SIG); /* Exported Function Prototypes */ void my_init(void); int connect(CONNECT_SIG); int select(SELECT_SIG); -int close(CLOSE_SIG); int bind(BIND_SIG); int accept(ACCEPT_SIG); int listen(LISTEN_SIG); @@ -95,8 +97,12 @@ int setsockopt(SETSOCKOPT_SIG); int getsockopt(GETSOCKOPT_SIG); int accept4(ACCEPT4_SIG); long syscall(SYSCALL_SIG); +int close(CLOSE_SIG); //int clone(CLONE_SIG); //int poll(POLL_SIG); +int dup2(DUP2_SIG); +int dup3(DUP3_SIG); + #ifdef USE_SOCKS_DNS int res_init(void); @@ -110,6 +116,7 @@ void set_up_intercept(); int checkpid(); #define SERVICE_CONNECT_ATTEMPTS 30 +#define RPC_FD 1023 ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd); @@ -126,10 +133,12 @@ void handle_error(char *name, char *info, int err) } #endif #ifdef VERBOSE - //dwr("%s()=%d\n", name, err); + dwr("%s()=%d\n", name, err); #endif } +static unsigned long rpc_count = 0; + /*------------------------------------------------------------------------------ ------------------- Intercept<--->Service Comm mechanisms----------------------- ------------------------------------------------------------------------------*/ @@ -158,7 +167,45 @@ int checkpid() { */ int send_command(int rpc_fd, char *cmd) { - int n_write = write(rpc_fd, cmd, BUF_SZ); +#ifdef DEBUG +/* + dwr(" - IDX_PID = %d\n", IDX_PID); + dwr(" - IDX_TID = %d\n", IDX_TID); + dwr(" - IDX_COUNT = %d\n", IDX_COUNT); + dwr(" - IDX_TIME = %d\n", IDX_TIME); + dwr(" - IDX_PAYLOAD = %d\n", IDX_PAYLOAD); +*/ +/* + #define IDX_PID 0 + #define IDX_TID sizeof(pid_t) + #define IDX_COUNT IDX_TID + sizeof(pid_t) + #define IDX_TIME IDX_COUNT + sizeof(int) + #define IDX_CMD IDX_TIME + 20 // 20 being the length of the timestamp string + #define IDX_PAYLOAD IDX_TIME + sizeof(char) +*/ + + // [pid_t] [pid_t] [rpc_count] [int] [...] + char metabuf[BUF_SZ]; // portion of buffer which contains RPC meta-data for debugging + memset(metabuf, '\0', BUF_SZ); + pid_t pid = syscall(SYS_getpid); + pid_t tid = syscall(SYS_gettid); + int payload_idx = sizeof(pid_t)*2 + sizeof(rpc_count); + rpc_count++; + char timestring[20]; + time_t timestamp; + timestamp = time(NULL); + strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(×tamp)); + + memcpy(&metabuf[IDX_PID], &pid, sizeof(pid_t) ); // pid + memcpy(&metabuf[IDX_TID], &tid, sizeof(pid_t) ); // tid + memcpy(&metabuf[IDX_COUNT], &rpc_count, sizeof(rpc_count) ); // rpc_count + memcpy(&metabuf[IDX_TIME], ×tring, 20 ); // timestamp +#endif + // copy payload into final command buffer + int copied = BUF_SZ-IDX_PAYLOAD; + memcpy(&metabuf[IDX_PAYLOAD], cmd, 200); + //dwr(" RX: (pid=%d, tid=%d, rpc_count=%d, timestamp=%s, cmd=%d\n", pid, tid, rpc_count, timestring, cmd[0]); + int n_write = write(rpc_fd, &metabuf, BUF_SZ); if(n_write < 0){ dwr("Error writing command to service (CMD = %d)\n", cmd[0]); errno = 0; @@ -200,9 +247,12 @@ int is_mapped_to_service(int sockfd) memset(cmd, '\0', BUF_SZ); cmd[0] = RPC_MAP_REQ; memcpy(&cmd[1], &sockfd, sizeof(sockfd)); + pthread_mutex_lock(&lock); if(send_command(fdret_sock, cmd) < 0) return -1; - return get_retval(); + int err = get_retval(); + pthread_mutex_unlock(&lock); + return err; } /*------------------------------------------------------------------------------ @@ -233,7 +283,10 @@ int init_service_connection() else { dwr("AF_UNIX connection established: %d\n", tfd); is_initialized = 1; - return tfd; + int newtfd = realdup2(tfd, 1023); + dwr("dup'd to rpc_fd = %d\n", newtfd); + close(tfd); + return newtfd; } attempts++; } @@ -277,8 +330,11 @@ void load_symbols(void) realgetsockopt = dlsym(RTLD_NEXT, "getsockopt"); realaccept4 = dlsym(RTLD_NEXT, "accept4"); //realclone = dlsym(RTLD_NEXT, "clone"); + realclose = dlsym(RTLD_NEXT, "close"); realsyscall = dlsym(RTLD_NEXT, "syscall"); //realsyscall = dlsym(RTLD_NEXT, "poll"); + realdup2 = dlsym(RTLD_NEXT, "dup2"); + realdup3 = dlsym(RTLD_NEXT, "dup3"); #ifdef USE_SOCKS_DNS realresinit = dlsym(RTLD_NEXT, "res_init"); #endif @@ -295,8 +351,11 @@ void load_symbols(void) realgetsockopt = dlsym(lib, "getsockopt"); realaccept4 = dlsym(lib), "accept4"); //realclone = dlsym(lib, "clone"); + realclose = dlsym(lib, "close"); realsyscall = dlsym(lib, "syscall"); //realsyscall = dlsym(lib, "poll"); + realdup2 = dlsym(RTLD_NEXT, "dup2"); + realdup3 = dlsym(RTLD_NEXT, "dup3"); #ifdef USE_SOCKS_DNS realresinit = dlsym(lib, "res_init"); #endif @@ -332,7 +391,7 @@ void set_up_intercept() /* int socket, int level, int option_name, const void *option_value, socklen_t option_len */ int setsockopt(SETSOCKOPT_SIG) { - dwr("setsockopt(%d)\n", socket); + dwr("\n\nsetsockopt(%d)\n", socket); /* if(is_mapped_to_service(socket) < 0) { // First, check if the service manages this return realsetsockopt(socket, level, option_name, option_value, option_len); @@ -363,7 +422,7 @@ int setsockopt(SETSOCKOPT_SIG) /* int sockfd, int level, int optname, void *optval, socklen_t *optlen */ int getsockopt(GETSOCKOPT_SIG) { - dwr("getsockopt(%d)\n", sockfd); + dwr("\n\ngetsockopt(%d)\n", sockfd); /* if(is_mapped_to_service(sockfd) < 0) { // First, check if the service manages this return realgetsockopt(sockfd, level, optname, optval, optlen); @@ -393,7 +452,7 @@ int getsockopt(GETSOCKOPT_SIG) socket() intercept function */ int socket(SOCKET_SIG) { - dwr("socket()*:\n"); + dwr("\n\nsocket()*:\n"); int err; #ifdef CHECKS /* Check that type makes sense */ @@ -426,7 +485,6 @@ int socket(SOCKET_SIG) */ /* FIXME: detect ENFILE condition */ #endif - char cmd[BUF_SZ]; fdret_sock = !is_initialized ? init_service_connection() : fdret_sock; if(fdret_sock < 0) { @@ -434,7 +492,6 @@ int socket(SOCKET_SIG) handle_error("socket4", "", -1); exit(-1); } - if(socket_family == AF_LOCAL || socket_family == AF_NETLINK || socket_family == AF_UNIX) { @@ -443,18 +500,15 @@ int socket(SOCKET_SIG) handle_error("socket5", "", err); return err; } - /* Assemble and send RPC */ struct socket_st rpc_st; rpc_st.socket_family = socket_family; rpc_st.socket_type = socket_type; rpc_st.protocol = protocol; rpc_st.__tid = syscall(SYS_gettid); - memset(cmd, '\0', BUF_SZ); cmd[0] = RPC_SOCKET; dwr("pid = %d\n", thispid); - memcpy(&cmd[1], &thispid, sizeof(pid_t)); memcpy(&cmd[1]+sizeof(pid_t), &rpc_st, sizeof(struct socket_st)); pthread_mutex_lock(&lock); send_command(fdret_sock, cmd); @@ -462,9 +516,11 @@ int socket(SOCKET_SIG) /* get new fd */ char rbuf[16]; ssize_t sz = sock_fd_read(fdret_sock, rbuf, sizeof(rbuf), &newfd); + int tmp = newfd; dwr("read %d bytes (%s)\n", sz, &rbuf); if(sz > 0) { + dwr("sending fd = %d to Service over (%d)\n", newfd, fdret_sock); /* send our local-fd number back to service so it can complete its mapping table entry */ memset(cmd, '\0', BUF_SZ); @@ -504,7 +560,7 @@ int socket(SOCKET_SIG) connect() intercept function */ int connect(CONNECT_SIG) { - dwr("connect(%d):\n", __fd); + dwr("\n\nconnect(%d):\n", __fd); print_addr(__addr); struct sockaddr_in *connaddr; connaddr = (struct sockaddr_in *) __addr; @@ -597,7 +653,7 @@ int select(SELECT_SIG) bind() intercept function */ int bind(BIND_SIG) { - dwr("bind(%d):\n", sockfd); + dwr("\n\nbind(%d):\n", sockfd); print_addr(addr); #ifdef CHECKS /* Check that this is a valid fd */ @@ -660,7 +716,7 @@ int bind(BIND_SIG) /* int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags */ int accept4(ACCEPT4_SIG) { - dwr("accept4(%d):\n", sockfd); + dwr("\n\naccept4(%d):\n", sockfd); #ifdef CHECKS if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { errno = EINVAL; @@ -687,7 +743,7 @@ int accept4(ACCEPT4_SIG) accept() intercept function */ int accept(ACCEPT_SIG) { - dwr("accept(%d):\n", sockfd); + dwr("\n\naccept(%d):\n", sockfd); #ifdef CHECKS /* Check that this is a valid fd */ if(fcntl(sockfd, F_GETFD) < 0) { @@ -794,7 +850,7 @@ int accept(ACCEPT_SIG) listen() intercept function */ int listen(LISTEN_SIG) { - dwr("listen(%d):\n", sockfd); + dwr("\n\nlisten(%d):\n", sockfd); int sock_type; socklen_t sock_type_len = sizeof(sock_type); @@ -861,7 +917,6 @@ int clone(CLONE_SIG) */ - /*------------------------------------------------------------------------------ -------------------------------------- poll()----------------------------------- ------------------------------------------------------------------------------*/ @@ -876,6 +931,59 @@ int poll(POLL_SIG) } */ +/*------------------------------------------------------------------------------ +-------------------------------------- close()----------------------------------- +------------------------------------------------------------------------------*/ + +// int fd +int close(CLOSE_SIG) +{ + dwr("close(%d)\n", fd); + if(fd == fdret_sock) + return 0; // FIXME: Ignore request to shut down our rpc fd, this is *almost always* safe + if(fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO){ + return realclose(fd); + } +} + +/*------------------------------------------------------------------------------ +-------------------------------------- dup2()----------------------------------- +------------------------------------------------------------------------------*/ + +// int oldfd, int newfd +int dup2(DUP2_SIG) +{ + dwr("dup2(%d, %d)\n", oldfd, newfd); + if(oldfd == fdret_sock) { + dwr("client application attempted to dup2 RPC socket (%d). This is not allowed.\n", oldfd); + errno = EBADF; + return -1; + } + if(oldfd != STDIN_FILENO && oldfd != STDOUT_FILENO && oldfd != STDERR_FILENO) { + return realdup2(oldfd, newfd); + } +} + +/*------------------------------------------------------------------------------ +-------------------------------------- dup3()----------------------------------- +------------------------------------------------------------------------------*/ + +// int oldfd, int newfd, int flags +int dup3(DUP3_SIG) +{ + dwr("dup3(%d, %d, %d)\n", oldfd, newfd, flags); +#ifdef DEBUG + // Only do this check if we want to debug the intercept, otherwise, dont mess with + // the client application's logging methods + if(newfd == STDIN_FILENO || newfd == STDOUT_FILENO || newfd == STDERR_FILENO) + return newfd; // FIXME: This is to prevent httpd from dup'ing over our stderr + //and preventing us from debugging + else +#endif + return realdup3(oldfd, newfd, flags); +} + + /*------------------------------------------------------------------------------ ------------------------------------ syscall()---------------------------------- ------------------------------------------------------------------------------*/ diff --git a/netcon/Intercept.h b/netcon/Intercept.h index 1be9bf53d..973e48eb8 100755 --- a/netcon/Intercept.h +++ b/netcon/Intercept.h @@ -31,7 +31,13 @@ #include -#define BUF_SZ 128 +#define IDX_PID 0 +#define IDX_TID sizeof(pid_t) +#define IDX_COUNT IDX_TID + sizeof(pid_t) +#define IDX_TIME IDX_COUNT + sizeof(int) +#define IDX_PAYLOAD IDX_TIME + 20 // 20 being the length of the timestamp string + +#define BUF_SZ 256 #define ERR_OK 0 /* Userland RPC codes */ @@ -177,4 +183,7 @@ struct shutdown_st #define CLONE_SIG int (*fn)(void *), void *child_stack, int flags, void *arg, ... #define POLL_SIG struct pollfd *fds, nfds_t nfds, int timeout +#define DUP2_SIG int oldfd, int newfd +#define DUP3_SIG int oldfd, int newfd, int flags + #endif diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index b4e4eaaf2..94821c8e8 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -567,22 +567,39 @@ void NetconEthernetTap::phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void * rpc_sockets.push_back(sockN); } +void unload_rpc(void *data, pid_t &pid, pid_t &tid, int &rpc_count, char (timestamp[20]), char &cmd, void* &payload); + /* * Processes incoming data on a client-specific RPC connection */ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) { + pid_t pid, tid; + int rpc_count; + char timestamp[20]; + char cmd; + void *payload; + unload_rpc(data, pid, tid, rpc_count, timestamp, cmd, payload); + dwr("\n\nRX: (pid=%d, tid=%d, rpc_count=%d, timestamp=%s, cmd=%d\n", pid, tid, rpc_count, timestamp, cmd); unsigned char *buf = (unsigned char*)data; - switch(buf[0]) + + switch(cmd) { case RPC_SOCKET: dwr(2, "RPC_SOCKET\n"); - struct socket_st socket_rpc; - pid_t pid; - memcpy(&pid, &buf[1], sizeof(pid_t)); // PID for client RPC tracking (only for debug) - memcpy(&socket_rpc, &buf[sizeof(pid_t)], sizeof(struct socket_st)); + struct socket_st socket_rpc; + memcpy(&socket_rpc, &buf[IDX_PAYLOAD+1], sizeof(struct socket_st)); + + if(rpc_count==rpc_counter) { + dwr("Detected repeat RPC.\n"); + //return; + } + else { + rpc_counter = rpc_count; + } + TcpConnection * new_conn; - if(new_conn = handle_socket(sock, uptr, &socket_rpc)) { + if((new_conn = handle_socket(sock, uptr, &socket_rpc))) { pidmap[sock] = pid; new_conn->pid = pid; } @@ -590,24 +607,30 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns case RPC_LISTEN: dwr(2, "RPC_LISTEN\n"); struct listen_st listen_rpc; - memcpy(&listen_rpc, &buf[1], sizeof(struct listen_st)); + memcpy(&listen_rpc, &buf[IDX_PAYLOAD+1], sizeof(struct listen_st)); handle_listen(sock, uptr, &listen_rpc); break; case RPC_BIND: dwr(2, "RPC_BIND\n"); struct bind_st bind_rpc; - memcpy(&bind_rpc, &buf[1], sizeof(struct bind_st)); + memcpy(&bind_rpc, &buf[IDX_PAYLOAD+1], sizeof(struct bind_st)); handle_bind(sock, uptr, &bind_rpc); break; case RPC_CONNECT: dwr(2, "RPC_CONNECT\n"); struct connect_st connect_rpc; - memcpy(&connect_rpc, &buf[1], sizeof(struct connect_st)); + memcpy(&connect_rpc, &buf[IDX_PAYLOAD+1], sizeof(struct connect_st)); handle_connect(sock, uptr, &connect_rpc); break; case RPC_MAP: - dwr(2, "RPC_MAP\n"); - handle_retval(sock, uptr, buf); + dwr(2, "RPC_MAP (len = %d)\n", len); + + int newfd; + //memcpy(&pid, &buf[IDX_PAYLOAD+1], sizeof(pid_t)); // PID for client RPC tracking (only for debug) + memcpy(&newfd, &buf[IDX_PAYLOAD+1], sizeof(int)); + //dwr("newfd = %d\n", newfd); + + handle_retval(sock, uptr, rpc_count, newfd); break; case RPC_MAP_REQ: dwr(2, "RPC_MAP_REQ\n"); @@ -616,6 +639,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns default: break; } + //memset(data, '\0', 256); } /* @@ -973,7 +997,7 @@ void NetconEthernetTap::handle_map_request(PhySocket *sock, void **uptr, unsigne dwr(4, " handle_map_request()\n"); TcpConnection *conn = (TcpConnection*)*uptr; int req_fd; - memcpy(&req_fd, &buf[1], sizeof(req_fd)); + memcpy(&req_fd, &buf[IDX_PAYLOAD+1], sizeof(req_fd)); for(size_t i=0; irpcSock == conn->rpcSock && tcp_connections[i]->perceived_fd == req_fd){ send_return_value(conn, 1, ERR_OK); // True @@ -994,16 +1018,26 @@ void NetconEthernetTap::handle_map_request(PhySocket *sock, void **uptr, unsigne * @param structure containing the data and parameters for this client's RPC * */ -void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned char* buf) +void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, int rpc_count, int newfd) { dwr(4, " handle_retval()\n"); TcpConnection *conn = (TcpConnection*)*uptr; if(!conn->pending) return; - // Copy data from buffer to TcpConnection object, update status - memcpy(&(conn->perceived_fd), &buf[1], sizeof(int)); conn->pending = false; + conn->perceived_fd = newfd; + + if(rpc_count==rpc_counter) { + dwr("Detected repeat RPC.\n"); + //return; + } + else { + rpc_counter = rpc_count; + //dwr("pid = %d\n", rpc_count); + //dwr("rpc_counter = %d\n", rpc_counter); + + } dwr(4, " handle_retval(): CONN:%x - Mapping [our=%d -> their=%d]\n",conn, _phy.getDescriptor(conn->dataSock), conn->perceived_fd); @@ -1027,7 +1061,7 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha } else { dwr(" handle_retval(): CONN:%x - This socket is mapped to two different pipes (?). Exiting.\n", conn); - die(0); // FIXME: Print service mapping state and exit + //die(0); // FIXME: Print service mapping state and exit } } } @@ -1070,7 +1104,7 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha */ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st *bind_rpc) { - dwr(3, " handle_bind()\n"); + struct sockaddr_in *connaddr; connaddr = (struct sockaddr_in *) &bind_rpc->addr; int conn_port = lwipstack->ntohs(connaddr->sin_port); @@ -1078,6 +1112,8 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st conn_addr.addr = *((u32_t *)_ips[0].rawIpData()); TcpConnection *conn = getConnectionByTheirFD(sock, bind_rpc->sockfd); + dwr(3, " handle_bind(%d)\n", bind_rpc->sockfd); + if(conn) { if(conn->pcb->state == CLOSED){ int err = lwipstack->tcp_bind(conn->pcb, &conn_addr, conn_port); @@ -1229,7 +1265,6 @@ TcpConnection * NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, s new_conn->their_fd = fds[1]; tcp_connections.push_back(new_conn); 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; diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp index 2267b49dc..8726af5c8 100644 --- a/netcon/NetconEthernetTap.hpp +++ b/netcon/NetconEthernetTap.hpp @@ -107,7 +107,7 @@ private: void handle_bind(PhySocket *sock, void **uptr, struct bind_st *bind_rpc); void handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc); void handle_map_request(PhySocket *sock, void **uptr, unsigned char* buf); - void handle_retval(PhySocket *sock, void **uptr, unsigned char* buf); + void handle_retval(PhySocket *sock, void **uptr, int rpc_count, int newfd); 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); @@ -154,6 +154,7 @@ private: std::vector tcp_connections; std::vector rpc_sockets; std::map pidmap; + pid_t rpc_counter = -1; netif interface; diff --git a/netcon/NetconUtilities.cpp b/netcon/NetconUtilities.cpp index c4a596360..94dd1ba01 100644 --- a/netcon/NetconUtilities.cpp +++ b/netcon/NetconUtilities.cpp @@ -37,6 +37,8 @@ #include "lwip/ip_addr.h" #include "lwip/ip_frag.h" +#include "Intercept.h" + #ifndef _NETCON_UTILITIES_CPP #define _NETCON_UTILITIES_CPP @@ -64,8 +66,27 @@ namespace ZeroTier va_end(ap); } - void clearscreen() + void unload_rpc(void *data, pid_t &pid, pid_t &tid, int &rpc_count, char (timestamp[20]), char &cmd, void* &payload) { + unsigned char *buf = (unsigned char*)data; + +/* + dwr(" - IDX_PID = %d\n", IDX_PID); + dwr(" - IDX_TID = %d\n", IDX_TID); + dwr(" - IDX_COUNT = %d\n", IDX_COUNT); + dwr(" - IDX_TIME = %d\n", IDX_TIME); + dwr(" - IDX_PAYLOAD = %d\n", IDX_PAYLOAD); +*/ + memcpy(&pid, &buf[IDX_PID], sizeof(pid_t)); + memcpy(&tid, &buf[IDX_TID], sizeof(pid_t)); + memcpy(&rpc_count, &buf[IDX_COUNT], sizeof(int)); + memcpy(timestamp, &buf[IDX_TIME], 20); + memcpy(&cmd, &buf[IDX_PAYLOAD], sizeof(char)); + payload = buf+IDX_PAYLOAD+1; + //dwr("RX: (pid=%d, tid=%d, rpc_count=%d, timestamp=%s, cmd=%d\n", pid, tid, rpc_count, timestamp, cmd); + } + + void clearscreen(){ fprintf(stderr, "\033[2J"); } diff --git a/netcon/make-intercept.mk b/netcon/make-intercept.mk index fbae717f4..245ea188a 100644 --- a/netcon/make-intercept.mk +++ b/netcon/make-intercept.mk @@ -27,7 +27,7 @@ SHCC=gcc -intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -DERRORS_ARE_FATAL -DVERBOSE -DCHECKS -D_GNU_SOURCE -DNETCON_INTERCEPT +intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -DERRORS_ARE_FATAL -DDEBUG -DVERBOSE -DCHECKS -D_GNU_SOURCE -DNETCON_INTERCEPT LIB_NAME = intercept SHLIB_EXT=dylib SHLIB_MAJOR = 1