summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Henry <joseph.henry@gmail.com>2015-10-21 16:27:17 -0700
committerJoseph Henry <joseph.henry@gmail.com>2015-10-21 16:27:17 -0700
commit303579cb42ed35a001174cf74e195ebd8321ab5d (patch)
treeaf8641017649723c4c0b6efac6ad4a6d014ec79d
parent8b03965912d3a3070c4e447c65b70a7c16067ee2 (diff)
downloadinfinitytier-303579cb42ed35a001174cf74e195ebd8321ab5d.tar.gz
infinitytier-303579cb42ed35a001174cf74e195ebd8321ab5d.zip
Added Node.js support
-rwxr-xr-xnetcon/Intercept.c163
-rwxr-xr-xnetcon/Intercept.h49
-rw-r--r--netcon/NetconEthernetTap.cpp6
-rw-r--r--netcon/README.md13
-rwxr-xr-xnetcon/libintercept.so.1.0bin45888 -> 47664 bytes
-rwxr-xr-xnetcon/liblwip.sobin342016 -> 0 bytes
6 files changed, 106 insertions, 125 deletions
diff --git a/netcon/Intercept.c b/netcon/Intercept.c
index d431f825..72c4cbda 100755
--- a/netcon/Intercept.c
+++ b/netcon/Intercept.c
@@ -33,6 +33,9 @@
/* Name used in err msgs */
char *progname = "";
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
#include <stdio.h>
#include <dlfcn.h>
#include <strings.h>
@@ -44,39 +47,18 @@ char *progname = "";
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-
-#include <netinet/in.h>
-#include <net/if.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
-#include <poll.h>
-#include <pthread.h>
-#include <unistd.h>
-
-/* For NPs */
-#include <sys/stat.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-/* for mmap */
-#include <sys/mman.h>
-
-#ifdef USE_SOCKS_DNS
- #include <resolv.h>
-#endif
-
#include "Intercept.h"
#include "Common.h"
#ifdef CHECKS
- //#include <sys/time.h>
#include <sys/resource.h>
#include <linux/net.h> /* for NPROTO */
-
#define SOCK_MAX (SOCK_PACKET + 1)
#define SOCK_TYPE_MASK 0xf
#endif
@@ -87,7 +69,6 @@ static int (*realresinit)(void);
#endif
static int (*realconnect)(CONNECT_SIG);
static int (*realselect)(SELECT_SIG);
-static int (*realpoll)(POLL_SIG);
static int (*realbind)(BIND_SIG);
static int (*realaccept)(ACCEPT_SIG);
static int (*reallisten)(LISTEN_SIG);
@@ -95,12 +76,12 @@ static int (*realsocket)(SOCKET_SIG);
static int (*realsetsockopt)(SETSOCKOPT_SIG);
static int (*realgetsockopt)(GETSOCKOPT_SIG);
static int (*realaccept4)(ACCEPT4_SIG);
+static long (*realsyscall)(SYSCALL_SIG);
/* Exported Function Prototypes */
void my_init(void);
int connect(CONNECT_SIG);
int select(SELECT_SIG);
-int poll(POLL_SIG);
int close(CLOSE_SIG);
int bind(BIND_SIG);
int accept(ACCEPT_SIG);
@@ -109,6 +90,7 @@ int socket(SOCKET_SIG);
int setsockopt(SETSOCKOPT_SIG);
int getsockopt(GETSOCKOPT_SIG);
int accept4(ACCEPT4_SIG);
+long syscall(SYSCALL_SIG);
#ifdef USE_SOCKS_DNS
int res_init(void);
@@ -121,7 +103,6 @@ void load_symbols(void);
void set_up_intercept();
int checkpid();
-
#define BUF_SZ 32
#define SERVICE_CONNECT_ATTEMPTS 30
#define ERR_OK 0
@@ -197,8 +178,7 @@ int get_retval()
/* Sets up the connection pipes and sockets to the service */
int init_service_connection()
{
- if(!is_initialized)
- {
+ if(!is_initialized) {
struct sockaddr_un addr;
int tfd = -1, attempts = 0, conn_err = -1;
memset(&addr, 0, sizeof(addr));
@@ -209,11 +189,8 @@ int init_service_connection()
perror("socket error");
exit(-1);
}
- while(conn_err < 0 && attempts < SERVICE_CONNECT_ATTEMPTS)
- {
- //dwr("trying connection (%d): %s\n", tfd, af_sock_name);
+ while(conn_err < 0 && attempts < SERVICE_CONNECT_ATTEMPTS) {
conn_err = realconnect(tfd, (struct sockaddr*)&addr, sizeof(addr));
-
if(conn_err < 0) {
dwr("re-attempting connection in %ds\n", 1+attempts);
sleep(1);
@@ -235,13 +212,11 @@ int init_service_connection()
void my_dest(void) __attribute__ ((destructor));
void my_dest(void) {
-
- dwr("closing connections to service...\n");
+ //dwr("closing connections to service...\n");
close(fdret_sock);
pthread_mutex_destroy(&lock);
}
-
void load_symbols(void)
{
#ifdef USE_OLD_DLSYM
@@ -262,11 +237,12 @@ void load_symbols(void)
reallisten = dlsym(RTLD_NEXT, "listen");
realsocket = dlsym(RTLD_NEXT, "socket");
realbind = dlsym(RTLD_NEXT, "bind");
- realpoll = dlsym(RTLD_NEXT, "poll");
realselect = dlsym(RTLD_NEXT, "select");
realsetsockopt = dlsym(RTLD_NEXT, "setsockopt");
realgetsockopt = dlsym(RTLD_NEXT, "getsockopt");
realaccept4 = dlsym(RTLD_NEXT, "accept4");
+ //realclone = dlsym(RTLD_NEXT, "clone");
+ realsyscall = dlsym(RTLD_NEXT, "syscall");
#ifdef USE_SOCKS_DNS
realresinit = dlsym(RTLD_NEXT, "res_init");
#endif
@@ -278,11 +254,12 @@ void load_symbols(void)
realaccept = dlsym(lib, "accept");
reallisten = dlsym(lib, "listen");
realsocket = dlsym(lib, "socket");
- realpoll = dlsym(lib, "poll");
realselect = dlsym(lib, "select");
realsetsockopt = dlsym(lib, "setsockopt");
realgetsockopt = dlsym(lib, "getsockopt");
realaccept4 = dlsym(lib), "accept4");
+ //realclone = dlsym(lib, "clone");
+ realsyscall = dlsym(lib, "syscall");
#ifdef USE_SOCKS_DNS
realresinit = dlsym(lib, "res_init");
#endif
@@ -317,6 +294,9 @@ void set_up_intercept()
/* int socket, int level, int option_name, const void *option_value, socklen_t option_len */
int setsockopt(SETSOCKOPT_SIG)
{
+ if(level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE)){
+ return 0;
+ }
/* make sure we don't touch any standard outputs */
if(socket == STDIN_FILENO || socket == STDOUT_FILENO || socket == STDERR_FILENO)
return(realsetsockopt(socket, level, option_name, option_value, option_len));
@@ -362,6 +342,7 @@ int getsockopt(GETSOCKOPT_SIG)
int socket(SOCKET_SIG)
{
+ //dwr("socket()*:\n");
int err;
#ifdef CHECKS
/* Check that type makes sense */
@@ -401,7 +382,7 @@ int socket(SOCKET_SIG)
return realsocket(socket_family, socket_type, protocol);
}
- /* Assemble and route command */
+ /* Assemble and send RPC */
struct socket_st rpc_st;
rpc_st.socket_family = socket_family;
rpc_st.socket_type = socket_type;
@@ -453,6 +434,7 @@ int socket(SOCKET_SIG)
connect() intercept function */
int connect(CONNECT_SIG)
{
+ //dwr("connect()*:\n");
struct sockaddr_in *connaddr;
connaddr = (struct sockaddr_in *) __addr;
@@ -494,13 +476,7 @@ int connect(CONNECT_SIG)
return err;
}
- //int flags = fcntl(__fd, F_GETFD);
- //dwr("connect(): socket flags = %d\n", flags);
- //if(sock_type && O_NONBLOCK) {
- // dwr("connect(): O_NONBLOCK\n");
- //}
-
- /* assemble and route command */
+ /* Assemble and send RPC */
int err;
char cmd[BUF_SZ];
memset(cmd, '\0', BUF_SZ);
@@ -513,10 +489,12 @@ int connect(CONNECT_SIG)
memcpy(&cmd[1], &rpc_st, sizeof(struct connect_st));
pthread_mutex_lock(&lock);
send_command(fdret_sock, cmd);
+ /*
if(sock_type && O_NONBLOCK) {
//pthread_mutex_unlock(&lock);
//return EINPROGRESS;
}
+ */
err = get_retval();
pthread_mutex_unlock(&lock);
return err;
@@ -530,20 +508,11 @@ int connect(CONNECT_SIG)
fd_set *exceptfds, struct timeval *timeout */
int select(SELECT_SIG)
{
+ //dwr("select()*:\n");
return realselect(n, readfds, writefds, exceptfds, timeout);
}
/*------------------------------------------------------------------------------
------------------------------------ poll() -------------------------------------
-------------------------------------------------------------------------------*/
-
-/* struct pollfd *__fds, nfds_t __nfds, int __timeout */
-int poll(POLL_SIG)
-{
- return realpoll(__fds, __nfds, __timeout);
-}
-
-/*------------------------------------------------------------------------------
------------------------------------ bind() ------------------------------------
------------------------------------------------------------------------------*/
@@ -551,6 +520,7 @@ int poll(POLL_SIG)
bind() intercept function */
int bind(BIND_SIG)
{
+ //dwr("bind()*:\n");
#ifdef CHECKS
/* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) {
@@ -558,9 +528,9 @@ int bind(BIND_SIG)
errno = EBADF;
}
/* Check that it is a socket */
- int sock_type = -1;
- socklen_t sock_type_len = sizeof(sock_type);
- if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+ int opt = -1;
+ socklen_t opt_len;
+ if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) {
errno = ENOTSOCK;
return -1;
}
@@ -586,7 +556,7 @@ int bind(BIND_SIG)
}
return(realbind(sockfd, addr, addrlen));
}
- /* Assemble and route command */
+ /* Assemble and send RPC */
char cmd[BUF_SZ];
struct bind_st rpc_st;
rpc_st.sockfd = sockfd;
@@ -612,13 +582,21 @@ int bind(BIND_SIG)
/* int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags */
int accept4(ACCEPT4_SIG)
{
+ //dwr("accept4()*:\n");
#ifdef CHECKS
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) {
errno = EINVAL;
return -1;
}
#endif
- return accept(sockfd, addr, addrlen);
+ int newfd = accept(sockfd, addr, addrlen);
+ if(newfd > 0) {
+ if(flags & SOCK_CLOEXEC)
+ fcntl(newfd, F_SETFL, FD_CLOEXEC);
+ if(flags & SOCK_NONBLOCK)
+ fcntl(newfd, F_SETFL, O_NONBLOCK);
+ }
+ return newfd;
}
@@ -630,6 +608,7 @@ int accept4(ACCEPT4_SIG)
accept() intercept function */
int accept(ACCEPT_SIG)
{
+ //dwr("accept()*:\n");
#ifdef CHECKS
/* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) {
@@ -637,14 +616,14 @@ int accept(ACCEPT_SIG)
errno = EBADF;
}
/* Check that it is a socket */
- int sock_type;
- socklen_t sock_type_len = sizeof(sock_type);
- if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+ int opt;
+ socklen_t opt_len;
+ if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len) < 0) {
errno = ENOTSOCK;
return -1;
}
/* Check that this socket supports accept() */
- if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
+ if(!(opt && (SOCK_STREAM | SOCK_SEQPACKET))) {
errno = EOPNOTSUPP;
return -1;
}
@@ -662,12 +641,13 @@ int accept(ACCEPT_SIG)
}
#endif
- /* make sure we don't touch any standard outputs */
+ /* redirect calls for standard I/O descriptors to kernel */
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
return(realaccept(sockfd, addr, addrlen));
- addr->sa_family = AF_INET;
- /* TODO: also get address info */
+ if(addr)
+ addr->sa_family = AF_INET;
+ /* TODO: also get address info */
char cmd[BUF_SZ];
if(realaccept == NULL) {
@@ -675,6 +655,9 @@ int accept(ACCEPT_SIG)
return -1;
}
+ //if(opt & O_NONBLOCK)
+ //fcntl(sockfd, F_SETFL, O_NONBLOCK);
+
char rbuf[16], c[1];
int new_conn_socket;
int n = read(sockfd, c, sizeof(c)); // Read signal byte
@@ -694,7 +677,8 @@ int accept(ACCEPT_SIG)
return -1;
}
pthread_mutex_unlock(&lock);
- //errno = ERR_OK;
+ errno = ERR_OK;
+ dwr("accepting for %d\n", new_conn_socket);
return new_conn_socket; // OK
}
else {
@@ -704,9 +688,8 @@ int accept(ACCEPT_SIG)
}
}
dwr("Error reading signal byte from service.\n");
- //errno = EWOULDBLOCK;
- errno = ECONNABORTED; // FIXME: Closest match, service unreachable
- return -1;
+ errno = EAGAIN; /* necessary? */
+ return -EAGAIN;
}
@@ -718,6 +701,7 @@ int accept(ACCEPT_SIG)
listen() intercept function */
int listen(LISTEN_SIG)
{
+ //dwr("listen()*:\n");
#ifdef CHECKS
/* Check that this is a valid fd */
if(fcntl(sockfd, F_GETFD) < 0) {
@@ -738,14 +722,12 @@ int listen(LISTEN_SIG)
}
#endif
- int err;
-
/* make sure we don't touch any standard outputs */
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
return(reallisten(sockfd, backlog));
+ /* Assemble and send RPC */
char cmd[BUF_SZ];
- /* Assemble and route command */
memset(cmd, '\0', BUF_SZ);
struct listen_st rpc_st;
rpc_st.sockfd = sockfd;
@@ -757,6 +739,41 @@ int listen(LISTEN_SIG)
send_command(fdret_sock, cmd);
//err = get_retval();
pthread_mutex_unlock(&lock);
- //errno = ERR_OK;
return ERR_OK;
}
+
+/*------------------------------------------------------------------------------
+------------------------------------ syscall()----------------------------------
+------------------------------------------------------------------------------*/
+
+long syscall(SYSCALL_SIG)
+{
+ va_list ap;
+ uintptr_t a,b,c,d,e,f;
+ va_start(ap, number);
+ a=va_arg(ap, uintptr_t);
+ b=va_arg(ap, uintptr_t);
+ c=va_arg(ap, uintptr_t);
+ d=va_arg(ap, uintptr_t);
+ e=va_arg(ap, uintptr_t);
+ f=va_arg(ap, uintptr_t);
+ va_end(ap);
+
+#if defined(__i386__)
+ /* TODO: Implement for 32-bit systems: syscall(__NR_socketcall, 18, args);
+ args[0] = (unsigned long) fd;
+ args[1] = (unsigned long) addr;
+ args[2] = (unsigned long) addrlen;
+ args[3] = (unsigned long) flags;
+ */
+#else
+ if(number == __NR_accept4) {
+ int sockfd = a;
+ struct sockaddr * addr = (struct sockaddr*)b;
+ socklen_t * addrlen = (socklen_t*)c;
+ int flags = d;
+ return accept4(sockfd, addr, addrlen, flags);
+ }
+#endif
+ return realsyscall(number,a,b,c,d,e,f);
+}
diff --git a/netcon/Intercept.h b/netcon/Intercept.h
index 7a8864aa..1a36cf76 100755
--- a/netcon/Intercept.h
+++ b/netcon/Intercept.h
@@ -165,58 +165,11 @@ struct shutdown_st
#define CONNECT_SOCKARG struct sockaddr *
#define SELECT_SIG int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout
-#define POLL_SIG struct pollfd *__fds, nfds_t __nfds, int __timeout
#define IOCTL_SIG int __fd, unsigned long int __request, ...
#define FCNTL_SIG int __fd, int __cmd, ...
-#define CLONE_SIG int (*fn) (void *arg), void *child_stack, int flags, void *arg
#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
-
-
-/* LWIP error beautification */
-
-/*
-const char *lwiperror(int n)
-{
- switch(n)
- {
- case 0:
- return "ERR_OK";
- case -1:
- return "ERR_MEM (out of memory)";
- case -2:
- return "ERR_BUF (buffer error)";
- case -3:
- return "ERR_TIMEOUT (timeout)";
- case -4:
- return "ERR_RTE (routing problem)";
- case -5:
- return "ERR_INPROGRESS (operation in progress)";
- case -6:
- return "ERR_VAL (illegal value)";
- case -7:
- return "ERR_WOULDBLOCK (operation would block)";
- case -8:
- return "ERR_USE (address in use)";
- case -9:
- return "ERR_ISCONN (already connected)";
- case -10:
- return "Fatal: ERR_ABRT (connection aborted)";
- case -11:
- return "Fatal: ERR_RST (connection reset)";
- case -12:
- return "Fatal: ERR_CLSD (connection closed)";
- case -13:
- return "Fatal: ERR_CONN (not connected)";
- case -14:
- return "Fatal: ERR_ARG (illegal argument)";
- case -15:
- return "Fatal: ERR_IF (low level netif error)";
- default:
- return "UNKNOWN_RET_VAL";
- }
-}
-*/
+#define SYSCALL_SIG long number, ...
#endif
diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp
index a5ce6f80..c2e31718 100644
--- a/netcon/NetconEthernetTap.cpp
+++ b/netcon/NetconEthernetTap.cpp
@@ -547,7 +547,7 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
if(socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
if(errno < 0) {
l->tap->send_return_value(conn, -1, errno);
- //fprintf(stderr, "**************\n");
+ fprintf(stderr, "nc_accept(): unable to create socketpair\n");
return ERR_MEM;
}
}
@@ -857,7 +857,6 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
int conn_port = lwipstack->ntohs(connaddr->sin_port);
ip_addr_t conn_addr;
conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
-
TcpConnection *conn = getConnectionByTheirFD(sock, bind_rpc->sockfd);
if(conn) {
@@ -878,9 +877,8 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
if(err == ERR_BUF)
send_return_value(conn, -1, ENOMEM); // FIXME: Closest match
}
- else {
+ else
send_return_value(conn, ERR_OK, ERR_OK); // Success
- }
}
else {
fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n");
diff --git a/netcon/README.md b/netcon/README.md
new file mode 100644
index 00000000..f4d1855e
--- /dev/null
+++ b/netcon/README.md
@@ -0,0 +1,13 @@
+20151021 Added Node.js support
+
+Notes:
+ - syscall(long number, ...) is now intercepted and re-directs the __NR_accept4 call to our intercepted accept4() function
+ - accept() now returns -EAGAIN in the case that we cannot read a signal byte from the descriptor linked to the service. This
+ is because the uv__server_io() function in libuv used by Node.js looks for this return value upon failure, without it we
+ were observing an innfinite loop in the I/O polling code in libuv.
+ - accept4() now correctly sets given flags for descriptor returned by accept()
+ - setsockopt() was modified to return success on any call with the following conditions:
+ level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
+ This might be unnecessary or might need a better workaround
+ - Careful attention should be given to how arguments are passed in the intercepted syscall() function, this differs for
+ 32/64-bit systems
diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0
index de9dff34..8e40bae2 100755
--- a/netcon/libintercept.so.1.0
+++ b/netcon/libintercept.so.1.0
Binary files differ
diff --git a/netcon/liblwip.so b/netcon/liblwip.so
deleted file mode 100755
index aba90d8e..00000000
--- a/netcon/liblwip.so
+++ /dev/null
Binary files differ