Tightening of RPC code

This commit is contained in:
Joseph Henry 2015-12-21 05:03:26 -08:00
parent 608e059b18
commit c488fa8461
18 changed files with 512 additions and 622 deletions

7
httpserver.js Normal file
View File

@ -0,0 +1,7 @@
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("welcome to the machine!\n");
});
server.listen(8080);
console.log("Server running!");

View File

@ -95,18 +95,24 @@ one: $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o
ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-idtool
ln -sf zerotier-one zerotier-cli ln -sf zerotier-one zerotier-cli
netcon: $(OBJS) netcon: rpc_lib $(OBJS)
rm -f *.o rm -f *.o
# Need to selectively rebuild one.cpp and OneService.cpp with ZT_SERVICE_NETCON and ZT_ONE_NO_ROOT_CHECK defined, and also NetconEthernetTap # Need to selectively rebuild one.cpp and OneService.cpp with ZT_SERVICE_NETCON and ZT_ONE_NO_ROOT_CHECK defined, and also NetconEthernetTap
$(CXX) $(CXXFLAGS) $(LDFLAGS) -DZT_SERVICE_NETCON -DZT_ONE_NO_ROOT_CHECK -Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6 -o zerotier-netcon-service $(OBJS) service/OneService.cpp netcon/NetconEthernetTap.cpp one.cpp $(LDLIBS) -ldl $(CXX) $(CXXFLAGS) $(LDFLAGS) -DZT_SERVICE_NETCON -DZT_ONE_NO_ROOT_CHECK -Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6 -o zerotier-netcon-service $(OBJS) service/OneService.cpp netcon/NetconEthernetTap.cpp one.cpp $(LDLIBS) -ldl -Lnetcon/ -lrpc
# Build netcon/liblwip.so which must be placed in ZT home for zerotier-netcon-service to work # Build netcon/liblwip.so which must be placed in ZT home for zerotier-netcon-service to work
cd netcon ; make -f make-liblwip.mk cd netcon ; make -f make-liblwip.mk
# Use gcc not clang to build standalone intercept library since gcc is typically used for libc and we want to ensure maximal ABI compatibility # Use gcc not clang to build standalone intercept library since gcc is typically used for libc and we want to ensure maximal ABI compatibility
cd netcon ; gcc -g -O2 -Wall -std=c99 -fPIC -DVERBOSE -DDEBUG_RPC -DCHECKS -D_GNU_SOURCE -DNETCON_INTERCEPT -I. -nostdlib -shared -o libzerotierintercept.so Intercept.c -ldl cd netcon ; gcc -Wl,--whole-archive -g -O2 -Wall -std=c99 -fPIC -DVERBOSE -D_GNU_SOURCE -DNETCON_INTERCEPT -I. -nostdlib -shared librpc.a -o libzerotierintercept.so Intercept.c -ldl
cp netcon/libzerotierintercept.so libzerotierintercept.so cp netcon/libzerotierintercept.so libzerotierintercept.so
ln -sf zerotier-netcon-service zerotier-cli ln -sf zerotier-netcon-service zerotier-cli
ln -sf zerotier-netcon-service zerotier-idtool ln -sf zerotier-netcon-service zerotier-idtool
rpc_lib:
g++ -c -fPIC -lpthread netcon/rpc.c -DVERBOSE -o netcon/rpc.o
ar -rv netcon/librpc.a netcon/rpc.o
selftest: $(OBJS) selftest.o selftest: $(OBJS) selftest.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LDLIBS) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LDLIBS)
$(STRIP) zerotier-selftest $(STRIP) zerotier-selftest
@ -115,7 +121,7 @@ installer: one FORCE
./ext/installfiles/linux/buildinstaller.sh ./ext/installfiles/linux/buildinstaller.sh
clean: FORCE clean: FORCE
rm -rf *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest zerotier-netcon-service build-* ZeroTierOneInstaller-* *.deb *.rpm rm -rf *.so *.o netcon/*.a node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest zerotier-netcon-service build-* ZeroTierOneInstaller-* *.deb *.rpm
# Remove files from all the funny places we put them for tests # Remove files from all the funny places we put them for tests
find netcon -type f \( -name '*.o' -o -name '*.so' -o -name '*.1.0' -o -name 'zerotier-one' -o -name 'zerotier-cli' -o -name 'zerotier-netcon-service' \) -delete find netcon -type f \( -name '*.o' -o -name '*.so' -o -name '*.1.0' -o -name 'zerotier-one' -o -name 'zerotier-cli' -o -name 'zerotier-netcon-service' \) -delete
find netcon/docker-test -name "zerotier-intercept" -type f -delete find netcon/docker-test -name "zerotier-intercept" -type f -delete

View File

@ -48,18 +48,16 @@
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/un.h> #include <sys/un.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/resource.h>
#include <linux/net.h> /* for NPROTO */
#define SOCK_MAX (SOCK_PACKET + 1)
#define SOCK_TYPE_MASK 0xf
#include "Intercept.h" #include "Intercept.h"
#include "rpc.h"
#include "common.inc.c" #include "common.inc.c"
#ifdef CHECKS
#include <sys/resource.h>
#include <linux/net.h> /* for NPROTO */
#define SOCK_MAX (SOCK_PACKET + 1)
#define SOCK_TYPE_MASK 0xf
#endif
/* Global Declarations */ /* Global Declarations */
static int (*realconnect)(CONNECT_SIG); static int (*realconnect)(CONNECT_SIG);
static int (*realbind)(BIND_SIG); static int (*realbind)(BIND_SIG);
@ -97,222 +95,59 @@ static int init_service_connection();
static void load_symbols(void); static void load_symbols(void);
static void set_up_intercept(); static void set_up_intercept();
#define SERVICE_CONNECT_ATTEMPTS 30
#define RPC_FD 1023
static pthread_mutex_t lock;
static ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
void handle_error(char *name, char *info, int err)
{
#ifdef ERRORS_ARE_FATAL
if(err < 0) {
dwr(MSG_DEBUG,"handle_error(%s)=%d: FATAL: %s\n", name, err, info);
exit(-1);
}
#endif
#ifdef VERBOSE
dwr(MSG_DEBUG,"%s()=%d\n", name, err);
#endif
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
------------------- Intercept<--->Service Comm mechanisms----------------------- ------------------- Intercept<--->Service Comm mechanisms ----------------------
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
static int is_initialized = 0; static int rpcfd = -1; /* used for fd-transfers */
static int fdret_sock; /* used for fd-transfers */
static int newfd; /* used for "this_end" socket */
static int thispid = -1; static int thispid = -1;
static int instance_count = 0; static int instance_count = 0;
/* static int connected_to_service() {
* Check for forking return rpcfd == -1 ? 0 : 1;
*/
static void checkpid()
{
/* Do noting if not configured (sanity check -- should never get here in this case) */
if (!getenv("ZT_NC_NETWORK"))
return;
if (thispid != getpid()) {
dwr(MSG_DEBUG, "checkpid(): clone/fork detected. Re-initializing this instance.\n");
set_up_intercept();
fdret_sock = init_service_connection();
thispid = getpid();
}
} }
/*
* Reads a return value from the service and sets errno (if applicable)
*/
static int get_retval()
{
dwr(MSG_DEBUG,"get_retval()\n");
if(fdret_sock >= 0) {
int retval;
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
char retbuf[BUF_SZ];
memset(&retbuf, '\0', sz);
int n_read = read(fdret_sock, &retbuf, sz);
if(n_read > 0) {
memcpy(&retval, &retbuf[1], sizeof(retval));
memcpy(&errno, &retbuf[1+sizeof(retval)], sizeof(errno));
dwr(MSG_DEBUG, "get_retval(): ret = %d\n", retval);
return retval;
}
}
dwr(MSG_DEBUG,"unable to read return value\n");
return -1;
}
/* Reads a new file descriptor from the service */
static int get_new_fd(int oversock)
{
char buf[BUF_SZ];
int newfd;
ssize_t size = sock_fd_read(oversock, buf, sizeof(buf), &newfd);
if(size > 0){
dwr(MSG_DEBUG, "get_new_fd(): RX: fd = (%d) over (%d)\n", newfd, oversock);
return newfd;
}
dwr(MSG_ERROR, "get_new_fd(): ERROR: unable to read fd over (%d)\n", oversock);
return -1;
}
#ifdef VERBOSE
static unsigned long rpc_count = 0;
#endif
/* Sends an RPC command to the service */
static int send_cmd(int rpc_fd, char *cmd)
{
pthread_mutex_lock(&lock);
char metabuf[BUF_SZ]; // portion of buffer which contains RPC metadata for debugging
#ifdef VERBOSE
/*
#define IDX_PID 0
#define IDX_TID sizeof(pid_t)
#define IDX_COUNT IDX_TID + sizeof(pid_t)
#define IDX_TIME IDX_COUNT + sizeof(int)
#define IDX_CMD IDX_TIME + 20 // 20 being the length of the timestamp string
#define IDX_PAYLOAD IDX_TIME + sizeof(char)
*/
/* [pid_t] [pid_t] [rpc_count] [int] [...] */
memset(metabuf, '\0', BUF_SZ);
pid_t pid = syscall(SYS_getpid);
pid_t tid = syscall(SYS_gettid);
rpc_count++;
char timestring[20];
time_t timestamp;
timestamp = time(NULL);
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 */
#endif
/* Combine command flag+payload with RPC metadata */
memcpy(&metabuf[IDX_PAYLOAD], cmd, PAYLOAD_SZ);
int n_write = write(rpc_fd, &metabuf, BUF_SZ);
if(n_write < 0){
dwr(MSG_DEBUG,"Error writing command to service (CMD = %d)\n", cmd[0]);
errno = 0;
}
int ret = ERR_OK;
if(n_write > 0) {
if(cmd[0]==RPC_SOCKET) {
ret = get_new_fd(fdret_sock);
}
if(cmd[0]==RPC_MAP_REQ
|| cmd[0]==RPC_CONNECT
|| cmd[0]==RPC_BIND
|| cmd[0]==RPC_LISTEN
|| cmd[0]==RPC_MAP) {
ret = get_retval();
}
if(cmd[0]==RPC_GETSOCKNAME) {
ret = n_write;
}
}
else {
ret = -1;
}
pthread_mutex_unlock(&lock);
return ret;
}
/* Check whether the socket is mapped to the service or not. We /* Check whether the socket is mapped to the service or not. We
need to know if this is a regular AF_LOCAL socket or an end of a socketpair need to know if this is a regular AF_LOCAL socket or an end of a socketpair
that the service uses. We don't want to keep state in the intercept, so that the service uses. We don't want to keep state in the intercept, so
we simply ask the service via an RPC */ we simply ask the service via an RPC */
static int is_mapped_to_service(int sockfd) static int is_mapped_to_service(int sockfd)
{ {
if(rpcfd < 0)
return 0; /* no connection obviously implies no mapping */
dwr(MSG_DEBUG,"is_mapped_to_service()\n"); dwr(MSG_DEBUG,"is_mapped_to_service()\n");
char cmd[BUF_SZ]; return rpc_send_command(RPC_MAP_REQ, rpcfd, &sockfd, sizeof(sockfd));
memset(cmd, '\0', BUF_SZ);
cmd[0] = RPC_MAP_REQ;
memcpy(&cmd[1], &sockfd, sizeof(sockfd));
return send_cmd(fdret_sock, cmd);
} }
/*------------------------------------------------------------------------------
---------- Unix-domain socket lazy initializer (for fd-transfers)--------------
------------------------------------------------------------------------------*/
/* Sets up the connection pipes and sockets to the service */ /* Sets up the connection pipes and sockets to the service */
static int init_service_connection() static int init_service_connection()
{ {
struct sockaddr_un addr;
int tfd = -1, attempts = 0, conn_err = -1;
const char *network_id; const char *network_id;
char af_sock_name[1024]; char rpcname[1024];
network_id = getenv("ZT_NC_NETWORK"); network_id = getenv("ZT_NC_NETWORK");
if (!network_id) /* Do noting if not configured (sanity check -- should never get here in this case) */
return -1; if (!network_id){
strncpy(af_sock_name,network_id,sizeof(af_sock_name)); fprintf(stderr, "init_service_connection(): ZT_NC_NETWORK not set.\n");
exit(0);
}
if((rpcfd < 0 && instance_count==0) || thispid != getpid())
rpc_mutex_init();
strncpy(rpcname,network_id,sizeof(rpcname));
instance_count++; instance_count++;
rpcfd = rpc_join(rpcname);
dwr(MSG_DEBUG,"init_service_connection()\n"); fprintf(stderr, "rpc_join = %d\n", rpcfd);
return rpcfd;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, af_sock_name, sizeof(addr.sun_path)-1);
if((tfd = realsocket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return -1;
while(conn_err < 0 && attempts < SERVICE_CONNECT_ATTEMPTS) {
conn_err = realconnect(tfd, (struct sockaddr*)&addr, sizeof(addr));
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;
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
------------------------ ctors and dtors (and friends)------------------------- ------------------------ ctors and dtors (and friends) ------------------------
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
static void my_dest(void) __attribute__ ((destructor)); static void my_dest(void) __attribute__ ((destructor));
static void my_dest(void) { static void my_dest(void) {
dwr(MSG_DEBUG,"closing connections to service...\n"); dwr(MSG_DEBUG,"closing connections to service...\n");
pthread_mutex_destroy(&lock); rpc_mutex_destroy();
} }
static void load_symbols(void) static void load_symbols(void)
@ -350,12 +185,6 @@ static void set_up_intercept()
return; return;
/* Hook/intercept Posix net API symbols */ /* Hook/intercept Posix net API symbols */
load_symbols(); load_symbols();
if(pthread_mutex_init(&lock, NULL) != 0) {
dwr(MSG_ERROR, "error while initializing service call mutex\n");
}
if(pthread_mutex_init(&loglock, NULL) != 0) {
dwr(MSG_ERROR, "error while initializing log mutex mutex\n");
}
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -370,11 +199,7 @@ int setsockopt(SETSOCKOPT_SIG)
return -1; return -1;
} }
dwr(MSG_DEBUG,"setsockopt(%d)\n", socket); dwr(MSG_DEBUG,"setsockopt(%d)\n", socket);
/*
if(is_mapped_to_service(socket) < 0) { // First, check if the service manages this
return realsetsockopt(socket, level, option_name, option_value, option_len);
}
*/
/* 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;
@ -408,24 +233,16 @@ int getsockopt(GETSOCKOPT_SIG)
if(is_mapped_to_service(sockfd) <= 0) { // First, check if the service manages this if(is_mapped_to_service(sockfd) <= 0) { // First, check if the service manages this
return realgetsockopt(sockfd, level, optname, optval, optlen); return realgetsockopt(sockfd, level, optname, optval, optlen);
} }
//return 0;
//int err = realgetsockopt(sockfd, level, optname, optval, optlen); //int err = realgetsockopt(sockfd, level, optname, optval, optlen);
/* TODO: this condition will need a little more intelligence later on /* 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 */ -- 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;
*val = 2; *val = 2;
optval = (void*)val; optval = (void*)val;
} }
/*
if(err < 0){
perror("getsockopt():\n");
}
*/
return 0; return 0;
} }
@ -438,30 +255,25 @@ int getsockopt(GETSOCKOPT_SIG)
socket() intercept function */ socket() intercept function */
int socket(SOCKET_SIG) int socket(SOCKET_SIG)
{ {
if(realsocket == NULL){ if(realsocket == NULL)
dwr(MSG_ERROR, "socket(): SYMBOL NOT FOUND.\n"); set_up_intercept();
return -1;
}
dwr(MSG_DEBUG,"socket():\n"); dwr(MSG_DEBUG,"socket():\n");
int err; int newfd = -1;
#ifdef CHECKS
/* Check that type makes sense */ /* Check that type makes sense */
int flags = socket_type & ~SOCK_TYPE_MASK; int flags = socket_type & ~SOCK_TYPE_MASK;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) {
errno = EINVAL; errno = EINVAL;
handle_error("socket", "", -1);
return -1; return -1;
} }
socket_type &= SOCK_TYPE_MASK; socket_type &= SOCK_TYPE_MASK;
/* Check protocol is in range */ /* Check protocol is in range */
if (socket_family < 0 || socket_family >= NPROTO){ if (socket_family < 0 || socket_family >= NPROTO){
errno = EAFNOSUPPORT; errno = EAFNOSUPPORT;
handle_error("socket", "", -1);
return -1; return -1;
} }
if (socket_type < 0 || socket_type >= SOCK_MAX) { if (socket_type < 0 || socket_type >= SOCK_MAX) {
errno = EINVAL; errno = EINVAL;
handle_error("socket", "", -1);
return -1; return -1;
} }
/* Check that we haven't hit the soft-limit file descriptors allowed */ /* Check that we haven't hit the soft-limit file descriptors allowed */
@ -474,59 +286,43 @@ int socket(SOCKET_SIG)
} }
*/ */
/* TODO: detect ENFILE condition */ /* TODO: detect ENFILE condition */
#endif
char cmd[BUF_SZ];
fdret_sock = !is_initialized ? init_service_connection() : fdret_sock;
if(fdret_sock < 0) {
dwr(MSG_DEBUG,"BAD service connection. exiting.\n");
handle_error("socket", "", -1);
exit(-1);
}
if(socket_family == AF_LOCAL if(socket_family == AF_LOCAL
|| socket_family == AF_NETLINK || socket_family == AF_NETLINK
|| socket_family == AF_UNIX) { || socket_family == AF_UNIX) {
int err = realsocket(socket_family, socket_type, protocol); int err = realsocket(socket_family, socket_type, protocol);
dwr(MSG_DEBUG,"realsocket, err = %d\n", err); dwr(MSG_DEBUG,"realsocket() = %d\n", err);
handle_error("socket", "", err);
return err; return err;
} }
rpcfd = !connected_to_service() ? init_service_connection() : rpcfd;
if(rpcfd < 0) {
dwr(MSG_DEBUG,"BAD service connection. exiting.\n");
exit(-1);
}
/* Assemble and send RPC */ /* Assemble and send RPC */
struct socket_st rpc_st; struct socket_st rpc_st;
rpc_st.socket_family = socket_family; rpc_st.socket_family = socket_family;
rpc_st.socket_type = socket_type; rpc_st.socket_type = socket_type;
rpc_st.protocol = protocol; rpc_st.protocol = protocol;
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
memset(cmd, '\0', BUF_SZ);
cmd[0] = RPC_SOCKET;
memcpy(&cmd[1], &rpc_st, sizeof(struct socket_st));
/* send command and get new fd */ newfd = rpc_send_command(RPC_SOCKET, rpcfd, &rpc_st, sizeof(struct socket_st));
newfd = send_cmd(fdret_sock, cmd);
if(newfd > 0) if(newfd > 0)
{ {
dwr(MSG_DEBUG,"sending fd = %d to Service over (%d)\n", newfd, fdret_sock); dwr(MSG_DEBUG,"sending fd = %d to Service over (%d)\n", newfd, rpcfd);
/* send our local-fd number back to service so /* send our local-fd number back to service so
it can complete its mapping table entry */ it can complete its mapping table entry */
memset(cmd, '\0', BUF_SZ);
cmd[0] = RPC_MAP;
memcpy(&cmd[1], &newfd, sizeof(newfd));
/* send fd mapping and get confirmation */ /* send fd mapping and get confirmation */
err = send_cmd(fdret_sock, cmd); if(rpc_send_command(RPC_MAP, rpcfd, &newfd, sizeof(newfd)) > -1) {
if(err > -1) {
errno = ERR_OK; errno = ERR_OK;
dwr(MSG_DEBUG, "RXd fd confirmation. Mapped!\n"); dwr(MSG_DEBUG, "RXd fd confirmation. Mapped!\n");
return newfd; /* Mapping complete, everything is OK */ return newfd; /* Mapping complete, everything is OK */
} }
else{
dwr(MSG_DEBUG,"Error, service sent bad fd.\n");
return err; /* Mapping failed */
} }
}
else {
dwr(MSG_DEBUG,"Error while receiving new fd.\n"); dwr(MSG_DEBUG,"Error while receiving new fd.\n");
return newfd; return -1;
}
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -546,11 +342,9 @@ int connect(CONNECT_SIG)
struct sockaddr_in *connaddr; struct sockaddr_in *connaddr;
connaddr = (struct sockaddr_in *) __addr; connaddr = (struct sockaddr_in *) __addr;
#ifdef CHECKS
/* Check that this is a valid fd */ /* Check that this is a valid fd */
if(fcntl(__fd, F_GETFD) < 0) { if(fcntl(__fd, F_GETFD) < 0) {
errno = EBADF; errno = EBADF;
handle_error("connect", "EBADF", -1);
return -1; return -1;
} }
/* Check that it is a socket */ /* Check that it is a socket */
@ -558,26 +352,18 @@ int connect(CONNECT_SIG)
socklen_t sock_type_len = sizeof(sock_type); socklen_t sock_type_len = sizeof(sock_type);
if(getsockopt(__fd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) { if(getsockopt(__fd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
errno = ENOTSOCK; errno = ENOTSOCK;
handle_error("connect", "ENOTSOCK", -1);
return -1; return -1;
} }
/* Check family */ /* Check family */
if (connaddr->sin_family < 0 || connaddr->sin_family >= NPROTO){ if (connaddr->sin_family < 0 || connaddr->sin_family >= NPROTO){
errno = EAFNOSUPPORT; errno = EAFNOSUPPORT;
handle_error("connect", "EAFNOSUPPORT", -1);
return -1; return -1;
} }
/* FIXME: Check that address is in user space, return EFAULT ? */ /* FIXME: Check that address is in user space, return EFAULT ? */
#endif
/* make sure we don't touch any standard outputs */ /* make sure we don't touch any standard outputs */
if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO){ if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO)
if (realconnect == NULL) {
handle_error("connect", "Unresolved symbol [connect]", -1);
exit(-1);
}
return(realconnect(__fd, __addr, __len)); return(realconnect(__fd, __addr, __len));
}
if(__addr != NULL && (connaddr->sin_family == AF_LOCAL if(__addr != NULL && (connaddr->sin_family == AF_LOCAL
|| connaddr->sin_family == PF_NETLINK || connaddr->sin_family == PF_NETLINK
@ -585,21 +371,17 @@ 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); */
return err; return err;
} }
/* Assemble and send RPC */ /* Assemble and send RPC */
char cmd[BUF_SZ];
memset(cmd, '\0', BUF_SZ);
struct connect_st rpc_st; struct connect_st rpc_st;
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
rpc_st.__fd = __fd; rpc_st.__fd = __fd;
memcpy(&rpc_st.__addr, __addr, sizeof(struct sockaddr_storage)); memcpy(&rpc_st.__addr, __addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.__len, &__len, sizeof(socklen_t)); memcpy(&rpc_st.__len, &__len, sizeof(socklen_t));
cmd[0] = RPC_CONNECT;
memcpy(&cmd[1], &rpc_st, sizeof(struct connect_st)); return rpc_send_command(RPC_CONNECT, rpcfd, &rpc_st, sizeof(struct connect_st));
return send_cmd(fdret_sock, cmd);
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -615,12 +397,9 @@ int bind(BIND_SIG)
return -1; return -1;
} }
dwr(MSG_DEBUG,"bind(%d):\n", sockfd); dwr(MSG_DEBUG,"bind(%d):\n", sockfd);
/* print_addr(addr); */
#ifdef CHECKS
/* Check that this is a valid fd */ /* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) { if(fcntl(sockfd, F_GETFD) < 0) {
errno = EBADF; errno = EBADF;
handle_error("bind", "EBADF", -1);
return -1; return -1;
} }
/* Check that it is a socket */ /* Check that it is a socket */
@ -628,10 +407,8 @@ int bind(BIND_SIG)
socklen_t opt_len; socklen_t opt_len;
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) { if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) {
errno = ENOTSOCK; errno = ENOTSOCK;
handle_error("bind", "ENOTSOCK", -1);
return -1; return -1;
} }
#endif
/* make sure we don't touch any standard outputs */ /* make sure we don't touch any standard outputs */
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO) if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
@ -658,17 +435,14 @@ int bind(BIND_SIG)
d[3] = (ip >> 24) & 0xFF; d[3] = (ip >> 24) & 0xFF;
dwr(MSG_DEBUG, "bind(): %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], ntohs(port)); dwr(MSG_DEBUG, "bind(): %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], ntohs(port));
/* Assemble and send RPC */ /* Assemble and send RPC */
char cmd[BUF_SZ];
struct bind_st rpc_st; struct bind_st rpc_st;
rpc_st.sockfd = sockfd; rpc_st.sockfd = sockfd;
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage)); memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t)); memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
cmd[0]=RPC_BIND;
memcpy(&cmd[1], &rpc_st, sizeof(struct bind_st)); return rpc_send_command(RPC_BIND, rpcfd, &rpc_st, sizeof(struct bind_st));
return send_cmd(fdret_sock, cmd);
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -689,7 +463,6 @@ int accept4(ACCEPT4_SIG)
if ((flags & SOCK_NONBLOCK)) if ((flags & SOCK_NONBLOCK))
fcntl(sockfd, F_SETFL, O_NONBLOCK); fcntl(sockfd, F_SETFL, O_NONBLOCK);
int newfd = accept(sockfd, addr, addrlen); int newfd = accept(sockfd, addr, addrlen);
handle_error("accept4", "", newfd);
return newfd; return newfd;
} }
@ -706,13 +479,11 @@ int accept(ACCEPT_SIG)
return -1; return -1;
} }
dwr(MSG_DEBUG,"accept(%d):\n", sockfd); dwr(MSG_DEBUG,"accept(%d):\n", sockfd);
#ifdef CHECKS
/* Check that this is a valid fd */ /* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) { if(fcntl(sockfd, F_GETFD) < 0) {
return -1; return -1;
errno = EBADF; errno = EBADF;
dwr(MSG_DEBUG,"EBADF\n"); dwr(MSG_DEBUG,"EBADF\n");
handle_error("accept", "EBADF", -1);
return -1; return -1;
} }
/* Check that it is a socket */ /* Check that it is a socket */
@ -721,14 +492,12 @@ int accept(ACCEPT_SIG)
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) { if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) {
errno = ENOTSOCK; errno = ENOTSOCK;
dwr(MSG_DEBUG,"ENOTSOCK\n"); dwr(MSG_DEBUG,"ENOTSOCK\n");
handle_error("accept", "ENOTSOCK", -1);
return -1; return -1;
} }
/* Check that this socket supports accept() */ /* Check that this socket supports accept() */
if(!(opt && (SOCK_STREAM | SOCK_SEQPACKET))) { if(!(opt && (SOCK_STREAM | SOCK_SEQPACKET))) {
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
dwr(MSG_DEBUG,"EOPNOTSUPP\n"); dwr(MSG_DEBUG,"EOPNOTSUPP\n");
handle_error("accept", "EOPNOTSUPP", -1);
return -1; return -1;
} }
/* Check that we haven't hit the soft-limit file descriptors allowed */ /* Check that we haven't hit the soft-limit file descriptors allowed */
@ -737,17 +506,14 @@ int accept(ACCEPT_SIG)
if(sockfd >= rl.rlim_cur){ if(sockfd >= rl.rlim_cur){
errno = EMFILE; errno = EMFILE;
dwr(MSG_DEBUG,"EMFILE\n"); dwr(MSG_DEBUG,"EMFILE\n");
handle_error("accept", "EMFILE", -1);
return -1; return -1;
} }
/* Check address length */ /* Check address length */
if(addrlen < 0) { if(addrlen < 0) {
errno = EINVAL; errno = EINVAL;
dwr(MSG_DEBUG,"EINVAL\n"); dwr(MSG_DEBUG,"EINVAL\n");
handle_error("accept", "EINVAL", -1);
return -1; return -1;
} }
#endif
/* redirect calls for standard I/O descriptors to kernel */ /* redirect calls for standard I/O descriptors to kernel */
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO){ if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO){
@ -759,8 +525,6 @@ int accept(ACCEPT_SIG)
addr->sa_family = AF_INET; addr->sa_family = AF_INET;
/* TODO: also get address info */ /* TODO: also get address info */
char cmd[BUF_SZ];
/* The following line is required for libuv/nodejs to accept connections properly, /* The following line is required for libuv/nodejs to accept connections properly,
however, this has the side effect of causing certain webservers to max out the CPU however, this has the side effect of causing certain webservers to max out the CPU
in an accept loop */ in an accept loop */
@ -769,27 +533,16 @@ int accept(ACCEPT_SIG)
if(new_conn_socket > 0) if(new_conn_socket > 0)
{ {
dwr(MSG_DEBUG, "accept(): RX: fd = (%d) over (%d)\n", new_conn_socket, fdret_sock); dwr(MSG_DEBUG, "accept(): RX: fd = (%d) over (%d)\n", new_conn_socket, rpcfd);
/* Send our local-fd number back to service so it can complete its mapping table */ /* Send our local-fd number back to service so it can complete its mapping table */
memset(cmd, '\0', BUF_SZ);
cmd[0] = RPC_MAP;
memcpy(&cmd[1], &new_conn_socket, sizeof(new_conn_socket));
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);
send_cmd(fdret_sock, cmd); rpc_send_command(RPC_MAP, rpcfd, &new_conn_socket, sizeof(new_conn_socket));
/*
if(n_write < 0) {
errno = ECONNABORTED;
handle_error("accept", "ECONNABORTED - Error sending perceived FD to service", -1);
return -1;
}
*/
errno = ERR_OK;
dwr(MSG_DEBUG,"accept()=%d\n", new_conn_socket); dwr(MSG_DEBUG,"accept()=%d\n", new_conn_socket);
errno = ERR_OK;
return new_conn_socket; /* OK */ return new_conn_socket; /* OK */
} }
errno = EAGAIN; /* necessary? */ dwr(MSG_DEBUG, "accept(): EAGAIN - Error reading signal byte from service");
handle_error("accept", "EAGAIN - Error reading signal byte from service", -1); errno = EAGAIN;
return -EAGAIN; return -EAGAIN;
} }
@ -809,26 +562,21 @@ int listen(LISTEN_SIG)
int sock_type; int sock_type;
socklen_t sock_type_len = sizeof(sock_type); socklen_t sock_type_len = sizeof(sock_type);
#ifdef CHECKS
/* Check that this is a valid fd */ /* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) { if(fcntl(sockfd, F_GETFD) < 0) {
errno = EBADF; errno = EBADF;
handle_error("listen", "EBADF", -1);
return -1; return -1;
} }
/* Check that it is a socket */ /* Check that it is a socket */
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) { if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
errno = ENOTSOCK; errno = ENOTSOCK;
handle_error("listen", "ENOTSOCK", -1);
return -1; return -1;
} }
/* Check that this socket supports accept() */ /* Check that this socket supports accept() */
if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) { if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
handle_error("listen", "EOPNOTSUPP", -1);
return -1; return -1;
} }
#endif
/* make sure we don't touch any standard outputs */ /* make sure we don't touch any standard outputs */
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO) if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
@ -842,15 +590,12 @@ int listen(LISTEN_SIG)
} }
/* Assemble and send RPC */ /* Assemble and send RPC */
char cmd[BUF_SZ];
memset(cmd, '\0', BUF_SZ);
struct listen_st rpc_st; struct listen_st rpc_st;
rpc_st.sockfd = sockfd; rpc_st.sockfd = sockfd;
rpc_st.backlog = backlog; rpc_st.backlog = backlog;
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
cmd[0] = RPC_LISTEN;
memcpy(&cmd[1], &rpc_st, sizeof(struct listen_st)); return rpc_send_command(RPC_LISTEN, rpcfd, &rpc_st, sizeof(struct listen_st));
return send_cmd(fdret_sock, cmd);
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -866,7 +611,7 @@ int clone(CLONE_SIG)
} }
dwr(MSG_DEBUG,"clone()\n"); dwr(MSG_DEBUG,"clone()\n");
int err = realclone(fn, child_stack, flags, arg); int err = realclone(fn, child_stack, flags, arg);
checkpid(); init_service_connection();
return err; return err;
} }
@ -878,12 +623,9 @@ int clone(CLONE_SIG)
int close(CLOSE_SIG) int close(CLOSE_SIG)
{ {
dwr(MSG_DEBUG, "close(%d)\n", fd); dwr(MSG_DEBUG, "close(%d)\n", fd);
if(realclose == NULL){ if(realclose == NULL)
checkpid(); // Add for nginx support, remove for apache support. init_service_connection();
dwr(MSG_ERROR, "close(%d): SYMBOL NOT FOUND.\n", fd); if(fd == rpcfd)
return -1;
}
if(fd == fdret_sock)
return -1; /* TODO: 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);
@ -902,15 +644,12 @@ int dup2(DUP2_SIG)
return -1; return -1;
} }
dwr(MSG_DEBUG,"dup2(%d, %d)\n", oldfd, newfd); dwr(MSG_DEBUG,"dup2(%d, %d)\n", oldfd, newfd);
if(oldfd == fdret_sock) { if(oldfd == rpcfd) {
dwr(MSG_DEBUG,"client application attempted to dup2 RPC socket (%d). This is not allowed.\n", oldfd); dwr(MSG_DEBUG,"client application attempted to dup2 RPC socket (%d). This is not allowed.\n", oldfd);
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
//if(oldfd != STDIN_FILENO && oldfd != STDOUT_FILENO && oldfd != STDERR_FILENO)
// if(newfd != STDIN_FILENO && newfd != STDOUT_FILENO && newfd != STDERR_FILENO)
return realdup2(oldfd, newfd); return realdup2(oldfd, newfd);
return -1;
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -925,14 +664,6 @@ int dup3(DUP3_SIG)
return -1; return -1;
} }
dwr(MSG_DEBUG,"dup3(%d, %d, %d)\n", oldfd, newfd, flags); dwr(MSG_DEBUG,"dup3(%d, %d, %d)\n", oldfd, newfd, flags);
#ifdef DEBUG
/* Only do this check if we want to debug the intercept, otherwise, dont mess with
the client application's logging methods */
if(newfd == STDIN_FILENO || newfd == STDOUT_FILENO || newfd == STDERR_FILENO)
return newfd; /* FIXME: This is to prevent httpd from dup'ing over our stderr
and preventing us from debugging */
else
#endif
return realdup3(oldfd, newfd, flags); return realdup3(oldfd, newfd, flags);
} }
@ -955,19 +686,16 @@ int getsockname(GETSOCKNAME_SIG)
* and is an IPv4 address. */ * and is an IPv4 address. */
/* assemble and send command */ /* assemble and send command */
char cmd[BUF_SZ];
struct getsockname_st rpc_st; struct getsockname_st rpc_st;
rpc_st.sockfd = sockfd; rpc_st.sockfd = sockfd;
memcpy(&rpc_st.addr, addr, *addrlen); memcpy(&rpc_st.addr, addr, *addrlen);
memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t)); memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
cmd[0] = RPC_GETSOCKNAME; rpc_send_command(RPC_GETSOCKNAME, rpcfd, &rpc_st, sizeof(struct getsockname_st));
memcpy(&cmd[1], &rpc_st, sizeof(struct getsockname_st));
send_cmd(fdret_sock, cmd);
/* read address info from service */ /* read address info from service */
char addrbuf[sizeof(struct sockaddr_storage)]; char addrbuf[sizeof(struct sockaddr_storage)];
memset(&addrbuf, 0, sizeof(struct sockaddr_storage)); memset(&addrbuf, 0, sizeof(struct sockaddr_storage));
read(fdret_sock, &addrbuf, sizeof(struct sockaddr_storage)); read(rpcfd, &addrbuf, sizeof(struct sockaddr_storage));
struct sockaddr_storage sock_storage; struct sockaddr_storage sock_storage;
memcpy(&sock_storage, addrbuf, sizeof(struct sockaddr_storage)); memcpy(&sock_storage, addrbuf, sizeof(struct sockaddr_storage));
*addrlen = sizeof(struct sockaddr_in); *addrlen = sizeof(struct sockaddr_in);
@ -981,10 +709,7 @@ int getsockname(GETSOCKNAME_SIG)
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
long syscall(SYSCALL_SIG){ long syscall(SYSCALL_SIG){
if(realsyscall == NULL){
dwr(MSG_ERROR, "syscall(): SYMBOL NOT FOUND.\n");
return -1;
}
//dwr(MSG_DEBUG_EXTRA,"syscall(%u, ...):\n", number); //dwr(MSG_DEBUG_EXTRA,"syscall(%u, ...):\n", number);
va_list ap; va_list ap;
@ -998,6 +723,9 @@ long syscall(SYSCALL_SIG){
f=va_arg(ap, uintptr_t); f=va_arg(ap, uintptr_t);
va_end(ap); va_end(ap);
if(realsyscall == NULL)
return -1;
#if defined(__i386__) #if defined(__i386__)
/* TODO: Implement for 32-bit systems: syscall(__NR_socketcall, 18, args); /* TODO: Implement for 32-bit systems: syscall(__NR_socketcall, 18, args);
args[0] = (unsigned long) fd; args[0] = (unsigned long) fd;
@ -1013,10 +741,8 @@ long syscall(SYSCALL_SIG){
int flags = d; int flags = d;
int old_errno = errno; int old_errno = errno;
int err = accept4(sockfd, addr, addrlen, flags); int err = accept4(sockfd, addr, addrlen, flags);
errno = old_errno; errno = old_errno;
if(err == -EBADF) err = err == -EBADF ? -EAGAIN : err;
err = -EAGAIN;
return err; return err;
} }
#endif #endif

View File

@ -31,156 +31,16 @@
#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 BUF_SZ 256
#define PAYLOAD_SZ 223 /* BUF_SZ-IDX_PAYLOAD */
#define ERR_OK 0
/* Userland RPC codes */
#define RPC_UNDEFINED 0
#define RPC_CONNECT 1
#define RPC_CONNECT_SOCKARG 2
#define RPC_CLOSE 3
#define RPC_READ 4
#define RPC_WRITE 5
#define RPC_BIND 6
#define RPC_ACCEPT 7
#define RPC_LISTEN 8
#define RPC_SOCKET 9
#define RPC_SHUTDOWN 10
#define RPC_GETSOCKNAME 11
/* 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 */
/* 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
/* Flags to indicate what events a
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)
/* for AF_UNIX sockets */
#define MAX_PATH_NAME_SIZE 64
/* bind */
#define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
struct bind_st
{
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
int __tid;
};
/* connect */
#define CONNECT_SIG int __fd, const struct sockaddr * __addr, socklen_t __len
struct connect_st
{
int __fd;
struct sockaddr_storage __addr;
socklen_t __len;
int __tid;
};
/* close */
#define CLOSE_SIG int fd #define CLOSE_SIG int fd
struct close_st
{
int fd;
};
/* read */
#define DEFAULT_READ_BUFFER_SIZE 1024 * 63
/* 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 #define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
{ #define CONNECT_SIG int __fd, const struct sockaddr * __addr, socklen_t __len
int fd;
size_t count;
unsigned char buf[DEFAULT_READ_BUFFER_SIZE];
};
/* write */
#define DEFAULT_WRITE_BUFFER_SIZE 1024 * 63
/* 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
{
int fd;
size_t count;
char buf[DEFAULT_WRITE_BUFFER_SIZE];
};
#define LISTEN_SIG int sockfd, int backlog #define LISTEN_SIG int sockfd, int backlog
struct listen_st
{
int sockfd;
int backlog;
int __tid;
};
#define SOCKET_SIG int socket_family, int socket_type, int protocol #define SOCKET_SIG int socket_family, int socket_type, int protocol
struct socket_st
{
int socket_family;
int socket_type;
int protocol;
int __tid;
};
#define ACCEPT4_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags #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 ACCEPT_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen
struct accept_st
{
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
int __tid;
};
#define SHUTDOWN_SIG int socket, int how #define SHUTDOWN_SIG int socket, int how
struct shutdown_st
{
int socket;
int how;
};
struct getsockname_st
{
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
};
#define CONNECT_SOCKARG struct sockaddr * #define CONNECT_SOCKARG struct sockaddr *
#define IOCTL_SIG int __fd, unsigned long int __request, ... #define IOCTL_SIG int __fd, unsigned long int __request, ...
#define FCNTL_SIG int __fd, int __cmd, ... #define FCNTL_SIG int __fd, int __cmd, ...

View File

@ -48,10 +48,12 @@
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "common.inc.c" #include "common.inc.c"
#include "rpc.h"
#define APPLICATION_POLL_FREQ 20 #define APPLICATION_POLL_FREQ 20
#define ZT_LWIP_TCP_TIMER_INTERVAL 5 #define ZT_LWIP_TCP_TIMER_INTERVAL 5
#define STATUS_TMR_INTERVAL 3000 // How often we check connection statuses #define STATUS_TMR_INTERVAL 3000 // How often we check connection statuses
#define DEFAULT_READ_BUFFER_SIZE 1024 * 63
namespace ZeroTier { namespace ZeroTier {
@ -128,9 +130,7 @@ public:
PhySocket *rpcSock; PhySocket *rpcSock;
PhySocket *dataSock; PhySocket *dataSock;
struct tcp_pcb *pcb; struct tcp_pcb *pcb;
struct sockaddr_storage *addr; struct sockaddr_storage *addr;
unsigned char buf[DEFAULT_READ_BUFFER_SIZE]; unsigned char buf[DEFAULT_READ_BUFFER_SIZE];
int idx; int idx;
}; };
@ -926,6 +926,9 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
if(!l->conn) if(!l->conn)
dwr(MSG_ERROR, "nc_err(): Connection is NULL!\n"); dwr(MSG_ERROR, "nc_err(): Connection is NULL!\n");
if(l->conn->listening)
return;
switch(err) switch(err)
{ {
case ERR_MEM: case ERR_MEM:
@ -1424,6 +1427,7 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
ip_addr_t conn_addr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr); ip_addr_t conn_addr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr);
if(conn != NULL) { if(conn != NULL) {
if (!conn->listening)
lwipstack->tcp_sent(conn->pcb, nc_sent); lwipstack->tcp_sent(conn->pcb, nc_sent);
lwipstack->tcp_recv(conn->pcb, nc_recved); lwipstack->tcp_recv(conn->pcb, nc_recved);
lwipstack->tcp_err(conn->pcb, nc_err); lwipstack->tcp_err(conn->pcb, nc_err);
@ -1482,6 +1486,8 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
} }
// Everything seems to be ok, but we don't have enough info to retval // Everything seems to be ok, but we don't have enough info to retval
conn->pending=true; conn->pending=true;
conn->listening=true;
send_return_value(conn, -1);
} }
else { else {
dwr(MSG_ERROR, " handle_connect(): could not locate PCB based on their fd\n"); dwr(MSG_ERROR, " handle_connect(): could not locate PCB based on their fd\n");
@ -1515,9 +1521,9 @@ void NetconEthernetTap::handle_write(TcpConnection *conn)
if(!conn->listening) if(!conn->listening)
lwipstack->_tcp_output(conn->pcb); lwipstack->_tcp_output(conn->pcb);
if(conn->dataSock) { if(conn->dataSock && !conn->listening) {
int read_fd = _phy.getDescriptor(conn->dataSock); int read_fd = _phy.getDescriptor(conn->dataSock);
if((r = read(read_fd, (&conn->buf)+conn->idx, sndbuf)) > 0) { if((r = recvfrom(read_fd, (&conn->buf)+conn->idx, sndbuf, MSG_DONTWAIT, NULL, NULL)) > 0) {
conn->idx += r; conn->idx += r;
/* Writes data pulled from the client's socket buffer to LWIP. This merely sends the /* Writes data pulled from the client's socket buffer to LWIP. This merely sends the
* data to LWIP to be enqueued and eventually sent to the network. */ * data to LWIP to be enqueued and eventually sent to the network. */

254
netcon/RPC.c Normal file
View File

@ -0,0 +1,254 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/un.h>
#include <pthread.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <strings.h>
#include "rpc.h"
#define RPC_FD 1023
#define SERVICE_CONNECT_ATTEMPTS 30
static int instance_count;
static int rpc_count;
static pthread_mutex_t lock;
void rpc_mutex_init() {
if(pthread_mutex_init(&lock, NULL) != 0) {
fprintf(stderr, "error while initializing service call mutex\n");
}
}
void rpc_mutex_destroy() {
pthread_mutex_destroy(&lock);
}
/*
* Reads a return value from the service and sets errno (if applicable)
*/
int get_retval(int rpc_sock)
{
if(rpc_sock >= 0) {
int retval;
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
char retbuf[BUF_SZ];
memset(&retbuf, 0, sz);
int n_read = read(rpc_sock, &retbuf, sz);
if(n_read > 0) {
memcpy(&retval, &retbuf[1], sizeof(retval));
memcpy(&errno, &retbuf[1+sizeof(retval)], sizeof(errno));
return retval;
}
}
return -1;
}
/*
* Reads a new file descriptor from the service
*/
int get_new_fd(int sock)
{
char buf[BUF_SZ];
int newfd;
ssize_t size = sock_fd_read(sock, buf, sizeof(buf), &newfd);
if(size > 0){
fprintf(stderr, "get_new_fd(): RX: fd = (%d) over (%d)\n", newfd, sock);
return newfd;
}
fprintf(stderr, "get_new_fd(): ERROR: unable to read fd over (%d)\n", sock);
return -1;
}
int rpc_join(const char * sockname)
{
struct sockaddr_un addr;
int conn_err = -1, attempts = 0;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);
int sock;
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
fprintf(stderr, "Error while creating RPC socket\n");
return -1;
}
while((conn_err != 0) && (attempts < SERVICE_CONNECT_ATTEMPTS)){
if((conn_err = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
fprintf(stderr, "Error while connecting to RPC socket. Re-attempting...\n");
sleep(1);
}
else {
int newfd = dup2(sock, RPC_FD-instance_count);
close(sock);
return newfd;
}
attempts++;
}
return -1;
}
/*
* Send a command to the service
*/
int rpc_send_command(int cmd, int rpc_sock, void *data, int len)
{
char cmdbuf[BUF_SZ];
cmdbuf[0] = cmd;
memcpy(&cmdbuf[1], data, len);
pthread_mutex_lock(&lock);
char metabuf[BUF_SZ]; // portion of buffer which contains RPC metadata for debugging
#ifdef VERBOSE
/*
#define IDX_PID 0
#define IDX_TID sizeof(pid_t)
#define IDX_COUNT IDX_TID + sizeof(pid_t)
#define IDX_TIME IDX_COUNT + sizeof(int)
#define IDX_CMD IDX_TIME + 20 // 20 being the length of the timestamp string
#define IDX_PAYLOAD IDX_TIME + sizeof(char)
*/
/* [pid_t] [pid_t] [rpc_count] [int] [...] */
memset(metabuf, 0, BUF_SZ);
pid_t pid = syscall(SYS_getpid);
pid_t tid = syscall(SYS_gettid);
rpc_count++;
char timestring[20];
time_t timestamp;
timestamp = time(NULL);
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 */
#endif
/* Combine command flag+payload with RPC metadata */
memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len);
int n_write = write(rpc_sock, &metabuf, BUF_SZ);
if(n_write < 0) {
fprintf(stderr, "Error writing command to service (CMD = %d)\n", cmdbuf[0]);
errno = 0;
}
int ret = ERR_OK;
if(n_write > 0) {
if(cmdbuf[0]==RPC_SOCKET) {
ret = get_new_fd(rpc_sock);
}
if(cmdbuf[0]==RPC_MAP_REQ
|| cmdbuf[0]==RPC_CONNECT
|| cmdbuf[0]==RPC_BIND
|| cmdbuf[0]==RPC_LISTEN
|| cmdbuf[0]==RPC_MAP) {
ret = get_retval(rpc_sock);
}
if(cmdbuf[0]==RPC_GETSOCKNAME) {
ret = n_write;
}
}
else {
ret = -1;
}
pthread_mutex_unlock(&lock);
return ret;
}
/*
* Send file descriptor
*/
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;
}
/*
* Read a file descriptor
*/
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) {
fprintf(stderr, "sock_fd_read(): recvmsg: Error\n");
return -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);
return -1;
}
if (cmsg->cmsg_type != SCM_RIGHTS) {
fprintf (stderr, "invalid cmsg_type %d\n",cmsg->cmsg_type);
return -1;
}
*fd = *((int *) CMSG_DATA(cmsg));
} else *fd = -1;
} else {
size = read (sock, buf, bufsize);
if (size < 0) {
fprintf(stderr, "sock_fd_read(): read: Error\n");
return -1;
}
}
return size;
}

