Browse Source

Test/Code Refactor in preparation for merge

Joseph Henry 9 years ago
parent
commit
1f27022fa7
50 changed files with 1169 additions and 349 deletions
  1. 5 5
      make-linux.mk
  2. 2 2
      netcon/Common.c
  3. 79 89
      netcon/Intercept.c
  4. 51 50
      netcon/Intercept.h
  5. 0 18
      netcon/LWIPStack.hpp
  6. 18 21
      netcon/NetconEthernetTap.cpp
  7. 1 1
      netcon/NetconEthernetTap.hpp
  8. 1 5
      netcon/NetconService.hpp
  9. 0 123
      netcon/NetconUtilities.cpp
  10. 0 3
      netcon/NetconUtilities.hpp
  11. 3 5
      netcon/README.md
  12. 31 7
      netcon/Sendfd.c
  13. 0 3
      netcon/Sendfd.h
  14. 28 0
      netcon/docker-test/README.md
  15. 1 0
      netcon/docker-test/_results/OK.httpd-2.4.16-1.fc23.x86_64.txt
  16. 1 0
      netcon/docker-test/_results/OK.httpd-2.4.17-3.fc23.x86_64.txt
  17. 19 0
      netcon/docker-test/build.sh
  18. 0 0
      netcon/docker-test/e5cd7a9e1c5311ab.conf
  19. 8 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/README.md
  20. 25 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/monitor_dockerfile
  21. 86 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/monitor_entrypoint.sh
  22. 41 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/netcon_dockerfile
  23. 53 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/netcon_entrypoint.sh
  24. 40 0
      netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/test.sh
  25. 8 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/README.md
  26. 25 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_dockerfile
  27. 86 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_entrypoint.sh
  28. 41 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_dockerfile
  29. 53 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_entrypoint.sh
  30. 40 0
      netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/test.sh
  31. 8 0
      netcon/docker-test/httpd/httpd_demo/README.md
  32. BIN
      netcon/docker-test/httpd/httpd_demo/htdocs/ZeroTierIcon.png
  33. 69 0
      netcon/docker-test/httpd/httpd_demo/htdocs/index.html
  34. 25 0
      netcon/docker-test/httpd/httpd_demo/monitor_dockerfile
  35. 86 0
      netcon/docker-test/httpd/httpd_demo/monitor_entrypoint.sh
  36. 47 0
      netcon/docker-test/httpd/httpd_demo/netcon_dockerfile
  37. 53 0
      netcon/docker-test/httpd/httpd_demo/netcon_entrypoint.sh
  38. 40 0
      netcon/docker-test/httpd/httpd_demo/test.sh
  39. 1 0
      netcon/docker-test/monitor_identity.public
  40. 1 0
      netcon/docker-test/monitor_identity.secret
  41. 1 0
      netcon/docker-test/netcon_identity.public
  42. 1 0
      netcon/docker-test/netcon_identity.secret
  43. 20 0
      netcon/docker-test/test.sh
  44. 7 7
      netcon/docker-test/zerotier-intercept
  45. BIN
      netcon/libintercept.so.1.0
  46. BIN
      netcon/liblwip.so
  47. 10 10
      netcon/make-intercept.mk
  48. BIN
      netcon/zerotier-cli
  49. 54 0
      netcon/zerotier-intercept
  50. BIN
      netcon/zerotier-one

+ 5 - 5
make-linux.mk

@@ -30,7 +30,7 @@ UNAME_M=$(shell uname -m)
 
 
 INCLUDES=-Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6
 INCLUDES=-Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6
 DEFS=-DZT_ENABLE_NETCON #-DVERBOSE
 DEFS=-DZT_ENABLE_NETCON #-DVERBOSE
-CXXFLAGS+=-Wc++11-compat-deprecated-writable-strings
+CXXFLAGS+=-Wc++11-compat-deprecated-writable-strings -Wformat
 LDLIBS?=
 LDLIBS?=
 
 
 include objects.mk
 include objects.mk
@@ -113,10 +113,10 @@ installer: one FORCE
 
 
 clean:
 clean:
 	rm -rf *.o
 	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
+	find netcon/ -name "*.1.0" -type f -delete
+	find netcon/ -name "*.so" -type f -delete
+	find netcon/ -name "zerotier-one" -type f -delete
+	find netcon/ -name "zerotier-cli" -type f -delete
 	rm -rf netcon/*.o netcon/*.so netcon/*.1.0
 	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
 	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
 
 

+ 2 - 2
netcon/Common.c

@@ -44,7 +44,7 @@
 #define MSG_ERROR       0 // Errors 
 #define MSG_ERROR       0 // Errors 
 #define MSG_INFO        1 // Information which is generally useful to any user
 #define MSG_INFO        1 // Information which is generally useful to any user
 #define MSG_DEBUG       2 // Information which is only useful to someone debugging
 #define MSG_DEBUG       2 // Information which is only useful to someone debugging
-#define MSG_DEBUG_EXTRA 3 // 
+#define MSG_DEBUG_EXTRA 3 // If nothing in your world makes sense
 
 
 #ifdef NETCON_INTERCEPT
 #ifdef NETCON_INTERCEPT
 
 
@@ -77,7 +77,7 @@ void print_addr(struct sockaddr *addr)
 #ifdef NETCON_SERVICE
 #ifdef NETCON_SERVICE
   namespace ZeroTier { 
   namespace ZeroTier { 
 #endif
 #endif
-  void dwr(int level, char *fmt, ... )
+  void dwr(int level, const char *fmt, ... )
   {
   {
     if(level > DEBUG_LEVEL)
     if(level > DEBUG_LEVEL)
         return;
         return;

+ 79 - 89
netcon/Intercept.c

@@ -35,7 +35,6 @@ char *progname = "";
 
 
 #include <unistd.h>
 #include <unistd.h>
 #include <stdint.h>
 #include <stdint.h>
-//#include <pthread.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <dlfcn.h>
 #include <dlfcn.h>
 #include <strings.h>
 #include <strings.h>
@@ -47,7 +46,6 @@ char *progname = "";
 #include <stdarg.h>
 #include <stdarg.h>
 #include <netdb.h>
 #include <netdb.h>
 #include <string.h>
 #include <string.h>
-//#include <stdlib.h>
 #include <sys/syscall.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
@@ -81,7 +79,7 @@ static int (*realaccept4)(ACCEPT4_SIG);
 static long (*realsyscall)(SYSCALL_SIG);
 static long (*realsyscall)(SYSCALL_SIG);
 static int (*realclose)(CLOSE_SIG);
 static int (*realclose)(CLOSE_SIG);
 static int (*realclone)(CLONE_SIG);
 static int (*realclone)(CLONE_SIG);
-//static int (*realpoll)(POLL_SIG);
+/* static int (*realpoll)(POLL_SIG); */
 static int (*realdup2)(DUP2_SIG);
 static int (*realdup2)(DUP2_SIG);
 static int (*realdup3)(DUP3_SIG);
 static int (*realdup3)(DUP3_SIG);
 
 
@@ -99,7 +97,7 @@ int accept4(ACCEPT4_SIG);
 long syscall(SYSCALL_SIG);
 long syscall(SYSCALL_SIG);
 int close(CLOSE_SIG);
 int close(CLOSE_SIG);
 int clone(CLONE_SIG);
 int clone(CLONE_SIG);
-//int poll(POLL_SIG);
+/* int poll(POLL_SIG); */
 int dup2(DUP2_SIG);
 int dup2(DUP2_SIG);
 int dup3(DUP3_SIG);
 int dup3(DUP3_SIG);
 
 
@@ -110,7 +108,6 @@ int dup3(DUP3_SIG);
 
 
 int connect_to_service(void);
 int connect_to_service(void);
 int init_service_connection();
 int init_service_connection();
-//void dwr(const char *fmt, ...);
 void load_symbols(void);
 void load_symbols(void);
 void set_up_intercept();
 void set_up_intercept();
 int checkpid();
 int checkpid();
@@ -129,7 +126,7 @@ void handle_error(char *name, char *info, int err)
 #ifdef ERRORS_ARE_FATAL
 #ifdef ERRORS_ARE_FATAL
   if(err < 0) {
   if(err < 0) {
     dwr(MSG_DEBUG,"handle_error(%s)=%d: FATAL: %s\n", name, err, info);
     dwr(MSG_DEBUG,"handle_error(%s)=%d: FATAL: %s\n", name, err, info);
-    //exit(-1);
+    exit(-1);
   }
   }
 #endif
 #endif
 #ifdef VERBOSE
 #ifdef VERBOSE
@@ -178,7 +175,7 @@ int send_command(int rpc_fd, char *cmd)
   #define IDX_CMD       IDX_TIME + 20 // 20 being the length of the timestamp string
   #define IDX_CMD       IDX_TIME + 20 // 20 being the length of the timestamp string
   #define IDX_PAYLOAD   IDX_TIME + sizeof(char) 
   #define IDX_PAYLOAD   IDX_TIME + sizeof(char) 
   */
   */
-  // [pid_t] [pid_t] [rpc_count] [int] [...]
+  /* [pid_t] [pid_t] [rpc_count] [int] [...] */
   memset(metabuf, '\0', BUF_SZ);
   memset(metabuf, '\0', BUF_SZ);
   pid_t pid = syscall(SYS_getpid);
   pid_t pid = syscall(SYS_getpid);
   pid_t tid = syscall(SYS_gettid);
   pid_t tid = syscall(SYS_gettid);
@@ -187,12 +184,12 @@ int send_command(int rpc_fd, char *cmd)
   time_t timestamp;
   time_t timestamp;
   timestamp = time(NULL);
   timestamp = time(NULL);
   strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(&timestamp));
   strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(&timestamp));
-  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],    &timestring,   20                ); // timestamp
+  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],    &timestring,   20                ); /* timestamp */
 #endif
 #endif
