summaryrefslogtreecommitdiff
path: root/netcon
diff options
context:
space:
mode:
Diffstat (limited to 'netcon')
-rw-r--r--netcon/Intercept.c44
-rw-r--r--netcon/Intercept.h24
-rw-r--r--netcon/LWIPStack.hpp6
-rw-r--r--netcon/README.md26
-rw-r--r--netcon/RPC.c16
-rwxr-xr-xnetcon/docker-test/build_tests.sh2
-rw-r--r--netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_dockerfile (renamed from netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_dockerfile)0
-rw-r--r--netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_entrypoint.sh (renamed from netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_entrypoint.sh)0
-rw-r--r--netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_dockerfile (renamed from netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_dockerfile)2
-rw-r--r--netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_entrypoint.sh46
-rw-r--r--netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_dockerfile24
-rw-r--r--netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_entrypoint.sh80
-rw-r--r--netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_dockerfile38
-rw-r--r--netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_entrypoint.sh (renamed from netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_entrypoint.sh)0
-rw-r--r--netcon/docker-test/python/python/monitor_dockerfile24
-rw-r--r--netcon/docker-test/python/python/monitor_entrypoint.sh80
-rw-r--r--netcon/docker-test/python/python/netcon_dockerfile38
-rw-r--r--netcon/docker-test/python/python/netcon_entrypoint.sh46
-rw-r--r--netcon/docker-test/python/python3/monitor_dockerfile24
-rw-r--r--netcon/docker-test/python/python3/monitor_entrypoint.sh80
-rw-r--r--netcon/docker-test/python/python3/netcon_dockerfile37
-rw-r--r--netcon/docker-test/python/python3/netcon_entrypoint.sh46
22 files changed, 659 insertions, 24 deletions
diff --git a/netcon/Intercept.c b/netcon/Intercept.c
index 9c4feedf..48276c96 100644
--- a/netcon/Intercept.c
+++ b/netcon/Intercept.c
@@ -38,20 +38,25 @@
#include <sys/time.h>
#include <pwd.h>
#include <errno.h>
-#include <linux/errno.h>
#include <stdarg.h>
#include <netdb.h>
#include <string.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/resource.h>
-#include <linux/net.h> /* for NPROTO */
-#define SOCK_MAX (SOCK_PACKET + 1)
+#if defined(__linux__)
+ #include <linux/errno.h>
+ #include <sys/syscall.h>
+ #include <linux/net.h> /* for NPROTO */
+#endif
+
+#if defined(__linux__)
+ #define SOCK_MAX (SOCK_PACKET + 1)
+#endif
#define SOCK_TYPE_MASK 0xf
#include "Intercept.h"
@@ -92,6 +97,11 @@ static int connected_to_service(int sockfd)
static int set_up_intercept()
{
if (!realconnect) {
+
+#if defined(__linux__)
+ realaccept4 = dlsym(RTLD_NEXT, "accept4");
+ realsyscall = dlsym(RTLD_NEXT, "syscall");
+#endif
realconnect = dlsym(RTLD_NEXT, "connect");
realbind = dlsym(RTLD_NEXT, "bind");
realaccept = dlsym(RTLD_NEXT, "accept");
@@ -100,9 +110,7 @@ static int set_up_intercept()
realbind = dlsym(RTLD_NEXT, "bind");
realsetsockopt = dlsym(RTLD_NEXT, "setsockopt");
realgetsockopt = dlsym(RTLD_NEXT, "getsockopt");
- realaccept4 = dlsym(RTLD_NEXT, "accept4");
realclose = dlsym(RTLD_NEXT, "close");
- realsyscall = dlsym(RTLD_NEXT, "syscall");
realgetsockname = dlsym(RTLD_NEXT, "getsockname");
}
if (!netpath) {
@@ -127,10 +135,12 @@ int setsockopt(SETSOCKOPT_SIG)
return realsetsockopt(socket, level, option_name, option_value, option_len);
dwr(MSG_DEBUG,"setsockopt(%d)\n", socket);
+#if defined(__linux__)
if(level == SOL_IPV6 && option_name == IPV6_V6ONLY)
return 0;
if(level == SOL_IP && (option_name == IP_TTL || option_name == IP_TOS))
return 0;
+#endif
if(level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE))
return 0;
if(realsetsockopt(socket, level, option_name, option_value, option_len) < 0)
@@ -169,13 +179,16 @@ int socket(SOCKET_SIG)
dwr(MSG_DEBUG,"socket():\n");
/* Check that type makes sense */
+#if defined(__linux__)
int flags = socket_type & ~SOCK_TYPE_MASK;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) {
errno = EINVAL;
return -1;
}
+#endif
socket_type &= SOCK_TYPE_MASK;
/* Check protocol is in range */
+#if defined(__linux__)
if (socket_family < 0 || socket_family >= NPROTO){
errno = EAFNOSUPPORT;
return -1;
@@ -184,9 +197,12 @@ int socket(SOCKET_SIG)
errno = EINVAL;
return -1;
}
+#endif
/* TODO: detect ENFILE condition */
if(socket_family == AF_LOCAL
+#if defined(__linux__)
|| socket_family == AF_NETLINK
+#endif
|| socket_family == AF_UNIX) {
int err = realsocket(socket_family, socket_type, protocol);
dwr(MSG_DEBUG,"realsocket() = %d\n", err);
@@ -244,24 +260,30 @@ int connect(CONNECT_SIG)
errno = ENOTSOCK;
return -1;
}
+#if defined(__linux__)
/* Check family */
if (connaddr->sin_family < 0 || connaddr->sin_family >= NPROTO){
errno = EAFNOSUPPORT;
return -1;
}
+#endif
/* make sure we don't touch any standard outputs */
if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO)
return(realconnect(__fd, __addr, __len));
if(__addr != NULL && (connaddr->sin_family == AF_LOCAL
+#if defined(__linux__)
|| connaddr->sin_family == PF_NETLINK
|| connaddr->sin_family == AF_NETLINK
+#endif
|| connaddr->sin_family == AF_UNIX)) {
return realconnect(__fd, __addr, __len);
}
/* Assemble and send RPC */
struct connect_st rpc_st;
+#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid);
+#endif
rpc_st.__fd = __fd;
memcpy(&rpc_st.__addr, __addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.__len, &__len, sizeof(socklen_t));
@@ -300,7 +322,9 @@ int bind(BIND_SIG)
connaddr = (struct sockaddr_in *)addr;
if(connaddr->sin_family == AF_LOCAL
+#if defined(__linux__)
|| connaddr->sin_family == AF_NETLINK
+#endif
|| connaddr->sin_family == AF_UNIX) {
int err = realbind(sockfd, addr, addrlen);
dwr(MSG_DEBUG,"realbind, err = %d\n", err);
@@ -317,7 +341,9 @@ int bind(BIND_SIG)
/* Assemble and send RPC */
struct bind_st rpc_st;
rpc_st.sockfd = sockfd;
+#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid);
+#endif
memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
return rpc_send_command(netpath, RPC_BIND, sockfd, &rpc_st, sizeof(struct bind_st));
@@ -328,6 +354,7 @@ int bind(BIND_SIG)
------------------------------------------------------------------------------*/
/* int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags */
+#if defined(__linux__)
int accept4(ACCEPT4_SIG)
{
dwr(MSG_DEBUG,"accept4(%d):\n", sockfd);
@@ -337,6 +364,7 @@ int accept4(ACCEPT4_SIG)
fcntl(sockfd, F_SETFL, O_NONBLOCK);
return accept(sockfd, addr, addrlen);
}
+#endif
/*------------------------------------------------------------------------------
----------------------------------- accept() -----------------------------------
@@ -442,7 +470,9 @@ int listen(LISTEN_SIG)
struct listen_st rpc_st;
rpc_st.sockfd = sockfd;
rpc_st.backlog = backlog;
+#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid);
+#endif
return rpc_send_command(netpath, RPC_LISTEN, sockfd, &rpc_st, sizeof(struct listen_st));
}
@@ -502,6 +532,7 @@ int getsockname(GETSOCKNAME_SIG)
------------------------------------ syscall() ---------------------------------
------------------------------------------------------------------------------*/
+#if defined(__linux__)
long syscall(SYSCALL_SIG)
{
va_list ap;
@@ -542,3 +573,4 @@ long syscall(SYSCALL_SIG)
#endif
return realsyscall(number,a,b,c,d,e,f);
}
+#endif \ No newline at end of file
diff --git a/netcon/Intercept.h b/netcon/Intercept.h
index b399993b..9593468f 100644
--- a/netcon/Intercept.h
+++ b/netcon/Intercept.h
@@ -25,12 +25,17 @@
* LLC. Start here: http://www.zerotier.com/
*/
-
#ifndef _INTERCEPT_H
#define _INTERCEPT_H 1
#include <sys/socket.h>
+
+#if defined(__linux__)
+ #define ACCEPT4_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags
+ #define SYSCALL_SIG long number, ...
+#endif
+
#define CLOSE_SIG int fd
#define READ_SIG int __fd, void *__buf, size_t __nbytes
#define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
@@ -38,7 +43,6 @@
#define WRITE_SIG int __fd, const void *__buf, size_t __n
#define LISTEN_SIG int sockfd, int backlog
#define SOCKET_SIG int socket_family, int socket_type, int protocol
-#define ACCEPT4_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags
#define ACCEPT_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen
#define SHUTDOWN_SIG int socket, int how
#define CONNECT_SOCKARG struct sockaddr *
@@ -47,12 +51,17 @@
#define DAEMON_SIG int nochdir, int noclose
#define SETSOCKOPT_SIG int socket, int level, int option_name, const void *option_value, socklen_t option_len
#define GETSOCKOPT_SIG int sockfd, int level, int optname, void *optval, socklen_t *optlen
-#define SYSCALL_SIG long number, ...
#define CLONE_SIG int (*fn)(void *), void *child_stack, int flags, void *arg, ...
#define GETSOCKNAME_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen
#define DUP2_SIG int oldfd, int newfd
#define DUP3_SIG int oldfd, int newfd, int flags
+
+#if defined(__linux__)
+ int accept4(ACCEPT4_SIG);
+ long syscall(SYSCALL_SIG);
+#endif
+
void my_init(void);
int connect(CONNECT_SIG);
int bind(BIND_SIG);
@@ -61,14 +70,17 @@ int listen(LISTEN_SIG);
int socket(SOCKET_SIG);
int setsockopt(SETSOCKOPT_SIG);
int getsockopt(GETSOCKOPT_SIG);
-int accept4(ACCEPT4_SIG);
-long syscall(SYSCALL_SIG);
int close(CLOSE_SIG);
int clone(CLONE_SIG);
int dup2(DUP2_SIG);
int dup3(DUP3_SIG);
int getsockname(GETSOCKNAME_SIG);
+#if defined(__linux__)
+ static int (*realaccept4)(ACCEPT4_SIG) = 0;
+ static long (*realsyscall)(SYSCALL_SIG) = 0;
+#endif
+
static int (*realconnect)(CONNECT_SIG) = 0;
static int (*realbind)(BIND_SIG) = 0;
static int (*realaccept)(ACCEPT_SIG) = 0;
@@ -76,8 +88,6 @@ static int (*reallisten)(LISTEN_SIG) = 0;
static int (*realsocket)(SOCKET_SIG) = 0;
static int (*realsetsockopt)(SETSOCKOPT_SIG) = 0;
static int (*realgetsockopt)(GETSOCKOPT_SIG) = 0;
-static int (*realaccept4)(ACCEPT4_SIG) = 0;
-static long (*realsyscall)(SYSCALL_SIG) = 0;
static int (*realclose)(CLOSE_SIG) = 0;
static int (*realgetsockname)(GETSOCKNAME_SIG) = 0;
diff --git a/netcon/LWIPStack.hpp b/netcon/LWIPStack.hpp
index fedbdd5f..2ad1a843 100644
--- a/netcon/LWIPStack.hpp
+++ b/netcon/LWIPStack.hpp
@@ -132,7 +132,13 @@ public:
LWIPStack(const char* path) :
_libref(NULL)
{
+
+#if defined(__linux__)
_libref = dlmopen(LM_ID_NEWLM, path, RTLD_NOW);
+#elif defined(__APPLE__)
+ _libref = dlopen(path, RTLD_NOW);
+#endif
+
if(_libref == NULL)
printf("dlerror(): %s\n", dlerror());
diff --git a/netcon/README.md b/netcon/README.md
index 413efc2b..12d48c1d 100644
--- a/netcon/README.md
+++ b/netcon/README.md
@@ -70,6 +70,22 @@ The intercept library does nothing unless the *ZT\_NC\_NETWORK* environment vari
Unlike *zerotier-one*, *zerotier-netcon-service* does not need to be run with root privileges and will not modify the host's network configuration in any way. It can be run alongside *zerotier-one* on the same host with no ill effect, though this can be confusing since you'll have to remember the difference between "real" host interfaces (tun/tap) and network containerized endpoints. The latter are completely unknown to the kernel and will not show up in *ifconfig*.
+# Linking into an application on Mac OSX
+
+Example:
+
+ gcc myapp.c -o myapp libzerotierintercept.so
+ export ZT_NC_NETWORK=/tmp/netcon-test-home/nc_8056c2e21c000001
+
+Start service
+
+ ./zerotier-netcon-service -d -p8000 /tmp/netcon-test-home
+
+Run application
+
+ ./myapp
+
+
# Starting the Network Containers Service
You don't need Docker or any other container engine to try Network Containers. A simple test can be performed in user space (no root) in your own home directory.
@@ -154,9 +170,11 @@ Results will be written to the *netcon/docker-test/_results/* directory which is
To run unit tests:
-1) Set up your own network at [https://my.zerotier.com/](https://my.zerotier.com/). For our example we'll just use the Earth network (8056c2e21c000001). Use its network id as follows:
+1) Disable SELinux. This is so the containers can use a shared volume to exchange MD5 sums and address information.
+
+2) Set up your own network at [https://my.zerotier.com/](https://my.zerotier.com/). For our example we'll just use the Earth network (8056c2e21c000001). Use its network id as follows:
-2) Generate two pairs of identity keys. Each public/private pair will be used by the *netcon* and *monitor* containers:
+3) Generate two pairs of identity keys. Each public/private pair will be used by the *netcon* and *monitor* containers:
mkdir -p /tmp/netcon_first
cp -f ./netcon/liblwip.so /tmp/netcon_first
@@ -176,7 +194,7 @@ To run unit tests:
./zerotier-cli -D/tmp/netcon_second join 8056c2e21c000001
kill `cat /tmp/netcon_second/zerotier-one.pid`
-3) Copy the identity files to your *docker-test* directory. Names will be altered during copy step so the dockerfiles know which identities to use for each image/container:
+4) Copy the identity files to your *docker-test* directory. Names will be altered during copy step so the dockerfiles know which identities to use for each image/container:
cp /tmp/netcon_first/identity.public ./netcon/docker-test/netcon_identity.public
cp /tmp/netcon_first/identity.secret ./netcon/docker-test/netcon_identity.secret
@@ -185,7 +203,7 @@ To run unit tests:
cp /tmp/netcon_second/identity.secret ./netcon/docker-test/monitor_identity.secret
-4) Place a blank network config file in the *netcon/docker-test* directory (e.g. "8056c2e21c000001.conf")
+5) Place a blank network config file in the *netcon/docker-test* directory (e.g. "8056c2e21c000001.conf")
- This will be used to inform test-specific scripts what network to use for testing
After you've created your network and placed its blank config file in *netcon/docker-test* run the following to perform unit tests for httpd:
diff --git a/netcon/RPC.c b/netcon/RPC.c
index a6965892..7d5c11e0 100644
--- a/netcon/RPC.c
+++ b/netcon/RPC.c
@@ -3,7 +3,10 @@
#include <sys/un.h>
#include <pthread.h>
#include <errno.h>
+
+#if defined(__linux__)
#include <sys/syscall.h>
+#endif
#include <fcntl.h>
#include <dlfcn.h>
@@ -70,12 +73,12 @@ int get_retval(int rpc_sock)
int load_symbols_rpc()
{
- #ifdef NETCON_INTERCEPT
+#ifdef NETCON_INTERCEPT
realsocket = dlsym(RTLD_NEXT, "socket");
realconnect = dlsym(RTLD_NEXT, "connect");
if(!realconnect || !realsocket)
return -1;
- #endif
+#endif
return 1;
}
@@ -131,19 +134,22 @@ int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
memcpy(&cmdbuf[CANARY_IDX], &canary_num, CANARY_SZ);
memcpy(&cmdbuf[STRUCT_IDX], data, len);
-#ifdef VERBOSE
+#if defined(VERBOSE)
+ rpc_count++;
memset(metabuf, 0, BUF_SZ);
+#if defined(__linux__)
pid_t pid = syscall(SYS_getpid);
pid_t tid = syscall(SYS_gettid);
- rpc_count++;
+#endif
char timestring[20];
time_t timestamp;
timestamp = time(NULL);
strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(&timestamp));
memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase
-
+#if defined(__linux__)
memcpy(&metabuf[IDX_PID], &pid, sizeof(pid_t) ); /* pid */
memcpy(&metabuf[IDX_TID], &tid, sizeof(pid_t) ); /* tid */
+#endif
memcpy(&metabuf[IDX_COUNT], &rpc_count, sizeof(rpc_count) ); /* rpc_count */
memcpy(&metabuf[IDX_TIME], &timestring, 20 ); /* timestamp */
#endif
diff --git a/netcon/docker-test/build_tests.sh b/netcon/docker-test/build_tests.sh
index f360124b..65009f18 100755
--- a/netcon/docker-test/build_tests.sh
+++ b/netcon/docker-test/build_tests.sh
@@ -18,7 +18,7 @@ find . -mindepth 2 -maxdepth 2 -type d | while read testdir; do
continue
fi
- echo "*** Building: '$testdir'..."
+ echo "\n\n\n*** Building: '$testdir'..."
rm _results/*.tmp
# Stage scripts
diff --git a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_dockerfile b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_dockerfile
index d2d2a0cb..d2d2a0cb 100644
--- a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_dockerfile
+++ b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_dockerfile
diff --git a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_entrypoint.sh b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_entrypoint.sh
index c8fca5a3..c8fca5a3 100644
--- a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/monitor_entrypoint.sh
+++ b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/monitor_entrypoint.sh
diff --git a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_dockerfile b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_dockerfile
index 90739f10..66a39d88 100644
--- a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_dockerfile
+++ b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_dockerfile
@@ -4,7 +4,7 @@ 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 -y install darkhttpd-1.11
RUN yum clean all
EXPOSE 9993/udp 80/udp
diff --git a/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_entrypoint.sh b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_entrypoint.sh
new file mode 100644
index 00000000..978696a8
--- /dev/null
+++ b/netcon/docker-test/darkhttpd/darkhttpd-1.11.x86_64/netcon_entrypoint.sh
@@ -0,0 +1,46 @@
+#!/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-netcon-service -d -U -p9993 >>/tmp/zerotier-netcon-service.out 2>&1'
+virtip4=""
+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`
+ dev=`/zerotier-cli listnetworks | grep -F "" | cut -d ' ' -f 8 | cut -d "_" -f 2 | sed "s/^<dev>//" | tr '\n' '\0'`
+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="$bigfile_name" bs="$bigfile_size" count=1
+md5sum < "$bigfile_name" > "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+
+echo '*** Starting application...'
+sleep 0.5
+
+export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
+export LD_PRELOAD=./libzerotierintercept.so
+darkhttpd /
diff --git a/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_dockerfile b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_dockerfile
new file mode 100644
index 00000000..d2d2a0cb
--- /dev/null
+++ b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_dockerfile
@@ -0,0 +1,24 @@
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Start ZeroTier-One
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]
diff --git a/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_entrypoint.sh b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_entrypoint.sh
new file mode 100644
index 00000000..c8fca5a3
--- /dev/null
+++ b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/monitor_entrypoint.sh
@@ -0,0 +1,80 @@
+#!/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=35 # wait for test container to come online
+app_timeout_time=25 # 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'
+virtip4=""
+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"
+ cat "$rx_md5sumfile" >> "$file_path$ok$test_name.txt"
+ cat "$tx_md5sumfile" >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_dockerfile b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_dockerfile
new file mode 100644
index 00000000..3053a832
--- /dev/null
+++ b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_dockerfile
@@ -0,0 +1,38 @@
+# 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.18-1.fc23.x86_64
+RUN yum clean all
+
+EXPOSE 9993/udp 80/udp
+
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so /
+RUN cp libzerotierintercept.so lib/libzerotierintercept.so
+RUN ln -sf /lib/libzerotierintercept.so /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+ADD zerotier-cli /
+ADD zerotier-netcon-service /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_entrypoint.sh
+
+# Start ZeroTier-One
+CMD ["./netcon_entrypoint.sh"]
diff --git a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_entrypoint.sh b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_entrypoint.sh
index d2ab248a..d2ab248a 100644
--- a/netcon/docker-test/httpd/httpd-2.4.17-3.fc23.x86_64/netcon_entrypoint.sh
+++ b/netcon/docker-test/httpd/httpd-2.4.18-1.fc23.x86_64/netcon_entrypoint.sh
diff --git a/netcon/docker-test/python/python/monitor_dockerfile b/netcon/docker-test/python/python/monitor_dockerfile
new file mode 100644
index 00000000..d2d2a0cb
--- /dev/null
+++ b/netcon/docker-test/python/python/monitor_dockerfile
@@ -0,0 +1,24 @@
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Start ZeroTier-One
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]
diff --git a/netcon/docker-test/python/python/monitor_entrypoint.sh b/netcon/docker-test/python/python/monitor_entrypoint.sh
new file mode 100644
index 00000000..c8fca5a3
--- /dev/null
+++ b/netcon/docker-test/python/python/monitor_entrypoint.sh
@@ -0,0 +1,80 @@
+#!/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=35 # wait for test container to come online
+app_timeout_time=25 # 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'
+virtip4=""
+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"
+ cat "$rx_md5sumfile" >> "$file_path$ok$test_name.txt"
+ cat "$tx_md5sumfile" >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netcon/docker-test/python/python/netcon_dockerfile b/netcon/docker-test/python/python/netcon_dockerfile
new file mode 100644
index 00000000..6646f670
--- /dev/null
+++ b/netcon/docker-test/python/python/netcon_dockerfile
@@ -0,0 +1,38 @@
+# ZT Network Containers Test
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+# Install apps
+RUN yum -y update
+RUN yum -y install python
+RUN yum clean all
+
+EXPOSE 9993/udp 80/udp
+
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so /
+RUN cp libzerotierintercept.so lib/libzerotierintercept.so
+RUN ln -sf /lib/libzerotierintercept.so /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+ADD zerotier-cli /
+ADD zerotier-netcon-service /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_entrypoint.sh
+
+# Start ZeroTier-One
+CMD ["./netcon_entrypoint.sh"]
diff --git a/netcon/docker-test/python/python/netcon_entrypoint.sh b/netcon/docker-test/python/python/netcon_entrypoint.sh
new file mode 100644
index 00000000..5e1a19b8
--- /dev/null
+++ b/netcon/docker-test/python/python/netcon_entrypoint.sh
@@ -0,0 +1,46 @@
+#!/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-netcon-service -d -U -p9993 >>/tmp/zerotier-netcon-service.out 2>&1'
+virtip4=""
+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`
+ dev=`/zerotier-cli listnetworks | grep -F "" | cut -d ' ' -f 8 | cut -d "_" -f 2 | sed "s/^<dev>//" | tr '\n' '\0'`
+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="$bigfile_name" bs="$bigfile_size" count=1
+md5sum < "$bigfile_name" > "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+
+echo '*** Starting application...'
+sleep 0.5
+
+export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
+export LD_PRELOAD=./libzerotierintercept.so
+python -m SimpleHTTPServer 80
diff --git a/netcon/docker-test/python/python3/monitor_dockerfile b/netcon/docker-test/python/python3/monitor_dockerfile
new file mode 100644
index 00000000..d2d2a0cb
--- /dev/null
+++ b/netcon/docker-test/python/python3/monitor_dockerfile
@@ -0,0 +1,24 @@
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+ADD zerotier-one /
+ADD zerotier-cli /
+
+# Start ZeroTier-One
+ADD monitor_entrypoint.sh /monitor_entrypoint.sh
+RUN chmod -v +x /monitor_entrypoint.sh
+CMD ["./monitor_entrypoint.sh"]
diff --git a/netcon/docker-test/python/python3/monitor_entrypoint.sh b/netcon/docker-test/python/python3/monitor_entrypoint.sh
new file mode 100644
index 00000000..c8fca5a3
--- /dev/null
+++ b/netcon/docker-test/python/python3/monitor_entrypoint.sh
@@ -0,0 +1,80 @@
+#!/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=35 # wait for test container to come online
+app_timeout_time=25 # 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'
+virtip4=""
+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"
+ cat "$rx_md5sumfile" >> "$file_path$ok$test_name.txt"
+ cat "$tx_md5sumfile" >> "$file_path$ok$test_name.txt"
+fi
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netcon/docker-test/python/python3/netcon_dockerfile b/netcon/docker-test/python/python3/netcon_dockerfile
new file mode 100644
index 00000000..f960fa30
--- /dev/null
+++ b/netcon/docker-test/python/python3/netcon_dockerfile
@@ -0,0 +1,37 @@
+# ZT Network Containers Test
+FROM fedora:23
+MAINTAINER https://www.zerotier.com/
+
+# Install apps
+RUN yum -y update
+RUN yum clean all
+
+EXPOSE 9993/udp 80/udp
+
+# 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 /
+
+# Install LWIP library used by service
+ADD liblwip.so /var/lib/zerotier-one/liblwip.so
+
+# Install syscall intercept library
+ADD zerotier-intercept /
+ADD libzerotierintercept.so /
+RUN cp libzerotierintercept.so lib/libzerotierintercept.so
+RUN ln -sf /lib/libzerotierintercept.so /lib/libzerotierintercept
+RUN /usr/bin/install -c zerotier-intercept /usr/bin
+
+ADD zerotier-cli /
+ADD zerotier-netcon-service /
+
+# Install test scripts
+ADD netcon_entrypoint.sh /netcon_entrypoint.sh
+RUN chmod -v +x /netcon_entrypoint.sh
+
+# Start ZeroTier-One
+CMD ["./netcon_entrypoint.sh"]
diff --git a/netcon/docker-test/python/python3/netcon_entrypoint.sh b/netcon/docker-test/python/python3/netcon_entrypoint.sh
new file mode 100644
index 00000000..c3c8b281
--- /dev/null
+++ b/netcon/docker-test/python/python3/netcon_entrypoint.sh
@@ -0,0 +1,46 @@
+#!/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-netcon-service -d -U -p9993 >>/tmp/zerotier-netcon-service.out 2>&1'
+virtip4=""
+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`
+ dev=`/zerotier-cli listnetworks | grep -F "" | cut -d ' ' -f 8 | cut -d "_" -f 2 | sed "s/^<dev>//" | tr '\n' '\0'`
+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="$bigfile_name" bs="$bigfile_size" count=1
+md5sum < "$bigfile_name" > "$tx_md5sumfile"
+echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
+
+echo '*** Starting application...'
+sleep 0.5
+
+export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
+export LD_PRELOAD=./libzerotierintercept.so
+python3 -m http.server 80