107
netcon/RPC.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef __RPCLIB_H_
#define __RPCLIB_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 BUF_SZ 256
#define PAYLOAD_SZ 223 /* BUF_SZ-IDX_PAYLOAD */
#define ERR_OK 0
/* RPC codes */
#define RPC_UNDEFINED 0
#define RPC_CONNECT 1
#define RPC_CONNECT_SOCKARG 2
#define RPC_CLOSE 3
#define RPC_READ 4
#define RPC_WRITE 5
#define RPC_BIND 6
#define RPC_ACCEPT 7
#define RPC_LISTEN 8
#define RPC_SOCKET 9
#define RPC_SHUTDOWN 10
#define RPC_GETSOCKNAME 11
/* 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 */
#ifdef __cplusplus
extern "C" {
#endif
void rpc_mutex_destroy();
void rpc_mutex_init();
int get_retval(int);
int get_new_fd(int);
int rpc_join(const char * sockname);
int rpc_send_command(int cmd, int rpc_sock, void *data, int len);
ssize_t sock_fd_write(int sock, int fd);
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
/* Structures used for sending commands via RPC mechanism */
struct bind_st {
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
int __tid;
};
struct connect_st {
int __fd;
struct sockaddr_storage __addr;
socklen_t __len;
int __tid;
};
struct close_st {
int fd;
};
struct listen_st {
int sockfd;
int backlog;
int __tid;
};
struct socket_st {
int socket_family;
int socket_type;
int protocol;
int __tid;
};
struct accept_st {
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
int __tid;
};
struct shutdown_st {
int socket;
int how;
};
struct getsockname_st {
int sockfd;
struct sockaddr_storage addr;
socklen_t addrlen;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -37,7 +37,10 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <pthread.h> #include <pthread.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/syscall.h>
#ifndef _COMMON_H
#define _COMMON_H 1
#define DEBUG_LEVEL 4 #define DEBUG_LEVEL 4
@ -49,8 +52,6 @@
#ifdef NETCON_INTERCEPT #ifdef NETCON_INTERCEPT
static pthread_mutex_t loglock;
void print_addr(struct sockaddr *addr) void print_addr(struct sockaddr *addr)
{ {
char *s = NULL; char *s = NULL;
@ -91,8 +92,8 @@ void print_addr(struct sockaddr *addr)
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));
pid_t pid = getpid(); pid_t tid = syscall(SYS_gettid);
fprintf(stderr, "%s [pid=%7d] ", timestring, pid); fprintf(stderr, "%s [tid=%7d] ", timestring, tid);
#endif #endif
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
fflush(stderr); fflush(stderr);
@ -104,95 +105,4 @@ void print_addr(struct sockaddr *addr)
} }
#endif #endif
static ssize_t sock_fd_write(int sock, int fd); #endif
static ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
static 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;
}
static 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) {
dwr(MSG_DEBUG, "sock_fd_read(): recvmsg: Error\n");
return -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);
return -1;
}
if (cmsg->cmsg_type != SCM_RIGHTS) {
fprintf (stderr, "invalid cmsg_type %d\n",cmsg->cmsg_type);
return -1;
}
*fd = *((int *) CMSG_DATA(cmsg));
} else *fd = -1;
} else {
size = read (sock, buf, bufsize);
if (size < 0) {
dwr(MSG_DEBUG, "sock_fd_read(): read: Error\n");
return -1;
}
}
return size;
}