-  // Combine command flag+payload with RPC metadata 
+  /* Combine command flag+payload with RPC metadata */ 
   memcpy(&metabuf[IDX_PAYLOAD], cmd, PAYLOAD_SZ);
   memcpy(&metabuf[IDX_PAYLOAD], cmd, PAYLOAD_SZ);
   int n_write = write(rpc_fd, &metabuf, BUF_SZ);
   int n_write = write(rpc_fd, &metabuf, BUF_SZ);
   if(n_write < 0){
   if(n_write < 0){
@@ -263,41 +260,39 @@ int init_service_connection()
 {
 {
   instance_count++;
   instance_count++;
   dwr(MSG_DEBUG,"init_service_connection()\n");
   dwr(MSG_DEBUG,"init_service_connection()\n");
-  //if(!is_initialized) {
-    struct sockaddr_un addr;
-    int tfd = -1, attempts = 0, conn_err = -1;
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, af_sock_name, sizeof(addr.sun_path)-1);
-
-    dwr(MSG_DEBUG, "init(): pre-realsocket\n");
-    if ( (tfd = realsocket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-      perror("socket error");
-      exit(-1);
-    }
-    dwr(MSG_DEBUG, "init(): post-realsocket, conn_err = %d, attempts = %d\n", conn_err, attempts);
+  struct sockaddr_un addr;
+  int tfd = -1, attempts = 0, conn_err = -1;
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_UNIX;
+  strncpy(addr.sun_path, af_sock_name, sizeof(addr.sun_path)-1);
+
+  dwr(MSG_DEBUG, "init(): pre-realsocket\n");
+  if ( (tfd = realsocket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+    perror("socket error");
+    exit(-1);
+  }
+  dwr(MSG_DEBUG, "init(): post-realsocket, conn_err = %d, attempts = %d\n", conn_err, attempts);
 
 
-    while(conn_err < 0 && attempts < SERVICE_CONNECT_ATTEMPTS) {
-      dwr(MSG_DEBUG, "init(): Attempting!\n");
+  while(conn_err < 0 && attempts < SERVICE_CONNECT_ATTEMPTS) {
+    dwr(MSG_DEBUG, "init(): Attempting!\n");
 
 
-      conn_err = realconnect(tfd, (struct sockaddr*)&addr, sizeof(addr));
-      dwr(MSG_DEBUG, "init(): post-realconnect\n");
+    conn_err = realconnect(tfd, (struct sockaddr*)&addr, sizeof(addr));
+    dwr(MSG_DEBUG, "init(): post-realconnect\n");
 
 
-      if(conn_err < 0) {
-        dwr(MSG_DEBUG,"re-attempting connection in %ds\n", 1+attempts);
-        sleep(1);
-      }
-      else {
-        dwr(MSG_DEBUG,"AF_UNIX connection established: %d\n", tfd);
-        is_initialized = 1;
-        int newtfd = realdup2(tfd, RPC_FD-instance_count);
-        dwr(MSG_DEBUG,"dup'd to rpc_fd = %d\n", newtfd);
-        close(tfd);
-        return newtfd;
-      }
-      attempts++;
+    if(conn_err < 0) {
+      dwr(MSG_DEBUG,"re-attempting connection in %ds\n", 1+attempts);
+      sleep(1);
     }
     }
-  //}
+    else {
+      dwr(MSG_DEBUG,"AF_UNIX connection established: %d\n", tfd);
+      is_initialized = 1;
+      int newtfd = realdup2(tfd, RPC_FD-instance_count);
+      dwr(MSG_DEBUG,"dup'd to rpc_fd = %d\n", newtfd);
+      close(tfd);
+      return newtfd;
+    }
+    attempts++;
+  }
   return -1;
   return -1;
 }
 }
 
 
@@ -307,7 +302,7 @@ int init_service_connection()
 
 
 void my_dest(void) __attribute__ ((destructor));
 void my_dest(void) __attribute__ ((destructor));
 void my_dest(void) {
 void my_dest(void) {
-  //dwr(MSG_DEBUG,"closing connections to service...\n");
+  dwr(MSG_DEBUG,"closing connections to service...\n");
   close(fdret_sock);
   close(fdret_sock);
   pthread_mutex_destroy(&lock);
   pthread_mutex_destroy(&lock);
 }
 }
@@ -321,10 +316,7 @@ void load_symbols(void)
   if(thispid == getpid()) {
   if(thispid == getpid()) {
     dwr(MSG_DEBUG,"detected duplicate call to global ctor (pid=%d).\n", thispid);
     dwr(MSG_DEBUG,"detected duplicate call to global ctor (pid=%d).\n", thispid);
   }
   }
-  //dwr(MSG_DEBUG," -- pid = %d\n", getpid());
-	//dwr(MSG_DEBUG," -- uid = %d\n", getuid());
   thispid = getpid();
   thispid = getpid();
-  //thistid = gettid();
 
 
 #ifndef USE_OLD_DLSYM
 #ifndef USE_OLD_DLSYM
   realconnect = dlsym(RTLD_NEXT, "connect");
   realconnect = dlsym(RTLD_NEXT, "connect");
@@ -340,7 +332,7 @@ void load_symbols(void)
   realclone = dlsym(RTLD_NEXT, "clone");
   realclone = dlsym(RTLD_NEXT, "clone");
   realclose = dlsym(RTLD_NEXT, "close");
   realclose = dlsym(RTLD_NEXT, "close");
   realsyscall = dlsym(RTLD_NEXT, "syscall");
   realsyscall = dlsym(RTLD_NEXT, "syscall");
-  //realsyscall = dlsym(RTLD_NEXT, "poll");
+  /* realsyscall = dlsym(RTLD_NEXT, "poll"); */
   realdup2 = dlsym(RTLD_NEXT, "dup2");
   realdup2 = dlsym(RTLD_NEXT, "dup2");
   realdup3 = dlsym(RTLD_NEXT, "dup3");
   realdup3 = dlsym(RTLD_NEXT, "dup3");
 #ifdef USE_SOCKS_DNS
 #ifdef USE_SOCKS_DNS
@@ -361,7 +353,7 @@ void load_symbols(void)
   realclone = dlsym(lib, "clone");
   realclone = dlsym(lib, "clone");
   realclose = dlsym(lib, "close");
   realclose = dlsym(lib, "close");
   realsyscall = dlsym(lib, "syscall");
   realsyscall = dlsym(lib, "syscall");
-  //realsyscall = dlsym(lib, "poll");
+  /* realsyscall = dlsym(lib, "poll"); */
   realdup2 = dlsym(RTLD_NEXT, "dup2");
   realdup2 = dlsym(RTLD_NEXT, "dup2");
   realdup3 = dlsym(RTLD_NEXT, "dup3");
   realdup3 = dlsym(RTLD_NEXT, "dup3");
 #ifdef USE_SOCKS_DNS
 #ifdef USE_SOCKS_DNS
@@ -384,10 +376,10 @@ void set_up_intercept()
 {
 {
   load_symbols();
   load_symbols();
   if(pthread_mutex_init(&lock, NULL) != 0) {
   if(pthread_mutex_init(&lock, NULL) != 0) {
-    printf("error while initializing service call mutex\n");
+    dwr(MSG_ERROR, "error while initializing service call mutex\n");
   }
   }
   if(pthread_mutex_init(&loglock, NULL) != 0) {
   if(pthread_mutex_init(&loglock, NULL) != 0) {
-    printf("error while initializing log mutex mutex\n");
+    dwr(MSG_ERROR, "error while initializing log mutex mutex\n");
   }
   }
 }
 }
 
 
@@ -409,7 +401,7 @@ int setsockopt(SETSOCKOPT_SIG)
     return realsetsockopt(socket, level, option_name, option_value, option_len);
     return realsetsockopt(socket, level, option_name, option_value, option_len);
   }
   }
   */
   */
-  //return(realsetsockopt(socket, level, option_name, option_value, option_len));
+  /* return(realsetsockopt(socket, level, option_name, option_value, option_len)); */
   if(level == SOL_IPV6 && option_name == IPV6_V6ONLY)
   if(level == SOL_IPV6 && option_name == IPV6_V6ONLY)
     return 0;
     return 0;
   if(level == SOL_IP && option_name == IP_TTL)
   if(level == SOL_IP && option_name == IP_TTL)
@@ -421,7 +413,7 @@ int setsockopt(SETSOCKOPT_SIG)
     return(realsetsockopt(socket, level, option_name, option_value, option_len));
     return(realsetsockopt(socket, level, option_name, option_value, option_len));
   int err = realsetsockopt(socket, level, option_name, option_value, option_len);
   int err = realsetsockopt(socket, level, option_name, option_value, option_len);
   if(err < 0){
   if(err < 0){
-    //perror("setsockopt():\n");
+    perror("setsockopt():\n");
   }
   }
   return 0;
   return 0;
 }
 }
@@ -445,8 +437,8 @@ int getsockopt(GETSOCKOPT_SIG)
   }
   }
   */
   */
   int err = realgetsockopt(sockfd, level, optname, optval, optlen);
   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
+  /* TODO: 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 */
   if(optname == SO_TYPE)
   if(optname == SO_TYPE)
   {
   {
     int* val = (int*)optval;
     int* val = (int*)optval;
@@ -454,7 +446,7 @@ int getsockopt(GETSOCKOPT_SIG)
     optval = (void*)val;
     optval = (void*)val;
   }
   }
   if(err < 0){
   if(err < 0){
-    //perror("setsockopt():\n");
+    perror("setsockopt():\n");
   }
   }
   return 0;
   return 0;
 }
 }
@@ -503,7 +495,7 @@ int socket(SOCKET_SIG)
     return -1;
     return -1;
   }
   }
   */
   */
-  /* FIXME: detect ENFILE condition */
+  /* TODO: detect ENFILE condition */
 #endif
 #endif
   char cmd[BUF_SZ];
   char cmd[BUF_SZ];
   fdret_sock = !is_initialized ? init_service_connection() : fdret_sock;
   fdret_sock = !is_initialized ? init_service_connection() : fdret_sock;
@@ -544,14 +536,14 @@ int socket(SOCKET_SIG)
     cmd[0] = RPC_MAP;
     cmd[0] = RPC_MAP;
     memcpy(&cmd[1], &newfd, sizeof(newfd));
     memcpy(&cmd[1], &newfd, sizeof(newfd));
 
 
-    if(newfd > -1) { // FIXME: check logic
+    if(newfd > -1) { 
       send_command(fdret_sock, cmd);
       send_command(fdret_sock, cmd);
       pthread_mutex_unlock(&lock);
       pthread_mutex_unlock(&lock);
-      errno = ERR_OK; // OK
+      errno = ERR_OK; /* OK */
       handle_error("socket6", "", newfd);
       handle_error("socket6", "", newfd);
       return newfd;
       return newfd;
     }
     }
-    else { // Try to read retval+errno since we RXed a bad fd
+    else { /* Try to read retval+errno since we RXed a bad fd */
       dwr(MSG_DEBUG,"Error, service sent bad fd.\n");
       dwr(MSG_DEBUG,"Error, service sent bad fd.\n");
       err = get_retval();
       err = get_retval();
       pthread_mutex_unlock(&lock);
       pthread_mutex_unlock(&lock);
@@ -625,7 +617,7 @@ int connect(CONNECT_SIG)
     || connaddr->sin_family == AF_UNIX)) {
     || connaddr->sin_family == AF_UNIX)) {
     int err = realconnect(__fd, __addr, __len);
     int err = realconnect(__fd, __addr, __len);
     perror("connect():");
     perror("connect():");
-    //handle_error("connect", "Cannot connect to local socket", err);
+    /* handle_error("connect", "Cannot connect to local socket", err); */
     return err;
     return err;
   }
   }
 
 
@@ -644,13 +636,13 @@ int connect(CONNECT_SIG)
   send_command(fdret_sock, cmd);
   send_command(fdret_sock, cmd);
   /*
   /*
   if(sock_type && O_NONBLOCK) {
   if(sock_type && O_NONBLOCK) {
-    //pthread_mutex_unlock(&lock);
-    //return EINPROGRESS;
+    pthread_mutex_unlock(&lock);
+    return EINPROGRESS;
   }
   }
   */
   */
   err = get_retval();
   err = get_retval();
   pthread_mutex_unlock(&lock);
   pthread_mutex_unlock(&lock);
-  //handle_error("connect", "", err);
+  /* handle_error("connect", "", err); */
   return err;
   return err;
 }
 }
 
 
@@ -666,7 +658,7 @@ int select(SELECT_SIG)
     dwr(MSG_ERROR, "select(): SYMBOL NOT FOUND.\n");
     dwr(MSG_ERROR, "select(): SYMBOL NOT FOUND.\n");
     return -1;
     return -1;
   }
   }
-  //dwr(MSG_DEBUG,"select():\n");
+  /* dwr(MSG_DEBUG,"select():\n"); */
   return realselect(n, readfds, writefds, exceptfds, timeout);
   return realselect(n, readfds, writefds, exceptfds, timeout);
 }
 }
 
 
@@ -717,7 +709,6 @@ int bind(BIND_SIG)
       dwr(MSG_DEBUG,"realbind, err = %d\n", err);
       dwr(MSG_DEBUG,"realbind, err = %d\n", err);
       return err;
       return err;
   }
   }
-
   /* Assemble and send RPC */
   /* Assemble and send RPC */
   char cmd[BUF_SZ];
   char cmd[BUF_SZ];
   struct bind_st rpc_st;
   struct bind_st rpc_st;
@@ -839,13 +830,15 @@ int accept(ACCEPT_SIG)
     handle_error("accept", "Unresolved symbol [accept]", -1);
     handle_error("accept", "Unresolved symbol [accept]", -1);
     return -1;
     return -1;
   }
   }
-  //if(opt & O_NONBLOCK)
-    //fcntl(sockfd, F_SETFL, O_NONBLOCK);
+  /*
+    if(opt & O_NONBLOCK)
+      fcntl(sockfd, F_SETFL, O_NONBLOCK);
+  */
 
 
   char rbuf[16], c[1];
   char rbuf[16], c[1];
   int new_conn_socket;
   int new_conn_socket;