View File

@ -31,8 +31,6 @@ echo '--- Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
# Generate large random file for transfer test, share md5sum for monitor container to check # Generate large random file for transfer test, share md5sum for monitor container to check
echo '*** Generating ' "$bigfile_size" ' file' echo '*** Generating ' "$bigfile_size" ' file'
@ -43,4 +41,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
rm -rf /run/httpd/* /tmp/httpd* rm -rf /run/httpd/* /tmp/httpd*
zerotier-intercept /usr/sbin/httpd -X
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
/usr/sbin/httpd -X

View File

@ -31,8 +31,6 @@ echo '--- Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
# Generate large random file for transfer test, share md5sum for monitor container to check # Generate large random file for transfer test, share md5sum for monitor container to check
echo '*** Generating ' "$bigfile_size" ' file' echo '*** Generating ' "$bigfile_size" ' file'
@ -43,4 +41,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
rm -rf /run/httpd/* /tmp/httpd* rm -rf /run/httpd/* /tmp/httpd*
zerotier-intercept /usr/sbin/httpd -X
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
/usr/sbin/httpd -X

View File

@ -32,8 +32,6 @@ echo '*** Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
# Generate large random file for transfer test, share md5sum for monitor container to check # Generate large random file for transfer test, share md5sum for monitor container to check
echo '*** Generating ' "$bigfile_size" ' file' echo '*** Generating ' "$bigfile_size" ' file'
@ -45,4 +43,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
rm -rf /run/httpd/* /tmp/httpd* rm -rf /run/httpd/* /tmp/httpd*
zerotier-intercept /usr/sbin/httpd -X
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
/usr/sbin/httpd -X

View File

@ -32,8 +32,6 @@ echo '*** Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
cp -f nginx.conf_ /etc/nginx/nginx.conf cp -f nginx.conf_ /etc/nginx/nginx.conf
nginx_html_path=/usr/share/nginx/html/ nginx_html_path=/usr/share/nginx/html/
@ -46,4 +44,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
zerotier-intercept nginx
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
nginx

View File

@ -32,8 +32,6 @@ echo '*** Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
cp -f nginx.conf_ /etc/nginx/nginx.conf cp -f nginx.conf_ /etc/nginx/nginx.conf
nginx_html_path=/usr/share/nginx/html/ nginx_html_path=/usr/share/nginx/html/
@ -46,4 +44,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
zerotier-intercept nginx
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
nginx

View File

@ -32,8 +32,6 @@ echo '*** Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
cp -f nginx.conf_ /etc/nginx/nginx.conf cp -f nginx.conf_ /etc/nginx/nginx.conf
nginx_html_path=/usr/share/nginx/html/ nginx_html_path=/usr/share/nginx/html/
@ -46,4 +44,7 @@ echo '*** Wrote MD5 sum to ' "$tx_md5sumfile"
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
zerotier-intercept nginx
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
nginx

View File

@ -30,8 +30,7 @@ echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev" export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
echo $ZT_NC_NETWORK export LD_PRELOAD=./libzerotierintercept.so
export LD_PRELOAD ./libzerotierintercept.so
# --- Test section --- # --- Test section ---
echo '*** Starting application...' echo '*** Starting application...'

View File

@ -29,9 +29,10 @@ echo '*** Up and running at' $virtip4 ' on network: ' $nwid
echo '*** Writing address to ' "$address_file" echo '*** Writing address to ' "$address_file"
echo $virtip4 > "$address_file" echo $virtip4 > "$address_file"
export ZT_NC_NWID=$dev
# --- Test section --- # --- Test section ---
echo '*** Starting application...' echo '*** Starting application...'
sleep 0.5 sleep 0.5
zerotier-intercept /usr/bin/redis-server --port 6379
export ZT_NC_NETWORK=/var/lib/zerotier-one/nc_"$dev"
export LD_PRELOAD=./libzerotierintercept.so
/usr/bin/redis-server --port 6379

7
netcon/httpserver.js Normal file
View File

@ -0,0 +1,7 @@
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("welcome to the machine!\n");
});
server.listen(8080);
console.log("Server running!");

View File

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
# This script is only needed for debugging purposes
cp libzerotierintercept.so /lib/libzerotierintercept.so cp libzerotierintercept.so /lib/libzerotierintercept.so
ln -sf /lib/libzerotierintercept.so /lib/libzerotierintercept ln -sf /lib/libzerotierintercept.so /lib/libzerotierintercept