+  int n = read(sockfd, c, sizeof(c)); /* Read signal byte */
 
 
-  int n = read(sockfd, c, sizeof(c)); // Read signal byte
   if(n > 0)
   if(n > 0)
   {
   {
     new_conn_socket = get_new_fd(fdret_sock);
     new_conn_socket = get_new_fd(fdret_sock);
@@ -858,12 +851,10 @@ int accept(ACCEPT_SIG)
       pthread_mutex_lock(&lock);
       pthread_mutex_lock(&lock);
 
 
       dwr(MSG_DEBUG, "accept(): sending perceived fd (%d) to service.\n", new_conn_socket);
       dwr(MSG_DEBUG, "accept(): sending perceived fd (%d) to service.\n", new_conn_socket);
-      //int n_write = write(fdret_sock, cmd, BUF_SZ);
-
       int n_write = send_command(fdret_sock, cmd);
       int n_write = send_command(fdret_sock, cmd);
 
 
       if(n_write < 0) {
       if(n_write < 0) {
-        errno = ECONNABORTED; // FIXME: Closest match, service unreachable
+        errno = ECONNABORTED; /* TODO: Closest match, service unreachable */
         handle_error("accept", "ECONNABORTED - Error sending perceived FD to service", -1);
         handle_error("accept", "ECONNABORTED - Error sending perceived FD to service", -1);
         return -1;
         return -1;
       }
       }
@@ -871,10 +862,10 @@ int accept(ACCEPT_SIG)
       errno = ERR_OK;
       errno = ERR_OK;
       dwr(MSG_DEBUG,"*accept()=%d\n", new_conn_socket);
       dwr(MSG_DEBUG,"*accept()=%d\n", new_conn_socket);
       handle_error("accept", "", new_conn_socket);
       handle_error("accept", "", new_conn_socket);
-      return new_conn_socket; // OK
+      return new_conn_socket; /* OK */
     }
     }
     else {
     else {
-      errno = ECONNABORTED; // FIXME: Closest match, service unreachable
+      errno = ECONNABORTED; /* TODO: Closest match, service unreachable */
       handle_error("accept", "ECONNABORTED - Error receiving new FD from service", -1);
       handle_error("accept", "ECONNABORTED - Error receiving new FD from service", -1);
       return -1;
       return -1;
     }
     }
@@ -927,7 +918,7 @@ int listen(LISTEN_SIG)
     return(reallisten(sockfd, backlog));
     return(reallisten(sockfd, backlog));
 
 
   if(is_mapped_to_service(sockfd) < 0) {
   if(is_mapped_to_service(sockfd) < 0) {
-    // We now know this socket is not one of our socketpairs
+    /* We now know this socket is not one of our socketpairs */
     int err = reallisten(sockfd, backlog);
     int err = reallisten(sockfd, backlog);
     dwr(MSG_DEBUG,"reallisten()=%d\n", err);
     dwr(MSG_DEBUG,"reallisten()=%d\n", err);
     return err;
     return err;
@@ -944,7 +935,7 @@ int listen(LISTEN_SIG)
   memcpy(&cmd[1], &rpc_st, sizeof(struct listen_st));
   memcpy(&cmd[1], &rpc_st, sizeof(struct listen_st));
   pthread_mutex_lock(&lock);
   pthread_mutex_lock(&lock);
   send_command(fdret_sock, cmd);
   send_command(fdret_sock, cmd);
-  /*int err = */get_retval();
+  get_retval();
   pthread_mutex_unlock(&lock);
   pthread_mutex_unlock(&lock);
   handle_error("listen", "", ERR_OK);
   handle_error("listen", "", ERR_OK);
   return ERR_OK;
   return ERR_OK;
@@ -954,7 +945,7 @@ int listen(LISTEN_SIG)
 -------------------------------------- clone()----------------------------------
 -------------------------------------- clone()----------------------------------
 ------------------------------------------------------------------------------*/
 ------------------------------------------------------------------------------*/
 
 
-// int (*fn)(void *), void *child_stack, int flags, void *arg, ...
+/* int (*fn)(void *), void *child_stack, int flags, void *arg, ... */
 int clone(CLONE_SIG)
 int clone(CLONE_SIG)
 {
 {
   if(realclone == NULL){
   if(realclone == NULL){
@@ -972,13 +963,12 @@ int clone(CLONE_SIG)
 -------------------------------------- poll()-----------------------------------
 -------------------------------------- poll()-----------------------------------
 ------------------------------------------------------------------------------*/
 ------------------------------------------------------------------------------*/
 
 
-// struct pollfd *fds, nfds_t nfds, int timeout
+/* struct pollfd *fds, nfds_t nfds, int timeout */
 /*
 /*
 int poll(POLL_SIG)
 int poll(POLL_SIG)
 {
 {
   dwr(MSG_DEBUG,"poll()\n");
   dwr(MSG_DEBUG,"poll()\n");
   return realpoll(fds, nfds, timeout);
   return realpoll(fds, nfds, timeout);
-  //return ERESTART_RESTARTBLOCK;
 }
 }
 */
 */
 
 
@@ -986,17 +976,17 @@ int poll(POLL_SIG)
 -------------------------------------- close()-----------------------------------
 -------------------------------------- close()-----------------------------------
 ------------------------------------------------------------------------------*/
 ------------------------------------------------------------------------------*/
 
 
-// int fd
+/* int fd */
 int close(CLOSE_SIG)
 int close(CLOSE_SIG)
 {
 {
-  //checkpid(); // Required for httpd-2.4.17-3.x86_64 -- After clone, some symbols aren't initialized yet
+  /* checkpid(); // Required for httpd-2.4.17-3.x86_64 -- After clone, some symbols aren't initialized yet */
   if(realclose == NULL){
   if(realclose == NULL){
     dwr(MSG_ERROR, "close(): SYMBOL NOT FOUND.\n");
     dwr(MSG_ERROR, "close(): SYMBOL NOT FOUND.\n");
     return -1;
     return -1;
   }
   }
   dwr(MSG_DEBUG,"close(%d)\n", fd);
   dwr(MSG_DEBUG,"close(%d)\n", fd);
   if(fd == fdret_sock)
   if(fd == fdret_sock)
-    return -1; // FIXME: Ignore request to shut down our rpc fd, this is *almost always* safe
+    return -1; /* TODO: Ignore request to shut down our rpc fd, this is *almost always* safe */
   if(fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
   if(fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
     return realclose(fd);
     return realclose(fd);
   return -1;
   return -1;
@@ -1006,7 +996,7 @@ int close(CLOSE_SIG)
 -------------------------------------- dup2()-----------------------------------
 -------------------------------------- dup2()-----------------------------------
 ------------------------------------------------------------------------------*/
 ------------------------------------------------------------------------------*/
 
 
-// int oldfd, int newfd
+/* int oldfd, int newfd */
 int dup2(DUP2_SIG)
 int dup2(DUP2_SIG)
 {
 {
   if(realdup2 == NULL){
   if(realdup2 == NULL){
@@ -1029,7 +1019,7 @@ int dup2(DUP2_SIG)
 -------------------------------------- dup3()-----------------------------------
 -------------------------------------- dup3()-----------------------------------
 ------------------------------------------------------------------------------*/
 ------------------------------------------------------------------------------*/
 
 
-// int oldfd, int newfd, int flags
+/* int oldfd, int newfd, int flags */
 int dup3(DUP3_SIG)
 int dup3(DUP3_SIG)
 {
 {
   if(realdup3 == NULL){
   if(realdup3 == NULL){
@@ -1038,11 +1028,11 @@ int dup3(DUP3_SIG)
   }
   }
   dwr(MSG_DEBUG,"dup3(%d, %d, %d)\n", oldfd, newfd, flags);
   dwr(MSG_DEBUG,"dup3(%d, %d, %d)\n", oldfd, newfd, flags);
 #ifdef DEBUG
 #ifdef DEBUG
-  // Only do this check if we want to debug the intercept, otherwise, dont mess with 
-  // the client application's logging methods
+  /* 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)
   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
+    return newfd; /* FIXME: This is to prevent httpd from dup'ing over our stderr 
+                   and preventing us from debugging */
   else
   else
 #endif
 #endif
     return realdup3(oldfd, newfd, flags);
     return realdup3(oldfd, newfd, flags);
@@ -1089,7 +1079,7 @@ long syscall(SYSCALL_SIG){
     errno = old_errno;
     errno = old_errno;
 
 
     if(err == -EBADF) { 
     if(err == -EBADF) { 
-      err = -EAGAIN; // For hysterical raisons
+      err = -EAGAIN; /* For hysterical raisins */
     }
     }
 
 
     return err;
     return err;

+ 51 - 50
netcon/Intercept.h

@@ -31,68 +31,68 @@
 
 
 #include <sys/socket.h>
 #include <sys/socket.h>
 
 
-#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 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 PAYLOAD_SZ			223 // BUF_SZ-IDX_PAYLOAD
+#define BUF_SZ          256
+#define PAYLOAD_SZ		223 /* BUF_SZ-IDX_PAYLOAD */
 
 
-#define ERR_OK                  0
+#define ERR_OK          0
 
 
 /* Userland RPC codes */
 /* Userland RPC codes */
-#define RPC_UNDEFINED			 			0
-#define RPC_CONNECT				 			1
+#define RPC_UNDEFINED			 	0
+#define RPC_CONNECT				 	1
 #define RPC_CONNECT_SOCKARG		 	2
 #define RPC_CONNECT_SOCKARG		 	2
-#define RPC_SELECT			 				3
-#define RPC_POLL				 				4
-#define RPC_CLOSE				 				5
-#define RPC_READ				 				6
-#define RPC_WRITE				 				7
-#define RPC_BIND				 				8
-#define RPC_ACCEPT			 				9
-#define RPC_LISTEN			 				10
-#define RPC_SOCKET			 				11
-#define RPC_SHUTDOWN		 				12
+#define RPC_SELECT			 		3
+#define RPC_POLL				 	4
+#define RPC_CLOSE				 	5
+#define RPC_READ				 	6
+#define RPC_WRITE				 	7
+#define RPC_BIND				 	8
+#define RPC_ACCEPT			 		9
+#define RPC_LISTEN			 		10
+#define RPC_SOCKET			 		11
+#define RPC_SHUTDOWN		 		12
 
 
 /* Administration RPC codes */
 /* Administration RPC codes */
-#define RPC_MAP									20	// Give the service the value we "see" for the new buffer fd
-#define RPC_MAP_REQ							21  // A call to determine whether an fd is mapped to the service
-#define RPC_RETVAL							22	// not RPC per se, but something we should codify
-#define RPC_KILL_INTERCEPT			23  // Tells the service we need to shut down all connections
+#define RPC_MAP						20	/* Give the service the value we "see" for the new buffer fd */
+#define RPC_MAP_REQ					21  /* A call to determine whether an fd is mapped to the service */
+#define RPC_RETVAL					22	/* not RPC per se, but something we should codify */
+#define RPC_KILL_INTERCEPT			23  /* Tells the service we need to shut down all connections */
 
 
 /* Connection statuses */
 /* Connection statuses */
-#define UNSTARTED								0
-#define CONNECTING			 				1
-#define CONNECTED				 				2
-#define SENDING					 				3
-#define RECEIVING				 				4
-#define SENTV4REQ				 				5
-#define GOTV4REQ				 				6
-#define SENTV5METHOD			 			7
-#define GOTV5METHOD				 			8
-#define SENTV5AUTH			 				9
-#define GOTV5AUTH				 				10
-#define SENTV5CONNECT			 			11
-#define GOTV5CONNECT			 			12
-#define DONE					 					13
-#define FAILED				 					14
+#define UNSTARTED					0
+#define CONNECTING			 		1
+#define CONNECTED				 	2
+#define SENDING					 	3
+#define RECEIVING				 	4
+#define SENTV4REQ				 	5
+#define GOTV4REQ				 	6
+#define SENTV5METHOD			 	7
+#define GOTV5METHOD				 	8
+#define SENTV5AUTH			 		9
+#define GOTV5AUTH				 	10
+#define SENTV5CONNECT			 	11
+#define GOTV5CONNECT			 	12
+#define DONE					 	13
+#define FAILED				 		14
 
 
 /* Flags to indicate what events a
 /* Flags to indicate what events a
    socket was select()ed for */
    socket was select()ed for */
-#define READ					 					(POLLIN|POLLRDNORM)
-#define WRITE					 					(POLLOUT|POLLWRNORM|POLLWRBAND)
-#define EXCEPT				 					(POLLRDBAND|POLLPRI)
-#define READWRITE				 				(READ|WRITE)
-#define READWRITEEXCEPT			 		(READ|WRITE|EXCEPT)
+#define READ (POLLIN|POLLRDNORM)
+#define WRITE (POLLOUT|POLLWRNORM|POLLWRBAND)
+#define EXCEPT (POLLRDBAND|POLLPRI)
+#define READWRITE (READ|WRITE)
+#define READWRITEEXCEPT (READ|WRITE|EXCEPT)
 
 
 
 
 /* for AF_UNIX sockets */
 /* for AF_UNIX sockets */
 #define MAX_PATH_NAME_SIZE 64
 #define MAX_PATH_NAME_SIZE 64
 
 
-// bind
+/* bind */
 #define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
 #define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
 struct bind_st
 struct bind_st
 {
 {
@@ -102,7 +102,7 @@ struct bind_st
 	int __tid;
 	int __tid;
 };
 };
 
 
-// connect
+/* connect */
 #define CONNECT_SIG int __fd, const struct sockaddr * __addr, socklen_t __len
 #define CONNECT_SIG int __fd, const struct sockaddr * __addr, socklen_t __len
 struct connect_st
 struct connect_st
 {
 {
@@ -112,16 +112,16 @@ struct connect_st
 	int __tid;
 	int __tid;
 };
 };
 
 
-// close
+/* close */
 #define CLOSE_SIG int fd
 #define CLOSE_SIG int fd
 struct close_st
 struct close_st
 {
 {
 	int fd;
 	int fd;
 };
 };
 
 
-// read
+/* read */
 #define DEFAULT_READ_BUFFER_SIZE	1024 * 63
 #define DEFAULT_READ_BUFFER_SIZE	1024 * 63
-// read buffer sizes (on test machine) min: 4096    default: 87380   max:6147872
+/* read buffer sizes (on test machine) min: 4096    default: 87380   max:6147872 */
 #define READ_SIG int __fd, void *__buf, size_t __nbytes
 #define READ_SIG int __fd, void *__buf, size_t __nbytes
 struct read_st
 struct read_st
 {
 {
@@ -130,8 +130,9 @@ struct read_st
 	unsigned char buf[DEFAULT_READ_BUFFER_SIZE];
 	unsigned char buf[DEFAULT_READ_BUFFER_SIZE];
 };
 };
 
 
+/* write */
 #define DEFAULT_WRITE_BUFFER_SIZE	1024 * 63
 #define DEFAULT_WRITE_BUFFER_SIZE	1024 * 63
-// write buffer sizes (on test machine) min: 4096    default: 16384   max:4194304
+/* write buffer sizes (on test machine) min: 4096    default: 16384   max:4194304 */
 #define WRITE_SIG int __fd, const void *__buf, size_t __n
 #define WRITE_SIG int __fd, const void *__buf, size_t __n
 struct write_st
 struct write_st
 {
 {

+ 0 - 18
netcon/LWIPStack.hpp

@@ -31,23 +31,6 @@
 #include "lwip/ip_addr.h"
 #include "lwip/ip_addr.h"
 #include "lwip/netif.h"
 #include "lwip/netif.h"
 
 
-/*
-#include "lwip/timers.h"
-#include "lwip/opt.h"
-#include "lwip/init.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
-#include "lwip/sys.h"
-#include "lwip/stats.h"
-//#include "lwip/tcp_impl.h"
-//#include "lwip/inet_chksum.h"
-#include "lwip/tcpip.h"
-//#include "lwip/ip_addr.h"
-#include "lwip/debug.h"
-//#include "lwip/ip.h"
-//#include "lwip/ip_frag.h"
-*/
-
 #include "../node/Mutex.hpp"
 #include "../node/Mutex.hpp"
 
 
 #include <stdio.h>
 #include <stdio.h>
@@ -61,7 +44,6 @@
 #endif
 #endif
 
 
 typedef ip_addr ip_addr_t;
 typedef ip_addr ip_addr_t;
-
 struct tcp_pcb;
 struct tcp_pcb;
 
 
 #define TCP_WRITE_SIG struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags
 #define TCP_WRITE_SIG struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags

+ 18 - 21
netcon/NetconEthernetTap.cpp

@@ -49,6 +49,7 @@
 #include "Intercept.h"
 #include "Intercept.h"
 #include "NetconUtilities.hpp"
 #include "NetconUtilities.hpp"
 #include "Common.c"
 #include "Common.c"
+#include "Sendfd.c"
 
 
 #define APPLICATION_POLL_FREQ 			20
 #define APPLICATION_POLL_FREQ 			20
 #define ZT_LWIP_TCP_TIMER_INTERVAL 		5
 #define ZT_LWIP_TCP_TIMER_INTERVAL 		5
@@ -76,6 +77,7 @@ NetconEthernetTap::NetconEthernetTap(
 	_enabled(true),
 	_enabled(true),
 	_run(true)
 	_run(true)
 {
 {
+	rpc_counter = -1;
 	char sockPath[4096];
 	char sockPath[4096];
 	Utils::snprintf(sockPath,sizeof(sockPath),"/tmp/.ztnc_%.16llx",(unsigned long long)nwid);
 	Utils::snprintf(sockPath,sizeof(sockPath),"/tmp/.ztnc_%.16llx",(unsigned long long)nwid);
 	_dev = sockPath;
 	_dev = sockPath;
@@ -292,19 +294,15 @@ void NetconEthernetTap::compact_dump()
  */
  */
 void NetconEthernetTap::dump()
 void NetconEthernetTap::dump()
 {
 {
-	/*
-	clearscreen();
-	gotoxy(0,0);
-	*/
 	fprintf(stderr, "\n\n---\n\ndie(): BEGIN SERVICE STATE DUMP\n");
 	fprintf(stderr, "\n\n---\n\ndie(): BEGIN SERVICE STATE DUMP\n");
 	fprintf(stderr, "*** IF YOU SEE THIS, EMAIL THE DUMP TEXT TO [email protected] ***\n");
 	fprintf(stderr, "*** IF YOU SEE THIS, EMAIL THE DUMP TEXT TO [email protected] ***\n");
-	fprintf(stderr, " tcp_conns = %d, rpc_socks = %d\n", tcp_connections.size(), rpc_sockets.size());
+	fprintf(stderr, " tcp_conns = %lu, rpc_socks = %lu\n", tcp_connections.size(), rpc_sockets.size());
 
 
   	// TODO: Add logic to detect bad mapping conditions
   	// TODO: Add logic to detect bad mapping conditions
 	for(size_t i=0; i<rpc_sockets.size(); i++) {
 	for(size_t i=0; i<rpc_sockets.size(); i++) {
 		for(size_t j=0; j<rpc_sockets.size(); j++) {
 		for(size_t j=0; j<rpc_sockets.size(); j++) {
 			if(j != i && rpc_sockets[i] == rpc_sockets[j]) {
 			if(j != i && rpc_sockets[i] == rpc_sockets[j]) {
-				fprintf(stderr, "Duplicate PhySockets found! (0x%x)\n", rpc_sockets[i]);
+				fprintf(stderr, "Duplicate PhySockets found! (0x%p)\n", rpc_sockets[i]);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -316,20 +314,20 @@ void NetconEthernetTap::dump()
 		int pid = pidmap[rpc_sockets[i]];
 		int pid = pidmap[rpc_sockets[i]];
 		get_path_from_pid(buf, pid);
 		get_path_from_pid(buf, pid);
 
 
-		fprintf(stderr, "\nClient(addr=0x%x, rpc=%d, pid=%d) %s\n", rpc_sockets[i], rpc_fd, pid, buf);
+		fprintf(stderr, "\nClient(addr=0x%p, rpc=%d, pid=%d) %s\n", rpc_sockets[i], rpc_fd, pid, buf);
 		for(size_t j=0; j<tcp_connections.size(); j++) {
 		for(size_t j=0; j<tcp_connections.size(); j++) {
 			get_path_from_pid(buf, tcp_connections[j]->pid);
 			get_path_from_pid(buf, tcp_connections[j]->pid);
 			if(tcp_connections[j]->rpcSock==rpc_sockets[i]){
 			if(tcp_connections[j]->rpcSock==rpc_sockets[i]){
 				fprintf(stderr, "  |\n");
 				fprintf(stderr, "  |\n");
-				fprintf(stderr, "  |-Connection(0x%x):\n", tcp_connections[j]);
+				fprintf(stderr, "  |-Connection(0x%p):\n", tcp_connections[j]);
 				fprintf(stderr, "  |      path\t\t\t= %s\n", buf);
 				fprintf(stderr, "  |      path\t\t\t= %s\n", buf);
 				fprintf(stderr, "  |      perceived_fd\t\t= %d\t(fd)\n", tcp_connections[j]->perceived_fd);
 				fprintf(stderr, "  |      perceived_fd\t\t= %d\t(fd)\n", tcp_connections[j]->perceived_fd);
 				fprintf(stderr, "  |      their_fd\t\t= %d\t(fd)\n", tcp_connections[j]->their_fd);
 				fprintf(stderr, "  |      their_fd\t\t= %d\t(fd)\n", tcp_connections[j]->their_fd);
-				fprintf(stderr, "  |      dataSock(0x%x)\t= %d\t(fd)\n", tcp_connections[j]->dataSock, _phy.getDescriptor(tcp_connections[j]->dataSock));
-				fprintf(stderr, "  |      rpcSock(0x%x)\t= %d\t(fd)\n", tcp_connections[j]->rpcSock, _phy.getDescriptor(tcp_connections[j]->rpcSock));
+				fprintf(stderr, "  |      dataSock(0x%p)\t= %d\t(fd)\n", tcp_connections[j]->dataSock, _phy.getDescriptor(tcp_connections[j]->dataSock));
+				fprintf(stderr, "  |      rpcSock(0x%p)\t= %d\t(fd)\n", tcp_connections[j]->rpcSock, _phy.getDescriptor(tcp_connections[j]->rpcSock));
 				fprintf(stderr, "  |      pending\t\t= %d\n", tcp_connections[j]->pending);
 				fprintf(stderr, "  |      pending\t\t= %d\n", tcp_connections[j]->pending);
 				fprintf(stderr, "  |      listening\t\t= %d\n", tcp_connections[j]->listening);
 				fprintf(stderr, "  |      listening\t\t= %d\n", tcp_connections[j]->listening);
-				fprintf(stderr, "  \\------pcb(0x%x)->state\t= %d\n", tcp_connections[j]->pcb, tcp_connections[j]->pcb->state);
+				fprintf(stderr, "  \\------pcb(0x%p)->state\t= %d\n", tcp_connections[j]->pcb, tcp_connections[j]->pcb->state);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -408,7 +406,6 @@ void NetconEthernetTap::closeAll()
 void NetconEthernetTap::threadMain()
 void NetconEthernetTap::threadMain()
 	throw()
 	throw()
 {
 {
-	//signal(SIGPIPE, SIG_IGN);
 	uint64_t prev_tcp_time = 0;
 	uint64_t prev_tcp_time = 0;
 	uint64_t prev_status_time = 0;
 	uint64_t prev_status_time = 0;
 	uint64_t prev_etharp_time = 0;
 	uint64_t prev_etharp_time = 0;
@@ -446,10 +443,11 @@ void NetconEthernetTap::threadMain()
 
 
 		// Connection prunning
 		// Connection prunning
 		if (since_status >= STATUS_TMR_INTERVAL) {
 		if (since_status >= STATUS_TMR_INTERVAL) {
-			compact_dump();
+			//compact_dump();
 			prev_status_time = now;
 			prev_status_time = now;
+			status_remaining = STATUS_TMR_INTERVAL - since_status;
 			if(rpc_sockets.size() || tcp_connections.size()) {
 			if(rpc_sockets.size() || tcp_connections.size()) {
-/*
+
 				// dump();
 				// dump();
 				// Here we will periodically check the list of rpc_sockets for those that
 				// Here we will periodically check the list of rpc_sockets for those that
 				// do not currently have any data connection associated with them. If they are
 				// do not currently have any data connection associated with them. If they are
@@ -495,7 +493,6 @@ void NetconEthernetTap::threadMain()
 							phyOnUnixData(rpc_sockets[i],_phy.getuptr(rpc_sockets[i]),&tmpbuf,BUF_SZ);
 							phyOnUnixData(rpc_sockets[i],_phy.getuptr(rpc_sockets[i]),&tmpbuf,BUF_SZ);
 					}
 					}
 				}
 				}
-				*/
 			}
 			}
 		}
 		}
 		// Main TCP/ETHARP timer section
 		// Main TCP/ETHARP timer section
@@ -528,7 +525,7 @@ void NetconEthernetTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
 void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
 void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
 	dwr(MSG_DEBUG, " phyOnUnixClose(sock=0x%x, uptr=0x%x): fd = %d\n", sock, uptr, _phy.getDescriptor(sock));
 	dwr(MSG_DEBUG, " phyOnUnixClose(sock=0x%x, uptr=0x%x): fd = %d\n", sock, uptr, _phy.getDescriptor(sock));
 	TcpConnection *conn = (TcpConnection*)*uptr;
 	TcpConnection *conn = (TcpConnection*)*uptr;
-	//closeConnection(conn);
+	closeConnection(conn);
 }
 }
 
 
 /*
 /*
@@ -752,7 +749,7 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
     tap->lwipstack->_tcp_recv(newpcb, nc_recved);
     tap->lwipstack->_tcp_recv(newpcb, nc_recved);
     tap->lwipstack->_tcp_err(newpcb, nc_err);
     tap->lwipstack->_tcp_err(newpcb, nc_err);
     tap->lwipstack->_tcp_sent(newpcb, nc_sent);
     tap->lwipstack->_tcp_sent(newpcb, nc_sent);
-    tap->lwipstack->_tcp_poll(newpcb, nc_poll, 0.5);
+    tap->lwipstack->_tcp_poll(newpcb, nc_poll, 1);
     tcp_accepted(conn->pcb); // Let lwIP know that it can queue additional incoming connections
     tcp_accepted(conn->pcb); // Let lwIP know that it can queue additional incoming connections
 		return ERR_OK;
 		return ERR_OK;
   }
   }
@@ -1238,7 +1235,7 @@ TcpConnection * NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, s
 	int rpc_fd = _phy.getDescriptor(sock);
 	int rpc_fd = _phy.getDescriptor(sock);
 	struct tcp_pcb *newpcb = lwipstack->tcp_new();
 	struct tcp_pcb *newpcb = lwipstack->tcp_new();
 	dwr(MSG_DEBUG, " handle_socket(): pcb=%x\n", newpcb);
 	dwr(MSG_DEBUG, " handle_socket(): pcb=%x\n", newpcb);
-  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) {
@@ -1252,12 +1249,12 @@ TcpConnection * NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, s
 		*uptr = new_conn;
 		*uptr = new_conn;
 		new_conn->rpcSock = sock;
 		new_conn->rpcSock = sock;
 		new_conn->pcb = newpcb;
 		new_conn->pcb = newpcb;
-	  new_conn->their_fd = fds[1];
+	    new_conn->their_fd = fds[1];
 		tcp_connections.push_back(new_conn);
 		tcp_connections.push_back(new_conn);
-    int n = sock_fd_write(_phy.getDescriptor(sock), fds[1]);
+    	sock_fd_write(_phy.getDescriptor(sock), fds[1]);
 		close(fds[1]); // close other end of socketpair
 		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
 		// Once the client tells us what its fd is on the other end, we can then complete the mapping
-    new_conn->pending = true;
+    	new_conn->pending = true;
 		return new_conn;
 		return new_conn;
   }
   }
   else {
   else {

+ 1 - 1
netcon/NetconEthernetTap.hpp

@@ -157,7 +157,7 @@ private:
 	std::vector<TcpConnection*> tcp_connections;
 	std::vector<TcpConnection*> tcp_connections;
 	std::vector<PhySocket*> rpc_sockets;
 	std::vector<PhySocket*> rpc_sockets;
 	std::map<PhySocket*, pid_t> pidmap;
 	std::map<PhySocket*, pid_t> pidmap;
-	pid_t rpc_counter = -1;
+	pid_t rpc_counter;
 
 
 	netif interface;
 	netif interface;
 
 

+ 1 - 5
netcon/NetconService.hpp

@@ -42,12 +42,10 @@ using namespace std;
 namespace ZeroTier {
 namespace ZeroTier {
 
 
   class NetconEthernetTap;
   class NetconEthernetTap;
-
-  // prototypes
   class TcpConnection;
   class TcpConnection;
 
 
   /*
   /*
-   *
+   * TCP connection administered by service
    */
    */
   class TcpConnection
   class TcpConnection
   {
   {
@@ -79,8 +77,6 @@ namespace ZeroTier {
     TcpConnection *conn;
     TcpConnection *conn;
     Larg(NetconEthernetTap *_tap, TcpConnection *conn) : tap(_tap), conn(conn) {}
     Larg(NetconEthernetTap *_tap, TcpConnection *conn) : tap(_tap), conn(conn) {}
   };
   };
-
-
 } // namespace ZeroTier
 } // namespace ZeroTier
 
 
 #endif
 #endif

+ 0 - 123
netcon/NetconUtilities.cpp

@@ -40,36 +40,11 @@
 #ifndef _NETCON_UTILITIES_CPP
 #ifndef _NETCON_UTILITIES_CPP
 #define _NETCON_UTILITIES_CPP
 #define _NETCON_UTILITIES_CPP
 
 
-#define DEBUG_LEVEL	4
-
 namespace ZeroTier
 namespace ZeroTier
 {
 {
-	/*
-	void dwr(int level, char *fmt, ... )
-	{
-		if(level > DEBUG_LEVEL)
-			return;
-		va_list ap;
-		va_start(ap, fmt);
-		vfprintf(stderr, fmt, ap);
-		fflush(stderr);
-		va_end(ap);
-	}
-
-	void dwr(char *fmt, ... )
-	{
-		va_list ap;
-		va_start(ap, fmt);
-		vfprintf(stderr, fmt, ap);
-		fflush(stderr);
-		va_end(ap);
-	}
-*/
 	void clearscreen(){
 	void clearscreen(){
 		fprintf(stderr, "\033[2J");
 		fprintf(stderr, "\033[2J");
 	}
 	}
-
-	//void reset_cursor()
 	void gotoxy(int x,int y) {
 	void gotoxy(int x,int y) {
 	    fprintf(stderr, "%c[%d;%df",0x1B,y,x);
 	    fprintf(stderr, "%c[%d;%df",0x1B,y,x);
 	}
 	}
@@ -91,104 +66,6 @@ namespace ZeroTier
 		if (readlink (ppfd, dest, 80) != -1){
 		if (readlink (ppfd, dest, 80) != -1){
 		}
 		}
 	}
 	}
-
-	// Functions used to pass file descriptors between processes
-	ssize_t sock_fd_write(int sock, int fd)
-	{
-		ssize_t size;
-		struct msghdr msg;
-		struct iovec iov;
-		char buf = '\0';
-		int buflen = 1;
-
-		union
-		{
-			  struct cmsghdr  cmsghdr;
-			  char control[CMSG_SPACE(sizeof (int))];
-		} cmsgu;
-		struct cmsghdr *cmsg;
-
-		iov.iov_base = &buf;
-		iov.iov_len = buflen;
-
-		msg.msg_name = NULL;
-		msg.msg_namelen = 0;
-		msg.msg_iov = &iov;
-		msg.msg_iovlen = 1;
-
-		if (fd != -1) {
-			  msg.msg_control = cmsgu.control;
-			  msg.msg_controllen = sizeof(cmsgu.control);
-			  cmsg = CMSG_FIRSTHDR(&msg);
-			  cmsg->cmsg_len = CMSG_LEN(sizeof (int));
-			  cmsg->cmsg_level = SOL_SOCKET;
-			  cmsg->cmsg_type = SCM_RIGHTS;
-			  *((int *) CMSG_DATA(cmsg)) = fd;
-		} else {
-			  msg.msg_control = NULL;
-			  msg.msg_controllen = 0;
-		}
-
-		size = sendmsg(sock, &msg, 0);
-		if (size < 0)
-			  perror ("sendmsg");
-		return size;
-	}
-
-
-	ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
-	{
-	    ssize_t size;
-
-	    if (fd) {
-	        struct msghdr msg;
-	        struct iovec iov;
-	        union
-					{
-	            struct cmsghdr cmsghdr;
-	            char control[CMSG_SPACE(sizeof (int))];
-	        } cmsgu;
-	        struct cmsghdr *cmsg;
-
-	        iov.iov_base = buf;
-	        iov.iov_len = bufsize;
-
-	        msg.msg_name = NULL;
-	        msg.msg_namelen = 0;
-	        msg.msg_iov = &iov;
-	        msg.msg_iovlen = 1;
-	        msg.msg_control = cmsgu.control;
-	        msg.msg_controllen = sizeof(cmsgu.control);
-	        size = recvmsg (sock, &msg, 0);
-	        if (size < 0) {
-	            perror ("recvmsg");
-	            exit(1);
-	        }
-	        cmsg = CMSG_FIRSTHDR(&msg);
-	        if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
-	            if (cmsg->cmsg_level != SOL_SOCKET) {
-	                fprintf (stderr, "invalid cmsg_level %d\n",
-	                     cmsg->cmsg_level);
-	                exit(1);
-	            }
-	            if (cmsg->cmsg_type != SCM_RIGHTS) {
-	                fprintf (stderr, "invalid cmsg_type %d\n",
-	                     cmsg->cmsg_type);
-	                exit(1);
-	            }
-
-	            *fd = *((int *) CMSG_DATA(cmsg));
-	        } else
-	            *fd = -1;
-	    } else {
-	        size = read (sock, buf, bufsize);
-	        if (size < 0) {
-	            perror("read");
-	            exit(1);
-	        }
-	    }
-	    return size;
-	}
 }
 }
 
 
 #endif
 #endif

+ 0 - 3
netcon/NetconUtilities.hpp

@@ -35,8 +35,5 @@ namespace ZeroTier
   void gotoxy(int x,int y);
   void gotoxy(int x,int y);
   void get_path_from_pid(char* dest, int pid);
   void get_path_from_pid(char* dest, int pid);
   void get_path_from_fd(char* dest, int pid, int fd);
   void get_path_from_fd(char* dest, int pid, int fd);
-  ip_addr_t ip_addr_sin(register struct sockaddr_in *sin);
-  ssize_t sock_fd_write(int sock, int fd);
-  ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
 }
 }
 #endif
 #endif

+ 3 - 5
netcon/README.md

@@ -1,11 +1,9 @@
-ZeroTier Network Containers 'service' and 'intercept'
+ZeroTier Network Containers 
 ======
 ======
-ZeroTier Network Containers is a blisteringly-fast and easy-to-use networking integration for Docker containers.
-
 
 
 ### Functional Overview:
 ### Functional Overview:
 
 
-This system exists as a dynamically-linked library, and a stand-alone background service.
+This system exists as a dynamically-linked library, and a service/IP-stack built into ZeroTier
 
 
 The intercept is compiled as a shared library and installed in some user-accessible directory. When you want to intercept
 The intercept is compiled as a shared library and installed in some user-accessible directory. When you want to intercept
 a user application you dynamically link the shared library to the application during runtime. When the application starts, the 
 a user application you dynamically link the shared library to the application during runtime. When the application starts, the 
@@ -51,7 +49,7 @@ To start a service and automatically intercept an application:
 
 
 Alternatively, to intercept a specific application (requires an already running service):
 Alternatively, to intercept a specific application (requires an already running service):
 
 
-    intercept ./my_app
+    zerotier-intercept ./my_app
 
 
 To start the Network Containers service:
 To start the Network Containers service:
 
 

+ 31 - 7
netcon/Sendfd.c

@@ -1,4 +1,31 @@
 
 
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2015  ZeroTier, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
 #include <stdlib.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -17,10 +44,9 @@ ssize_t sock_fd_write(int sock, int fd)
 	char buf = '\0';
 	char buf = '\0';
 	int buflen = 1;
 	int buflen = 1;
 
 
-	union
-	{
-		  struct cmsghdr  cmsghdr;
-		  char control[CMSG_SPACE(sizeof (int))];
+	union {
+        struct cmsghdr  cmsghdr;
+		char control[CMSG_SPACE(sizeof (int))];
 	} cmsgu;
 	} cmsgu;
 	struct cmsghdr *cmsg;
 	struct cmsghdr *cmsg;
 
 
@@ -55,12 +81,10 @@ ssize_t sock_fd_write(int sock, int fd)
 ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
 ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
 {
 {
     ssize_t size;
     ssize_t size;
-
     if (fd) {
     if (fd) {
         struct msghdr msg;
         struct msghdr msg;
         struct iovec iov;
         struct iovec iov;
-        union
-				{
+        union {
             struct cmsghdr cmsghdr;
             struct cmsghdr cmsghdr;
             char control[CMSG_SPACE(sizeof (int))];
             char control[CMSG_SPACE(sizeof (int))];
         } cmsgu;
         } cmsgu;

+ 0 - 3
netcon/Sendfd.h

@@ -1,3 +0,0 @@
-
-ssize_t sock_fd_write(int sock, int fd);
-ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);

+ 28 - 0
netcon/docker-test/README.md

@@ -0,0 +1,28 @@
+To run unit tests:
+
+1) Place a blank network config file in this directory (e.g. "e5cd7a9e1c5311ab.conf")
+ - This will be used to inform test-specific scripts what network to use for testing (create your own, or use the given at your own risk)
+
+2) run build.sh
+ - Builds ZeroTier with Network Containers enabled
+ - Builds LWIP library
+ - Builds library harness
+ - Copies all aformentioned files into unit test directory to be used for building docker files
+
+3) run test.sh
+ - Will (for now, one at a time), execute each unit test's (test.sh)
+
+
+
+A) Each unit test's test.sh will:
+ - temporarily copy all built files into local directory
+ - build test container
+ - build monitor container
+ - remove temporary files
+ - run each container and perform test
+
+B) Results will be written to the 'zerotierone/docker-test/_result' directory
+ - Results will be a combination of raw and formatted dumps to files whose names reflect the test performed
+ - In the event of failure, 'FAIL.' will be appended to the result file's name
+  - (e.g. FAIL.my_application_1.0.2.x86_64)
+ - In the event of success, 'OK.' will be appended

+ 1 - 0
netcon/docker-test/_results/OK.httpd-2.4.16-1.fc23.x86_64.txt

@@ -0,0 +1 @@
+Test: md5 sum ok!

+ 1 - 0
netcon/docker-test/_results/OK.httpd-2.4.17-3.fc23.x86_64.txt

@@ -0,0 +1 @@
+Test: md5 sum ok!

+ 19 - 0
netcon/docker-test/build.sh

@@ -0,0 +1,19 @@
+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
+
+cp ../../zerotier-one zerotier-one
+cp ../../zerotier-cli zerotier-cli
+
+cp ../liblwip.so liblwip.so
+cp ../libzerotierintercept.so.1.0 libzerotierintercept.so.1.0
+cp ../zerotier-intercept zerotier-intercept
+

+ 0 - 0
netcon/docker-test/e5cd7a9e1c5311ab.conf


+ 8 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/README.md

@@ -0,0 +1,8 @@
+Network Containers Test Sequence for: httpd_demo
+
+1) Creates a Netcon docker container with an intercepted instance of httpd
+2) Creates a test monitor container 
+
+3) Test monitor container waits for X seconds for the Netcon container to come online
+4) Test monitor attempts to curl an index.html file
+ - If file is of sufficient size, it will append "OK." to the result file for this test, otherwise "FAIL." is appended

+ 25 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/monitor_dockerfile

@@ -0,0 +1,25 @@
+# ZT Network Containers Test Monitor
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+EXPOSE 9993/udp
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD monitor_identity.public /var/lib/zerotier-one/identity.public
+ADD monitor_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# 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
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]

+ 86 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/monitor_entrypoint.sh

@@ -0,0 +1,86 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+netcon_wait_time=25 # wait for test container to come online
+app_timeout_time=15 # app-specific timeout
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+fail=FAIL. # appended to result file in event of failure
+ok=OK. # appended to result file in event of success
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile # large, random test transfer file
+rx_md5sumfile="$file_path"rx_"$bigfile_name"_md5sum"$tmp_ext"
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test Monitor'
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Starting Test...'
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Sleeping for ('  "$netcon_wait_time"  's ) while we wait for the Network Container to come online...'
+sleep "$netcon_wait_time"s
+ncvirtip=$(<$address_file)
+
+
+# --- Test section ---
+echo '*** Curling from intercepted server at' $ncvirtip
+rm -rf "$file_path"*."$file_base"
+touch "$bigfile_name"
+
+# Perform test
+# curl --connect-timeout "$app_timeout_time" -v -o "$file_path$file_base" http://"$ncvirtip"/index.html
+# Large transfer test
+curl --connect-timeout "$app_timeout_time" -v -o "$bigfile_name" http://"$ncvirtip"/"$bigfile_name"
+
+# Check md5
+md5sum < "$bigfile_name" >> "$rx_md5sumfile"
+rx_md5sum=$(<$rx_md5sumfile)
+tx_md5sum=$(<$tx_md5sumfile)
+
+echo '*** Comparing md5: ' "$rx_md5sum" ' and ' "$tx_md5sum"
+
+if [ $rx_md5sum != $tx_md5sum ]; 
+then
+	echo 'MD5 FAIL'
+	touch "$file_path$fail$test_name.txt"
+	printf 'Test: md5 sum did not match!\n' >> "$file_path$fail$test_name.txt"
+else
+	echo 'MD5 OK'
+	touch "$file_path$ok$test_name.txt"
+	printf 'Test: md5 sum ok!\n' >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+

+ 41 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/netcon_dockerfile

@@ -0,0 +1,41 @@
+# ZT Network Containers Test
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+# Install apps
+RUN yum -y update
+RUN yum -y install httpd-2.4.16-1.fc23.x86_64
+RUN yum clean all
+
+EXPOSE 9993/udp
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so.1.0 /
+RUN cp libzerotierintercept.so.1.0 lib/libzerotierintercept.so.1.0
+RUN cp libzerotierintercept.so.1.0 /lib/libzerotierintercept.so.1.0
+RUN ln -sf /lib/libzerotierintercept.so.1.0 /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD netcon_identity.public /var/lib/zerotier-one/identity.public
+ADD netcon_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_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 ["./netcon_entrypoint.sh"]

+ 53 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/netcon_entrypoint.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile
+bigfile_size=10M # size of file we want to use for the test
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test: ' "$test_name"
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Writing address to ' "$address_file"
+echo $virtip4 > "$address_file"
+
+
+# --- Test section ---
+# Generate large random file for transfer test, share md5sum for monitor container to check
+echo '*** Generating ' "$bigfile_size" ' file'
+dd if=/dev/urandom of=/var/www/html/"$bigfile_name"  bs="$bigfile_size"  count=1
+#md5sum /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+md5sum < /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+echo '*** Starting httpd...'
+sleep 0.5
+rm -rf /run/httpd/* /tmp/httpd*
+zerotier-intercept /usr/sbin/httpd -D FOREGROUND >>/tmp/apache.out 2>&1

+ 40 - 0
netcon/docker-test/httpd/httpd-2.4.16-1.fc23.x86_64/test.sh

@@ -0,0 +1,40 @@
+
+test_name=${PWD##*/}
+echo 'Building dockerfiles for test: ' "$test_name"
+touch "$test_name".name
+
+# Docker won't allow the inclusion of files outside of the build directory
+cp ../../*.conf .
+cp ../../zerotier-one zerotier-one
+cp ../../zerotier-cli zerotier-cli
+cp ../../zerotier-intercept zerotier-intercept
+cp ../../libzerotierintercept.so.1.0 libzerotierintercept.so.1.0
+cp ../../liblwip.so liblwip.so
+cp ../../netcon_identity.public netcon_identity.public
+cp ../../netcon_identity.secret netcon_identity.secret
+cp ../../monitor_identity.public monitor_identity.public
+cp ../../monitor_identity.secret monitor_identity.secret
+
+docker build --tag="$test_name" -f netcon_dockerfile .
+docker build --tag="$test_name"_monitor -f monitor_dockerfile .
+
+rm -f zerotier-one
+rm -f zerotier-cli
+rm -f zerotier-intercept
+rm -f libzerotierintercept.so.1.0
+rm -f liblwip.so
+rm -f netcon_identity.public
+rm -f netcon_identity.secret
+rm -f monitor_identity.public
+rm -f monitor_identity.secret
+rm -f *.conf
+rm -f *.name
+
+# Start netcon container to be tested
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name":latest
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name"_monitor:latest
+
+sleep 45s
+docker kill $(docker ps -a -q)
+
+rm -rf ../../_results/*.tmp

+ 8 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/README.md

@@ -0,0 +1,8 @@
+Network Containers Test Sequence for: httpd_demo
+
+1) Creates a Netcon docker container with an intercepted instance of httpd
+2) Creates a test monitor container 
+
+3) Test monitor container waits for X seconds for the Netcon container to come online
+4) Test monitor attempts to curl an index.html file
+ - If file is of sufficient size, it will append "OK." to the result file for this test, otherwise "FAIL." is appended

+ 25 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_dockerfile

@@ -0,0 +1,25 @@
+# ZT Network Containers Test Monitor
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+EXPOSE 9993/udp
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD monitor_identity.public /var/lib/zerotier-one/identity.public
+ADD monitor_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# 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
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]

+ 86 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_entrypoint.sh

@@ -0,0 +1,86 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+netcon_wait_time=25 # wait for test container to come online
+app_timeout_time=15 # app-specific timeout
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+fail=FAIL. # appended to result file in event of failure
+ok=OK. # appended to result file in event of success
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile # large, random test transfer file
+rx_md5sumfile="$file_path"rx_"$bigfile_name"_md5sum"$tmp_ext"
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test Monitor'
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Starting Test...'
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Sleeping for ('  "$netcon_wait_time"  's ) while we wait for the Network Container to come online...'
+sleep "$netcon_wait_time"s
+ncvirtip=$(<$address_file)
+
+
+# --- Test section ---
+echo '*** Curling from intercepted server at' $ncvirtip
+rm -rf "$file_path"*."$file_base"
+touch "$bigfile_name"
+
+# Perform test
+# curl --connect-timeout "$app_timeout_time" -v -o "$file_path$file_base" http://"$ncvirtip"/index.html
+# Large transfer test
+curl --connect-timeout "$app_timeout_time" -v -o "$bigfile_name" http://"$ncvirtip"/"$bigfile_name"
+
+# Check md5
+md5sum < "$bigfile_name" >> "$rx_md5sumfile"
+rx_md5sum=$(<$rx_md5sumfile)
+tx_md5sum=$(<$tx_md5sumfile)
+
+echo '*** Comparing md5: ' "$rx_md5sum" ' and ' "$tx_md5sum"
+
+if [ $rx_md5sum != $tx_md5sum ]; 
+then
+	echo 'MD5 FAIL'
+	touch "$file_path$fail$test_name.txt"
+	printf 'Test: md5 sum did not match!\n' >> "$file_path$fail$test_name.txt"
+else
+	echo 'MD5 OK'
+	touch "$file_path$ok$test_name.txt"
+	printf 'Test: md5 sum ok!\n' >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+

+ 41 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_dockerfile

@@ -0,0 +1,41 @@
+# ZT Network Containers 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.x86_64
+RUN yum clean all
+
+EXPOSE 9993/udp
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so.1.0 /
+RUN cp libzerotierintercept.so.1.0 lib/libzerotierintercept.so.1.0
+RUN cp libzerotierintercept.so.1.0 /lib/libzerotierintercept.so.1.0
+RUN ln -sf /lib/libzerotierintercept.so.1.0 /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD netcon_identity.public /var/lib/zerotier-one/identity.public
+ADD netcon_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_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 ["./netcon_entrypoint.sh"]

+ 53 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_entrypoint.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile
+bigfile_size=10M # size of file we want to use for the test
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test: ' "$test_name"
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Writing address to ' "$address_file"
+echo $virtip4 > "$address_file"
+
+
+# --- Test section ---
+# Generate large random file for transfer test, share md5sum for monitor container to check
+echo '*** Generating ' "$bigfile_size" ' file'
+dd if=/dev/urandom of=/var/www/html/"$bigfile_name"  bs="$bigfile_size"  count=1
+#md5sum /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+md5sum < /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+echo '*** Starting httpd...'
+sleep 0.5
+rm -rf /run/httpd/* /tmp/httpd*
+zerotier-intercept /usr/sbin/httpd -D FOREGROUND >>/tmp/apache.out 2>&1

+ 40 - 0
netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/test.sh

@@ -0,0 +1,40 @@
+
+test_name=${PWD##*/}
+echo 'Building dockerfiles for test: ' "$test_name"
+touch "$test_name".name
+
+# Docker won't allow the inclusion of files outside of the build directory
+cp ../../*.conf .
+cp ../../zerotier-one zerotier-one
+cp ../../zerotier-cli zerotier-cli
+cp ../../zerotier-intercept zerotier-intercept
+cp ../../libzerotierintercept.so.1.0 libzerotierintercept.so.1.0
+cp ../../liblwip.so liblwip.so
+cp ../../netcon_identity.public netcon_identity.public
+cp ../../netcon_identity.secret netcon_identity.secret
+cp ../../monitor_identity.public monitor_identity.public
+cp ../../monitor_identity.secret monitor_identity.secret
+
+docker build --tag="$test_name" -f netcon_dockerfile .
+docker build --tag="$test_name"_monitor -f monitor_dockerfile .
+
+rm -f zerotier-one
+rm -f zerotier-cli
+rm -f zerotier-intercept
+rm -f libzerotierintercept.so.1.0
+rm -f liblwip.so
+rm -f netcon_identity.public
+rm -f netcon_identity.secret
+rm -f monitor_identity.public
+rm -f monitor_identity.secret
+rm -f *.conf
+rm -f *.name
+
+# Start netcon container to be tested
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name":latest
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name"_monitor:latest
+
+sleep 45s
+docker kill $(docker ps -a -q)
+
+rm -rf ../../_results/*.tmp

+ 8 - 0
netcon/docker-test/httpd/httpd_demo/README.md

@@ -0,0 +1,8 @@
+Network Containers Test Sequence for: httpd_demo
+
+1) Creates a Netcon docker container with an intercepted instance of httpd
+2) Creates a test monitor container 
+
+3) Test monitor container waits for X seconds for the Netcon container to come online
+4) Test monitor attempts to curl an index.html file
+ - If file is of sufficient size, it will append "OK." to the result file for this test, otherwise "FAIL." is appended

BIN
netcon/docker-test/httpd/httpd_demo/htdocs/ZeroTierIcon.png


+ 69 - 0
netcon/docker-test/httpd/httpd_demo/htdocs/index.html

@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<link rel="stylesheet" href="http://bootswatch.com/cosmo/bootstrap.min.css">
+	<title>ZeroTier Network Containers Preview</title>
+</head>
+<body>
+
+<br><br>
+
+<div class="container-fluid">
+	<div class="row">
+		<div class="col-xs-1 col-xs-offset-1"><img src="ZeroTierIcon.png" style="width: 100%; height: 100%;"></div>
+		<div class="col-xs-9">
+			<h1>ZeroTier Network Containers Preview</h1>
+			(a.k.a. super bleeding edge pre-alphe pre-release demo)
+		</div>
+	</div>
+</div>
+
+<br>
+<hr>
+<br>
+
+<div class="container-fluid"><div class="row"><div class="col-xs-10 col-xs-offset-1 lead">
+
+<p><b>This page is being served from a Docker container with its own private TCP/IP microservice.</b></p>
+
+<p>
+It's connected to a virtual network, but if you "docker exec" into it and look around you won't find any special devices. No special privileges or configuration changes on the Docker host were needed. Everything is completely "stock" and completely self-contained.
+</p>
+
+<p>
+There's nothing special about the web server. It's just Apache. There's nothing special about the Linux image. It's based on a regular Fedora Docker base image. Other than Apache, the only thing this image contains is the ZeroTier network containers microservice and dynamic library.
+</p>
+
+<p>
+When Apache is run, our launcher script configures it to load a special dynamic library. This library intercepts calls to the Linux C networking API, redirecting network I/O to our private network stack microservice instead of the standard Linux kernel network path. This microservice takes care of the rest, automatically encapsulating traffic and sending it over the virtual network instead of the physical.
+</p>
+
+<p>
+It's a bit like how networking would work on a microkernel: modular, composable, portable, and independent.
+</p>
+
+<p>
+Network Containers allows a Docker (or LXC, CoreOS/rkt, runc, OpenVZ, SmartOS/Triton, <a target="_blank" href="https://github.com/p8952/bocker">bocker</a>, or even just bare metal Linux) system to connect to virtual networks without requiring <u>any</u> special permissions or special configuration on the host node. Processes inside the container don't even need to run with root permissions. It's 100% user-space, making it ideal for multi-tenant deployments or any other situation where modifying the configuration of the host node is impossible or just inconvenient.
+</p>
+
+<p>
+Once properly tuned and optimized, Network Containers also has the potential to be much faster than tun/tap or pcap based network overlays. It imposes only a single context switch from application/service to virtual network microservice as opposed to at least four for tun/tap and pcap-based solutions, since the latter require two trips through the kernel network stack. We believe it may be possible to approach or even equal the performance of VXLAN/IPSec or other fully kernel-mode configurations, but with the ease and total independence of a fully container-based solution.
+</p>
+
+<p>
+We created this container image to show you a preview of one of the projects we've been working on at ZeroTier. We still have a good deal of packaging, testing, and performance optimization work to do before Network Containers will be ready for a real public beta release. Follow the <a href="https://www.zerotier.com/blog">blog</a> or <a href="https://twitter.com/zerotier">@zerotier</a> for updates and announcements.
+</p>
+
+<p>
+P.S. If you want to use ZeroTier in Docker today, you can do it with the same ZeroTier One endpoint service you're using to access this network. The only catch is that you have to launch your containers with "--device=/dev/net/tun --cap-add=NET_ADMIN". Network Containers eliminates the need for these special options.
+</p>
+
+</div></div></div>
+
+<hr>
+
+</body>
+</html>

+ 25 - 0
netcon/docker-test/httpd/httpd_demo/monitor_dockerfile

@@ -0,0 +1,25 @@
+# ZT Network Containers Test Monitor
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+EXPOSE 9993/udp
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD monitor_identity.public /var/lib/zerotier-one/identity.public
+ADD monitor_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# 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
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]

+ 86 - 0
netcon/docker-test/httpd/httpd_demo/monitor_entrypoint.sh

@@ -0,0 +1,86 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+netcon_wait_time=25 # wait for test container to come online
+app_timeout_time=15 # app-specific timeout
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+fail=FAIL. # appended to result file in event of failure
+ok=OK. # appended to result file in event of success
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile # large, random test transfer file
+rx_md5sumfile="$file_path"rx_"$bigfile_name"_md5sum"$tmp_ext"
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test Monitor'
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Starting Test...'
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Sleeping for ('  "$netcon_wait_time"  's ) while we wait for the Network Container to come online...'
+sleep "$netcon_wait_time"s
+ncvirtip=$(<$address_file)
+
+
+# --- Test section ---
+echo '*** Curling from intercepted server at' $ncvirtip
+rm -rf "$file_path"*."$file_base"
+touch "$bigfile_name"
+
+# Perform test
+# curl --connect-timeout "$app_timeout_time" -v -o "$file_path$file_base" http://"$ncvirtip"/index.html
+# Large transfer test
+curl --connect-timeout "$app_timeout_time" -v -o "$bigfile_name" http://"$ncvirtip"/"$bigfile_name"
+
+# Check md5
+md5sum < "$bigfile_name" >> "$rx_md5sumfile"
+rx_md5sum=$(<$rx_md5sumfile)
+tx_md5sum=$(<$tx_md5sumfile)
+
+echo '*** Comparing md5: ' "$rx_md5sum" ' and ' "$tx_md5sum"
+
+if [ $rx_md5sum != $tx_md5sum ]; 
+then
+	echo 'MD5 FAIL'
+	touch "$file_path$fail$test_name.txt"
+	printf 'Test: md5 sum did not match!\n' >> "$file_path$fail$test_name.txt"
+else
+	echo 'MD5 OK'
+	touch "$file_path$ok$test_name.txt"
+	printf 'Test: md5 sum ok!\n' >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+

+ 47 - 0
netcon/docker-test/httpd/httpd_demo/netcon_dockerfile

@@ -0,0 +1,47 @@
+# ZT Network Containers 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.x86_64
+RUN yum clean all
+
+EXPOSE 9993/udp
+
+#include Apache
+ADD htdocs/index.html /
+ADD htdocs/ZeroTierIcon.png /
+RUN mv index.html /var/www/html/index.html
+RUN mv ZeroTierIcon.png /var/www/html/ZeroTierIcon.png
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so.1.0 /
+RUN cp libzerotierintercept.so.1.0 lib/libzerotierintercept.so.1.0
+RUN cp libzerotierintercept.so.1.0 /lib/libzerotierintercept.so.1.0
+RUN ln -sf /lib/libzerotierintercept.so.1.0 /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+# Add ZT files
+RUN mkdir -p /var/lib/zerotier-one/networks.d
+ADD netcon_identity.public /var/lib/zerotier-one/identity.public
+ADD netcon_identity.secret /var/lib/zerotier-one/identity.secret
+ADD *.conf /var/lib/zerotier-one/networks.d/
+ADD *.conf /
+ADD *.name /
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_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 ["./netcon_entrypoint.sh"]

+ 53 - 0
netcon/docker-test/httpd/httpd_demo/netcon_entrypoint.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/
+
+
+# --- Test Parameters ---
+test_namefile=$(ls *.name)
+test_name="${test_namefile%.*}" # test network id
+nwconf=$(ls *.conf) # blank test network config file
+nwid="${nwconf%.*}" # test network id
+file_path=/opt/results/ # test result output file path (fs shared between host and containers)
+file_base="$test_name".txt # test result output file
+tmp_ext=.tmp # temporary filetype used for sharing test data between containers
+address_file="$file_path$test_name"_addr"$tmp_ext" # file shared between host and containers for sharing address (optional)
+bigfile_name=bigfile
+bigfile_size=10M # size of file we want to use for the test
+tx_md5sumfile="$file_path"tx_"$bigfile_name"_md5sum"$tmp_ext"
+
+
+# --- Network Config ---
+echo '*** ZeroTier Network Containers Test: ' "$test_name"
+chown -R daemon /var/lib/zerotier-one
+chgrp -R daemon /var/lib/zerotier-one
+su daemon -s /bin/bash -c '/zerotier-one -d -U -p9993 >>/tmp/zerotier-one.out 2>&1'
+echo '*** Waiting for initial identity generation...'
+while [ ! -s /var/lib/zerotier-one/identity.secret ]; do
+	sleep 0.2
+done
+echo '*** Waiting for network config...'
+virtip4=""
+while [ ! -s /var/lib/zerotier-one/networks.d/"$nwconf" ]; do
+	sleep 0.2
+done
+while [ -z "$virtip4" ]; do
+	sleep 0.2
+	virtip4=`/zerotier-cli listnetworks | grep -F $nwid | cut -d ' ' -f 9 | sed 's/,/\n/g' | grep -F '.' | cut -d / -f 1`
+done
+echo '*** Up and running at' $virtip4 ' on network: ' $nwid
+echo '*** Writing address to ' "$address_file"
+echo $virtip4 > "$address_file"
+
+
+# --- Test section ---
+# Generate large random file for transfer test, share md5sum for monitor container to check
+echo '*** Generating ' "$bigfile_size" ' file'
+dd if=/dev/urandom of=/var/www/html/"$bigfile_name"  bs="$bigfile_size"  count=1
+#md5sum /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+md5sum < /var/www/html/"$bigfile_name" >> "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+echo '*** Starting httpd...'
+sleep 0.5
+rm -rf /run/httpd/* /tmp/httpd*
+zerotier-intercept /usr/sbin/httpd -D FOREGROUND >>/tmp/apache.out 2>&1

+ 40 - 0
netcon/docker-test/httpd/httpd_demo/test.sh

@@ -0,0 +1,40 @@
+
+test_name=${PWD##*/}
+echo 'Building dockerfiles for test: ' "$test_name"
+touch "$test_name".name
+
+# Docker won't allow the inclusion of files outside of the build directory
+cp ../../*.conf .
+cp ../../zerotier-one zerotier-one
+cp ../../zerotier-cli zerotier-cli
+cp ../../zerotier-intercept zerotier-intercept
+cp ../../libzerotierintercept.so.1.0 libzerotierintercept.so.1.0
+cp ../../liblwip.so liblwip.so
+cp ../../netcon_identity.public netcon_identity.public
+cp ../../netcon_identity.secret netcon_identity.secret
+cp ../../monitor_identity.public monitor_identity.public
+cp ../../monitor_identity.secret monitor_identity.secret
+
+docker build --tag="$test_name" -f netcon_dockerfile .
+docker build --tag="$test_name"_monitor -f monitor_dockerfile .
+
+rm -f zerotier-one
+rm -f zerotier-cli
+rm -f zerotier-intercept
+rm -f libzerotierintercept.so.1.0
+rm -f liblwip.so
+rm -f netcon_identity.public
+rm -f netcon_identity.secret
+rm -f monitor_identity.public
+rm -f monitor_identity.secret
+rm -f *.conf
+rm -f *.name
+
+# Start netcon container to be tested
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name":latest
+docker run -d -it -v $PWD/../../_results:/opt/results --device=/dev/net/tun "$test_name"_monitor:latest
+
+sleep 45s
+docker kill $(docker ps -a -q)
+
+rm -rf ../../_results/*.tmp

+ 1 - 0
netcon/docker-test/monitor_identity.public

@@ -0,0 +1 @@
+e5b0e7dc2a:0:f257ee08ad335ef87caf30598a5a17a758f193da58085b7b471c9cc48413585cba5e7830c23508907a2f991308a7ddc01912023cc454a7de80cdad68edebcc63

+ 1 - 0
netcon/docker-test/monitor_identity.secret

@@ -0,0 +1 @@
+e5b0e7dc2a:0:f257ee08ad335ef87caf30598a5a17a758f193da58085b7b471c9cc48413585cba5e7830c23508907a2f991308a7ddc01912023cc454a7de80cdad68edebcc63:21e5f68984b729acdaedd6c4c057d0a5447cefa66ec5de8d10982f77efc148e65ce954ee17604716398a91ab74563b0b25263f84b45cecd97fa1bc35d1ef2bd7

+ 1 - 0
netcon/docker-test/netcon_identity.public

@@ -0,0 +1 @@
+ba2488cd53:0:a8bd3d0febd1da023b11382f45df6d246be9407ac62dc32c0c60aa2b96d3df15aa303a0eb28297916f7bcdbcd73a960f404a202f336cd35103d837bce1fb896f

+ 1 - 0
netcon/docker-test/netcon_identity.secret

@@ -0,0 +1 @@
+ba2488cd53:0:a8bd3d0febd1da023b11382f45df6d246be9407ac62dc32c0c60aa2b96d3df15aa303a0eb28297916f7bcdbcd73a960f404a202f336cd35103d837bce1fb896f:07d0caef50f3c94897035a954cdc73dc391f77a267caa54d52d4841edbec24388d601d27522d415a943764f9c91b7870754c08b4e04780b29c7c69edade2f638

+ 20 - 0
netcon/docker-test/test.sh

@@ -0,0 +1,20 @@
+./build.sh
+
+cd httpd
+
+# httpd
+cd httpd-2.4.16-1.fc23.x86_64/
+pwd
+./test.sh
+cd ..
+
+cd httpd-2.4.17-3.fc23.x86_64/
+pwd
+./test.sh
+cd ..
+
+
+# nginx
+
+
+cd ..

+ 7 - 7
netcon/intercept → netcon/docker-test/zerotier-intercept

@@ -11,14 +11,14 @@ case "$1" in
 	on)
 	on)
 		if [ -z "$LD_PRELOAD" ]
 		if [ -z "$LD_PRELOAD" ]
 			then
 			then
-				export LD_PRELOAD="/lib/libintercept.so.1.0"
+				export LD_PRELOAD="/lib/libzerotierintercept.so.1.0"
 			else
 			else
-				echo $LD_PRELOAD | grep -q "/lib/libintercept\.so.1.0" || \
-				export LD_PRELOAD="/lib/libintercept.so $LD_PRELOAD"
+				echo $LD_PRELOAD | grep -q "/lib/libzerotierintercept\.so.1.0" || \
+				export LD_PRELOAD="/lib/libzerotierintercept.so $LD_PRELOAD"
 		fi
 		fi
 	;;
 	;;
 	off)
 	off)
-		export LD_PRELOAD=`echo -n $LD_PRELOAD | sed 's/\/lib\/libintercept.so.1.0 \?//'`
+		export LD_PRELOAD=`echo -n $LD_PRELOAD | sed 's/\/lib\/libzerotierintercept.so.1.0 \?//'`
 		if [ -z "$LD_PRELOAD" ]
 		if [ -z "$LD_PRELOAD" ]
 			then
 			then
 				unset LD_PRELOAD
 				unset LD_PRELOAD
@@ -33,10 +33,10 @@ case "$1" in
 	*)
 	*)
 		if [ -z "$LD_PRELOAD" ]
 		if [ -z "$LD_PRELOAD" ]
 		then
 		then
-			export LD_PRELOAD="/lib/libintercept.so.1.0"
+			export LD_PRELOAD="/lib/libzerotierintercept.so.1.0"
 		else
 		else
-			echo $LD_PRELOAD | grep -q "/lib/libintercept\.so.1.0" || \
-			export LD_PRELOAD="/lib/libintercept.so.1.0 $LD_PRELOAD"
+			echo $LD_PRELOAD | grep -q "/lib/libzerotierintercept\.so.1.0" || \
+			export LD_PRELOAD="/lib/libzerotierintercept.so.1.0 $LD_PRELOAD"
 		fi
 		fi
 
 
 		if [ $# = 0 ]
 		if [ $# = 0 ]

BIN
netcon/libintercept.so.1.0


BIN
netcon/liblwip.so


+ 10 - 10
netcon/make-intercept.mk

@@ -27,28 +27,28 @@
 
 
 SHCC=gcc
 SHCC=gcc
 
 
-intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -DERRORS_ARE_FATAL -DVERBOSE -DDEBUG_RPC -DCHECKS -D_GNU_SOURCE -DNETCON_INTERCEPT
-LIB_NAME = intercept
+intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -DVERBOSE -DDEBUG_RPC -DCHECKS -D_GNU_SOURCE -DNETCON_INTERCEPT
+#LIB_NAME = intercept
 SHLIB_EXT=dylib
 SHLIB_EXT=dylib
 SHLIB_MAJOR = 1
 SHLIB_MAJOR = 1
 SHLIB_MINOR = 8
 SHLIB_MINOR = 8
 COMMON = Common
 COMMON = Common
 OBJS= Intercept.o
 OBJS= Intercept.o
-SHLIB = ${LIB_NAME}.${SHLIB_EXT}.${SHLIB_MAJOR}.${SHLIB_MINOR}
+#SHLIB = ${LIB_NAME}.${SHLIB_EXT}.${SHLIB_MAJOR}.${SHLIB_MINOR}
 SHLDFLAGS = -g -O2 -Wall -I. -nostdlib -shared
 SHLDFLAGS = -g -O2 -Wall -I. -nostdlib -shared
 LIBS = -ldl -lc -lrt -lpthread
 LIBS = -ldl -lc -lrt -lpthread
 
 
 lib:
 lib:
 	${SHCC} $(intercept_CFLAGS) -I. Intercept.c -o Intercept.o
 	${SHCC} $(intercept_CFLAGS) -I. Intercept.c -o Intercept.o
 	${SHCC} $(intercept_CFLAGS) -I. Sendfd.c -o Sendfd.o
 	${SHCC} $(intercept_CFLAGS) -I. Sendfd.c -o Sendfd.o
-	${SHCC} $(SHLDFLAGS) Intercept.o Sendfd.o -o libintercept.so.1.0 $(LIBS)
+	${SHCC} $(SHLDFLAGS) Intercept.o Sendfd.o -o libzerotierintercept.so.1.0 $(LIBS)
 
 
 install:
 install:
-	cp libintercept.so.1.0 /lib/libintercept.so.1.0
-	ln -sf /lib/libintercept.so.1.0 /lib/libintercept
-	/usr/bin/install -c intercept /usr/bin
+	cp libzerotierintercept.so.1.0 /lib/libzerotierintercept.so.1.0
+	ln -sf /lib/libzerotierintercept.so.1.0 /lib/libzerotierintercept
+	/usr/bin/install -c zerotier-intercept /usr/bin
 
 
 uninstall:
 uninstall:
-	rm -r /lib/libintercept.so.1.0
-	rm -r /lib/libintercept
-	rm -r /usr/bin/intercept
+	rm -r /lib/libzerotierintercept.so.1.0
+	rm -r /lib/libzerotierintercept
+	rm -r /usr/bin/zerotier-intercept

BIN
netcon/zerotier-cli


+ 54 - 0
netcon/zerotier-intercept

@@ -0,0 +1,54 @@
+#!/bin/sh
+# usage:
+# /usr/bin/intercept program <args>
+
+if [ $# = 0 ] ; then
+   echo "$0: insufficient arguments"
+   exit
+fi
+
+case "$1" in
+	on)
+		if [ -z "$LD_PRELOAD" ]
+			then
+				export LD_PRELOAD="/lib/libzerotierintercept.so.1.0"
+			else
+				echo $LD_PRELOAD | grep -q "/lib/libzerotierintercept\.so.1.0" || \
+				export LD_PRELOAD="/lib/libzerotierintercept.so $LD_PRELOAD"
+		fi
+	;;
+	off)
+		export LD_PRELOAD=`echo -n $LD_PRELOAD | sed 's/\/lib\/libzerotierintercept.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/libzerotierintercept.so.1.0"
+		else
+			echo $LD_PRELOAD | grep -q "/lib/libzerotierintercept\.so.1.0" || \
+			export LD_PRELOAD="/lib/libzerotierintercept.so.1.0 $LD_PRELOAD"
+		fi
+
+		if [ $# = 0 ]
+		then
+			${SHELL:-/bin/sh}
+		fi
+
+		if [ $# -gt 0 ]
+		then
+			exec "$@"
+		fi
+	;;
+esac
+
+#EOF

BIN
netcon/zerotier-one