mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-19 13:07:55 +00:00
RPC update
This commit is contained in:
parent
c6571073fe
commit
e2ae9165c6
@ -95,24 +95,18 @@ 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: rpc_lib $(OBJS)
|
netcon: $(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 -Lnetcon/ -lrpc
|
$(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 -x c netcon/RPC.c $(LDLIBS) -ldl
|
||||||
# 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 -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
|
cd netcon ; gcc -g -O2 -Wall -std=c99 -fPIC -DVERBOSE -D_GNU_SOURCE -DNETCON_INTERCEPT -I. -nostdlib -shared -o libzerotierintercept.so Intercept.c RPC.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
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
------------------- Intercept<--->Service Comm mechanisms ----------------------
|
------------------- Intercept<--->Service Comm mechanisms ----------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static char *network_pathname = (char *)0;
|
static char *netpath = (char *)0;
|
||||||
|
|
||||||
/* 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
|
||||||
@ -79,7 +79,7 @@ static int connected_to_service(int sockfd)
|
|||||||
getpeername(sockfd, (struct sockaddr*)&addr, &len);
|
getpeername(sockfd, (struct sockaddr*)&addr, &len);
|
||||||
if (addr.ss_family == AF_LOCAL || addr.ss_family == AF_LOCAL) {
|
if (addr.ss_family == AF_LOCAL || addr.ss_family == AF_LOCAL) {
|
||||||
addr_un = (struct sockaddr_un*)&addr;
|
addr_un = (struct sockaddr_un*)&addr;
|
||||||
if(strcmp(addr_un->sun_path, network_pathname) == 0) {
|
if(strcmp(addr_un->sun_path, netpath) == 0) {
|
||||||
dwr(MSG_DEBUG_EXTRA,"connected_to_service(): Yes, %s\n", addr_un->sun_path);
|
dwr(MSG_DEBUG_EXTRA,"connected_to_service(): Yes, %s\n", addr_un->sun_path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -115,12 +115,11 @@ static int set_up_intercept()
|
|||||||
realsyscall = dlsym(RTLD_NEXT, "syscall");
|
realsyscall = dlsym(RTLD_NEXT, "syscall");
|
||||||
realgetsockname = dlsym(RTLD_NEXT, "getsockname");
|
realgetsockname = dlsym(RTLD_NEXT, "getsockname");
|
||||||
}
|
}
|
||||||
|
if (!netpath) {
|
||||||
if (!network_pathname) {
|
netpath = getenv("ZT_NC_NETWORK");
|
||||||
network_pathname = getenv("ZT_NC_NETWORK");
|
if (!netpath)
|
||||||
if (!network_pathname)
|
|
||||||
return 0;
|
return 0;
|
||||||
dwr(MSG_DEBUG,"Connecting to service at: %s\n", network_pathname);
|
dwr(MSG_DEBUG,"Connecting to service at: %s\n", netpath);
|
||||||
/* Hook/intercept Posix net API symbols */
|
/* Hook/intercept Posix net API symbols */
|
||||||
rpc_mutex_init();
|
rpc_mutex_init();
|
||||||
}
|
}
|
||||||
@ -194,6 +193,14 @@ int socket(SOCKET_SIG)
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(flags & SOCK_DGRAM) {
|
||||||
|
fprintf(stderr, "socket(): DGRAM, passing through\n");
|
||||||
|
return realsocket(socket_family, socket_type, protocol);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
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){
|
||||||
@ -219,7 +226,7 @@ int socket(SOCKET_SIG)
|
|||||||
rpc_st.protocol = protocol;
|
rpc_st.protocol = protocol;
|
||||||
rpc_st.__tid = syscall(SYS_gettid);
|
rpc_st.__tid = syscall(SYS_gettid);
|
||||||
/* -1 is passed since we we're generating the new socket in this call */
|
/* -1 is passed since we we're generating the new socket in this call */
|
||||||
return rpc_send_command(RPC_SOCKET, -1, &rpc_st, sizeof(struct socket_st));
|
return rpc_send_command(netpath, RPC_SOCKET, -1, &rpc_st, sizeof(struct socket_st));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
@ -233,9 +240,42 @@ int connect(CONNECT_SIG)
|
|||||||
if (!set_up_intercept())
|
if (!set_up_intercept())
|
||||||
return realconnect(__fd, __addr, __len);
|
return realconnect(__fd, __addr, __len);
|
||||||
|
|
||||||
dwr(MSG_DEBUG,"connect(%d):\n", __fd);
|
/*
|
||||||
|
int opt;
|
||||||
|
socklen_t opt_len;
|
||||||
|
realgetsockopt(__fd, SOL_SOCKET, SO_TYPE, (void *) &opt, &opt_len);
|
||||||
|
|
||||||
|
if(opt & SOCK_DGRAM)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "connect(): DGRAM, passing through.\n");
|
||||||
|
return realconnect(__fd, __addr, __len);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
struct sockaddr_in *connaddr;
|
struct sockaddr_in *connaddr;
|
||||||
connaddr = (struct sockaddr_in *) __addr;
|
connaddr = (struct sockaddr_in *)__addr;
|
||||||
|
|
||||||
|
if(__addr->sa_family == AF_LOCAL || __addr->sa_family == AF_UNIX) {
|
||||||
|
struct sockaddr_storage storage;
|
||||||
|
memcpy(&storage, __addr, __len);
|
||||||
|
struct sockaddr_un *s_un = (struct sockaddr_un*)&storage;
|
||||||
|
fprintf(stderr, "connect(): address = %s\n", s_un->sun_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = connaddr->sin_port;
|
||||||
|
int ip = connaddr->sin_addr.s_addr;
|
||||||
|
unsigned char d[4];
|
||||||
|
d[0] = ip & 0xFF;
|
||||||
|
d[1] = (ip >> 8) & 0xFF;
|
||||||
|
d[2] = (ip >> 16) & 0xFF;
|
||||||
|
d[3] = (ip >> 24) & 0xFF;
|
||||||
|
dwr(MSG_DEBUG,"connect(): %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], ntohs(port));
|
||||||
|
|
||||||
|
|
||||||
|
if (!set_up_intercept())
|
||||||
|
return realconnect(__fd, __addr, __len);
|
||||||
|
|
||||||
|
dwr(MSG_DEBUG,"connect(%d):\n", __fd);
|
||||||
/* 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;
|
||||||
@ -261,8 +301,7 @@ int connect(CONNECT_SIG)
|
|||||||
|| connaddr->sin_family == PF_NETLINK
|
|| connaddr->sin_family == PF_NETLINK
|
||||||
|| connaddr->sin_family == AF_NETLINK
|
|| connaddr->sin_family == AF_NETLINK
|
||||||
|| connaddr->sin_family == AF_UNIX)) {
|
|| connaddr->sin_family == AF_UNIX)) {
|
||||||
int err = realconnect(__fd, __addr, __len);
|
return realconnect(__fd, __addr, __len);
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
/* Assemble and send RPC */
|
/* Assemble and send RPC */
|
||||||
struct connect_st rpc_st;
|
struct connect_st rpc_st;
|
||||||
@ -270,7 +309,7 @@ int connect(CONNECT_SIG)
|
|||||||
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));
|
||||||
return rpc_send_command(RPC_CONNECT, __fd, &rpc_st, sizeof(struct connect_st));
|
return rpc_send_command(netpath, RPC_CONNECT, __fd, &rpc_st, sizeof(struct connect_st));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
@ -325,7 +364,7 @@ int bind(BIND_SIG)
|
|||||||
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));
|
||||||
return rpc_send_command(RPC_BIND, sockfd, &rpc_st, sizeof(struct bind_st));
|
return rpc_send_command(netpath, RPC_BIND, sockfd, &rpc_st, sizeof(struct bind_st));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
@ -398,10 +437,6 @@ int accept(ACCEPT_SIG)
|
|||||||
if(addr)
|
if(addr)
|
||||||
addr->sa_family = AF_INET;
|
addr->sa_family = AF_INET;
|
||||||
|
|
||||||
/* 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
|
|
||||||
in an accept loop */
|
|
||||||
//fcntl(sockfd, F_SETFL, SOCK_NONBLOCK);
|
|
||||||
int new_fd = get_new_fd(sockfd);
|
int new_fd = get_new_fd(sockfd);
|
||||||
if(new_fd > 0) {
|
if(new_fd > 0) {
|
||||||
errno = ERR_OK;
|
errno = ERR_OK;
|
||||||
@ -452,7 +487,7 @@ int listen(LISTEN_SIG)
|
|||||||
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);
|
||||||
return rpc_send_command(RPC_LISTEN, sockfd, &rpc_st, sizeof(struct listen_st));
|
return rpc_send_command(netpath, RPC_LISTEN, sockfd, &rpc_st, sizeof(struct listen_st));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
@ -490,7 +525,7 @@ int getsockname(GETSOCKNAME_SIG)
|
|||||||
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));
|
||||||
int rpcfd = rpc_send_command(RPC_GETSOCKNAME, sockfd, &rpc_st, sizeof(struct getsockname_st));
|
int rpcfd = rpc_send_command(netpath, RPC_GETSOCKNAME, sockfd, &rpc_st, sizeof(struct getsockname_st));
|
||||||
/* 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));
|
||||||
|
@ -63,15 +63,6 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Gets the process/path name associated with a pid
|
|
||||||
static void get_path_from_pid(char* dest, int pid)
|
|
||||||
{
|
|
||||||
char ppath[80];
|
|
||||||
sprintf(ppath, "/proc/%d/exe", pid);
|
|
||||||
if (readlink (ppath, dest, 80) != -1){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static err_t tapif_init(struct netif *netif)
|
static err_t tapif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
// Actual init functionality is in addIp() of tap
|
// Actual init functionality is in addIp() of tap
|
||||||
@ -438,10 +429,12 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
|
|||||||
if(conn) {
|
if(conn) {
|
||||||
if(!conn->pcb)
|
if(!conn->pcb)
|
||||||
return;
|
return;
|
||||||
|
// TODO: Removed to address double-free segfault when killing a python simple server
|
||||||
|
|
||||||
// tell LWIP to close the associated PCB
|
// tell LWIP to close the associated PCB
|
||||||
if(conn->pcb->state != CLOSED && lwipstack->_tcp_close(conn->pcb) != ERR_OK) {
|
//if(conn->pcb->state != CLOSED && lwipstack->_tcp_close(conn->pcb) != ERR_OK) {
|
||||||
dwr(MSG_ERROR," closeConnection(): Error while calling tcp_close()\n");
|
// dwr(MSG_ERROR," closeConnection(): Error while calling tcp_close()\n");
|
||||||
}
|
//}
|
||||||
// remove from connection list
|
// remove from connection list
|
||||||
for(size_t i=0; i<tcp_connections.size(); i++) {
|
for(size_t i=0; i<tcp_connections.size(); i++) {
|
||||||
if(tcp_connections[i]->sock == sock){
|
if(tcp_connections[i]->sock == sock){
|
||||||
@ -478,7 +471,7 @@ void NetconEthernetTap::phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void *
|
|||||||
|
|
||||||
/* Unpacks the buffer from an RPC command */
|
/* Unpacks the buffer from an RPC command */
|
||||||
void NetconEthernetTap::unload_rpc(void *data, pid_t &pid, pid_t &tid,
|
void NetconEthernetTap::unload_rpc(void *data, pid_t &pid, pid_t &tid,
|
||||||
int &rpc_count, char (timestamp[20]), char (magic[sizeof(uint64_t)]), char &cmd, void* &payload)
|
int &rpc_count, char (timestamp[20]), char (CANARY[sizeof(uint64_t)]), char &cmd, void* &payload)
|
||||||
{
|
{
|
||||||
unsigned char *buf = (unsigned char*)data;
|
unsigned char *buf = (unsigned char*)data;
|
||||||
memcpy(&pid, &buf[IDX_PID], sizeof(pid_t));
|
memcpy(&pid, &buf[IDX_PID], sizeof(pid_t));
|
||||||
@ -486,7 +479,7 @@ void NetconEthernetTap::unload_rpc(void *data, pid_t &pid, pid_t &tid,
|
|||||||
memcpy(&rpc_count, &buf[IDX_COUNT], sizeof(int));
|
memcpy(&rpc_count, &buf[IDX_COUNT], sizeof(int));
|
||||||
memcpy(timestamp, &buf[IDX_TIME], 20);
|
memcpy(timestamp, &buf[IDX_TIME], 20);
|
||||||
memcpy(&cmd, &buf[IDX_PAYLOAD], sizeof(char));
|
memcpy(&cmd, &buf[IDX_PAYLOAD], sizeof(char));
|
||||||
memcpy(magic, &buf[IDX_PAYLOAD+1], MAGIC_SIZE);
|
memcpy(CANARY, &buf[IDX_PAYLOAD+1], CANARY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -494,14 +487,14 @@ void NetconEthernetTap::unload_rpc(void *data, pid_t &pid, pid_t &tid,
|
|||||||
*/
|
*/
|
||||||
void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
||||||
{
|
{
|
||||||
uint64_t magic_num;
|
uint64_t CANARY_num;
|
||||||
pid_t pid, tid;
|
pid_t pid, tid;
|
||||||
int rpc_count;
|
int rpc_count;
|
||||||
char cmd, timestamp[20], magic[MAGIC_SIZE];
|
char cmd, timestamp[20], CANARY[CANARY_SIZE];
|
||||||
void *payload;
|
void *payload;
|
||||||
unsigned char *buf = (unsigned char*)data;
|
unsigned char *buf = (unsigned char*)data;
|
||||||
std::pair<PhySocket*, void*> sockdata;
|
std::pair<PhySocket*, void*> sockdata;
|
||||||
PhySocket *streamsock, *rpcsock;
|
PhySocket *rpcsock;
|
||||||
bool found_job = false, detected_rpc = false;
|
bool found_job = false, detected_rpc = false;
|
||||||
TcpConnection *conn;
|
TcpConnection *conn;
|
||||||
int wlen = len;
|
int wlen = len;
|
||||||
@ -515,8 +508,8 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
detected_rpc = true;
|
detected_rpc = true;
|
||||||
}
|
}
|
||||||
if(detected_rpc) {
|
if(detected_rpc) {
|
||||||
unload_rpc(data, pid, tid, rpc_count, timestamp, magic, cmd, payload);
|
unload_rpc(data, pid, tid, rpc_count, timestamp, CANARY, cmd, payload);
|
||||||
memcpy(&magic_num, magic, MAGIC_SIZE);
|
memcpy(&CANARY_num, CANARY, CANARY_SIZE);
|
||||||
dwr(MSG_DEBUG," <%x> RPC: (pid=%d, tid=%d, rpc_count=%d, timestamp=%s, cmd=%d)\n", sock, pid, tid, rpc_count, timestamp, cmd);
|
dwr(MSG_DEBUG," <%x> RPC: (pid=%d, tid=%d, rpc_count=%d, timestamp=%s, cmd=%d)\n", sock, pid, tid, rpc_count, timestamp, cmd);
|
||||||
if(cmd == RPC_SOCKET) {
|
if(cmd == RPC_SOCKET) {
|
||||||
dwr(MSG_DEBUG," <%x> RPC_SOCKET\n", sock);
|
dwr(MSG_DEBUG," <%x> RPC_SOCKET\n", sock);
|
||||||
@ -530,7 +523,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // All RPCs other than RPC_SOCKET
|
else { // All RPCs other than RPC_SOCKET
|
||||||
jobmap[magic_num] = std::make_pair<PhySocket*, void*>(sock, data);
|
jobmap[CANARY_num] = std::make_pair<PhySocket*, void*>(sock, data);
|
||||||
}
|
}
|
||||||
write(_phy.getDescriptor(sock), "z", 1); // RPC ACK byte to maintain RPC->Stream order
|
write(_phy.getDescriptor(sock), "z", 1); // RPC ACK byte to maintain RPC->Stream order
|
||||||
}
|
}
|
||||||
@ -541,19 +534,19 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
char padding[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
|
char padding[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
|
||||||
dwr(MSG_DEBUG," <%x> stream data, len = %d\n", sock, len);
|
dwr(MSG_DEBUG," <%x> stream data, len = %d\n", sock, len);
|
||||||
// Look for padding
|
// Look for padding
|
||||||
std::string padding_pattern(padding, padding+MAGIC_PADDING_SIZE);
|
std::string padding_pattern(padding, padding+CANARY_PADDING_SIZE);
|
||||||
std::string buffer(buf, buf + len);
|
std::string buffer(buf, buf + len);
|
||||||
padding_pos = buffer.find(padding_pattern);
|
padding_pos = buffer.find(padding_pattern);
|
||||||
token_pos = padding_pos-MAGIC_SIZE;
|
token_pos = padding_pos-CANARY_SIZE;
|
||||||
dwr(MSG_DEBUG, " <%x> padding_pos = %d\n", sock, padding_pos);
|
dwr(MSG_DEBUG, " <%x> padding_pos = %d\n", sock, padding_pos);
|
||||||
// Grab token, next we'll use it to look up an RPC job
|
// Grab token, next we'll use it to look up an RPC job
|
||||||
if(token_pos > -1) {
|
if(token_pos > -1) {
|
||||||
memcpy(&magic_num, buf+token_pos, MAGIC_SIZE);
|
memcpy(&CANARY_num, buf+token_pos, CANARY_SIZE);
|
||||||
if(magic_num != 0) { // TODO: Added to address magic_num==0 bug, last seeen 20160108
|
if(CANARY_num != 0) { // TODO: Added to address CANARY_num==0 bug, last seeen 20160108
|
||||||
// Find job
|
// Find job
|
||||||
sockdata = jobmap[magic_num];
|
sockdata = jobmap[CANARY_num];
|
||||||
if(!sockdata.first) { // Stream before RPC
|
if(!sockdata.first) { // Stream before RPC
|
||||||
dwr(MSG_DEBUG," <%x> unable to locate job entry for %llu\n", sock, magic_num);
|
dwr(MSG_DEBUG," <%x> unable to locate job entry for %llu\n", sock, CANARY_num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -577,7 +570,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
// [TOKEN] + [DATA]
|
// [TOKEN] + [DATA]
|
||||||
if(len > TOKEN_SIZE && token_pos == 0) {
|
if(len > TOKEN_SIZE && token_pos == 0) {
|
||||||
wlen = len - TOKEN_SIZE;
|
wlen = len - TOKEN_SIZE;
|
||||||
data_start = padding_pos+MAGIC_PADDING_SIZE;
|
data_start = padding_pos+CANARY_PADDING_SIZE;
|
||||||
memcpy((&conn->buf)+conn->idx, buf+data_start, wlen);
|
memcpy((&conn->buf)+conn->idx, buf+data_start, wlen);
|
||||||
}
|
}
|
||||||
// [DATA] + [TOKEN]
|
// [DATA] + [TOKEN]
|
||||||
@ -590,9 +583,9 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
if(len > TOKEN_SIZE && token_pos > 0 && len > (token_pos + TOKEN_SIZE)) {
|
if(len > TOKEN_SIZE && token_pos > 0 && len > (token_pos + TOKEN_SIZE)) {
|
||||||
wlen = len - TOKEN_SIZE;
|
wlen = len - TOKEN_SIZE;
|
||||||
data_start = 0;
|
data_start = 0;
|
||||||
data_end = padding_pos-MAGIC_SIZE;
|
data_end = padding_pos-CANARY_SIZE;
|
||||||
memcpy((&conn->buf)+conn->idx, buf+data_start, (data_end-data_start)+1);
|
memcpy((&conn->buf)+conn->idx, buf+data_start, (data_end-data_start)+1);
|
||||||
memcpy((&conn->buf)+conn->idx, buf+(padding_pos+MAGIC_PADDING_SIZE), len-(token_pos+TOKEN_SIZE));
|
memcpy((&conn->buf)+conn->idx, buf+(padding_pos+CANARY_PADDING_SIZE), len-(token_pos+TOKEN_SIZE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,7 +607,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
// Process RPC if we have a corresponding jobmap entry
|
// Process RPC if we have a corresponding jobmap entry
|
||||||
if(found_job) {
|
if(found_job) {
|
||||||
conn = getConnection(sock);
|
conn = getConnection(sock);
|
||||||
unload_rpc(buf, pid, tid, rpc_count, timestamp, magic, cmd, payload);
|
unload_rpc(buf, pid, tid, rpc_count, timestamp, CANARY, cmd, payload);
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case RPC_BIND:
|
case RPC_BIND:
|
||||||
dwr(MSG_DEBUG," <%x> RPC_BIND\n", sock);
|
dwr(MSG_DEBUG," <%x> RPC_BIND\n", sock);
|
||||||
@ -644,7 +637,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
closeConnection(sockdata.first); // close RPC after sending retval, no longer needed
|
closeConnection(sockdata.first); // close RPC after sending retval, no longer needed
|
||||||
jobmap.erase(magic_num);
|
jobmap.erase(CANARY_num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -973,7 +966,7 @@ void NetconEthernetTap::handle_getsockname(PhySocket *sock, PhySocket *rpcsock,
|
|||||||
memset(&retmsg, 0, sizeof(retmsg));
|
memset(&retmsg, 0, sizeof(retmsg));
|
||||||
if ((conn)&&(conn->addr))
|
if ((conn)&&(conn->addr))
|
||||||
memcpy(&retmsg, conn->addr, sizeof(struct sockaddr_storage));
|
memcpy(&retmsg, conn->addr, sizeof(struct sockaddr_storage));
|
||||||
int n = write(_phy.getDescriptor(rpcsock), &retmsg, sizeof(struct sockaddr_storage));
|
write(_phy.getDescriptor(rpcsock), &retmsg, sizeof(struct sockaddr_storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
68
netcon/RPC.c
68
netcon/RPC.c
@ -6,16 +6,21 @@
|
|||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include "RPC.h"
|
#include "RPC.h"
|
||||||
|
|
||||||
#define RPC_FD 1023
|
|
||||||
#define SERVICE_CONNECT_ATTEMPTS 30
|
#define SERVICE_CONNECT_ATTEMPTS 30
|
||||||
|
|
||||||
static int instance_count;
|
#define CONNECT_SIG int __fd, const struct sockaddr * __addr, socklen_t __len
|
||||||
|
#define SOCKET_SIG int socket_family, int socket_type, int protocol
|
||||||
|
|
||||||
|
static int (*realconnect)(CONNECT_SIG) = 0;
|
||||||
|
static int (*realsocket)(SOCKET_SIG) = 0;
|
||||||
|
|
||||||
static int rpc_count;
|
static int rpc_count;
|
||||||
|
|
||||||
static pthread_mutex_t lock;
|
static pthread_mutex_t lock;
|
||||||
@ -63,30 +68,40 @@ int get_retval(int rpc_sock)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int load_symbols_rpc()
|
||||||
|
{
|
||||||
|
#ifdef NETCON_INTERCEPT
|
||||||
|
realsocket = dlsym(RTLD_NEXT, "socket");
|
||||||
|
realconnect = dlsym(RTLD_NEXT, "connect");
|
||||||
|
if(!realconnect || !realsocket)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int rpc_join(const char * sockname)
|
int rpc_join(const char * sockname)
|
||||||
{
|
{
|
||||||
|
if(!load_symbols_rpc())
|
||||||
|
return -1;
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
int conn_err = -1, attempts = 0;
|
int conn_err = -1, attempts = 0;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);
|
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);
|
||||||
|
|
||||||
int sock;
|
int sock;
|
||||||
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
if((sock = realsocket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
||||||
fprintf(stderr, "Error while creating RPC socket\n");
|
fprintf(stderr, "Error while creating RPC socket\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while((conn_err != 0) && (attempts < SERVICE_CONNECT_ATTEMPTS)){
|
while((conn_err != 0) && (attempts < SERVICE_CONNECT_ATTEMPTS)){
|
||||||
if((conn_err = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
if((conn_err = realconnect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
||||||
fprintf(stderr, "Error while connecting to RPC socket. Re-attempting...\n");
|
fprintf(stderr, "Error while connecting to RPC socket. Re-attempting...\n");
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
//int newfd = dup2(sock, RPC_FD-instance_count);
|
|
||||||
//close(sock);
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
|
||||||
attempts++;
|
attempts++;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -95,36 +110,24 @@ int rpc_join(const char * sockname)
|
|||||||
/*
|
/*
|
||||||
* Send a command to the service
|
* Send a command to the service
|
||||||
*/
|
*/
|
||||||
int rpc_send_command(int cmd, int forfd, void *data, int len)
|
int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
char c, padding[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
|
char c, padding[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
|
||||||
char cmdbuf[BUF_SZ], magic[TOKEN_SIZE], metabuf[BUF_SZ];
|
char cmdbuf[BUF_SZ], CANARY[TOKEN_SIZE], metabuf[BUF_SZ];
|
||||||
memcpy(magic+MAGIC_SIZE, padding, TOKEN_SIZE);
|
memcpy(CANARY+CANARY_SIZE, padding, TOKEN_SIZE);
|
||||||
uint64_t magic_num;
|
uint64_t canary_num;
|
||||||
|
|
||||||
// ephemeral RPC socket used only for this command
|
// ephemeral RPC socket used only for this command
|
||||||
int rpc_sock = rpc_join("/root/dev/ztest/nc_e5cd7a9e1c3511dd");
|
int rpc_sock = rpc_join(path);
|
||||||
// Generate token
|
// Generate token
|
||||||
int fdrand = open("/dev/urandom", O_RDONLY);
|
int fdrand = open("/dev/urandom", O_RDONLY);
|
||||||
read(fdrand, &magic, MAGIC_SIZE);
|
read(fdrand, &CANARY, CANARY_SIZE);
|
||||||
memcpy(&magic_num, magic, MAGIC_SIZE);
|
memcpy(&canary_num, CANARY, CANARY_SIZE);
|
||||||
cmdbuf[CMD_ID_IDX] = cmd;
|
cmdbuf[CMD_ID_IDX] = cmd;
|
||||||
memcpy(&cmdbuf[MAGIC_IDX], &magic_num, MAGIC_SIZE);
|
memcpy(&cmdbuf[CANARY_IDX], &canary_num, CANARY_SIZE);
|
||||||
memcpy(&cmdbuf[STRUCT_IDX], data, len);
|
memcpy(&cmdbuf[STRUCT_IDX], data, len);
|
||||||
|
|
||||||
// Format: [sig_byte] + [cmd_id] + [magic] + [meta] + [payload]
|
|
||||||
|
|
||||||
#ifdef VERBOSE
|
#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);
|
memset(metabuf, 0, BUF_SZ);
|
||||||
pid_t pid = syscall(SYS_getpid);
|
pid_t pid = syscall(SYS_getpid);
|
||||||
pid_t tid = syscall(SYS_gettid);
|
pid_t tid = syscall(SYS_gettid);
|
||||||
@ -141,7 +144,7 @@ int rpc_send_command(int cmd, int forfd, void *data, int len)
|
|||||||
memcpy(&metabuf[IDX_TIME], ×tring, 20 ); /* timestamp */
|
memcpy(&metabuf[IDX_TIME], ×tring, 20 ); /* timestamp */
|
||||||
#endif
|
#endif
|
||||||
/* Combine command flag+payload with RPC metadata */
|
/* Combine command flag+payload with RPC metadata */
|
||||||
memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len + 1 + MAGIC_SIZE);
|
memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len + 1 + CANARY_SIZE);
|
||||||
|
|
||||||
// Write RPC
|
// Write RPC
|
||||||
int n_write = write(rpc_sock, &metabuf, BUF_SZ);
|
int n_write = write(rpc_sock, &metabuf, BUF_SZ);
|
||||||
@ -152,7 +155,10 @@ int rpc_send_command(int cmd, int forfd, void *data, int len)
|
|||||||
// Write token to corresponding data stream
|
// Write token to corresponding data stream
|
||||||
read(rpc_sock, &c, 1);
|
read(rpc_sock, &c, 1);
|
||||||
if(c == 'z' && n_write > 0 && forfd > -1){
|
if(c == 'z' && n_write > 0 && forfd > -1){
|
||||||
int w = send(forfd, &magic, TOKEN_SIZE, 0);
|
if(send(forfd, &CANARY, TOKEN_SIZE, 0) < 0) {
|
||||||
|
fprintf(stderr,"unable to write canary to stream\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Process response from service
|
// Process response from service
|
||||||
int ret = ERR_OK;
|
int ret = ERR_OK;
|
||||||
|
27
netcon/RPC.h
27
netcon/RPC.h
@ -3,29 +3,28 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MAGIC_SIZE sizeof(uint64_t)
|
#define CANARY_SIZE sizeof(uint64_t)
|
||||||
#define MAGIC_PADDING_SIZE 12
|
#define CANARY_PADDING_SIZE 12
|
||||||
#define TOKEN_SIZE MAGIC_SIZE+MAGIC_PADDING_SIZE
|
#define TOKEN_SIZE CANARY_SIZE+CANARY_PADDING_SIZE
|
||||||
|
|
||||||
#define RPC_PHRASE "zerotier\0"
|
#define RPC_PHRASE "zerotier\0"
|
||||||
#define RPC_PHRASE_SIZE 9
|
#define RPC_PHRASE_SIZE 9
|
||||||
// 1st section
|
// 1st RPC section (metdata)
|
||||||
#define IDX_SIGNAL_PHRASE 0
|
#define IDX_SIGNAL_PHRASE 0
|
||||||
#define IDX_PID IDX_SIGNAL_PHRASE + RPC_PHRASE_SIZE
|
#define IDX_PID IDX_SIGNAL_PHRASE + RPC_PHRASE_SIZE
|
||||||
#define IDX_TID sizeof(pid_t) + IDX_PID
|
#define IDX_TID sizeof(pid_t) + IDX_PID
|
||||||
#define IDX_COUNT IDX_TID + sizeof(pid_t)
|
#define IDX_COUNT IDX_TID + sizeof(pid_t)
|
||||||
#define IDX_TIME IDX_COUNT + sizeof(int)
|
#define IDX_TIME IDX_COUNT + sizeof(int)
|
||||||
#define IDX_PAYLOAD IDX_TIME + 20 /* 20 being the length of the timestamp string */
|
#define IDX_PAYLOAD IDX_TIME + 20 /* 20 being the length of the timestamp string */
|
||||||
|
// 2nd RPC section (payload and canary)
|
||||||
|
#define CMD_ID_IDX 0
|
||||||
|
#define CANARY_IDX 1
|
||||||
|
#define STRUCT_IDX CANARY_IDX+CANARY_SIZE
|
||||||
|
|
||||||
// 2nd section
|
#define BUF_SZ 256
|
||||||
#define CMD_ID_IDX 0
|
#define PAYLOAD_SZ 223 /* BUF_SZ-IDX_PAYLOAD */
|
||||||
#define MAGIC_IDX 1
|
|
||||||
#define STRUCT_IDX MAGIC_IDX+MAGIC_SIZE
|
|
||||||
|
|
||||||
#define BUF_SZ 256
|
#define ERR_OK 0
|
||||||
#define PAYLOAD_SZ 223 /* BUF_SZ-IDX_PAYLOAD */
|
|
||||||
|
|
||||||
#define ERR_OK 0
|
|
||||||
|
|
||||||
/* RPC codes */
|
/* RPC codes */
|
||||||
#define RPC_UNDEFINED 0
|
#define RPC_UNDEFINED 0
|
||||||
@ -54,8 +53,10 @@ extern "C" {
|
|||||||
|
|
||||||
int get_retval(int);
|
int get_retval(int);
|
||||||
|
|
||||||
|
//#ifdef NETCON_INTERCEPT
|
||||||
int rpc_join(const char * sockname);
|
int rpc_join(const char * sockname);
|
||||||
int rpc_send_command(int cmd, int forfd, void *data, int len);
|
int rpc_send_command(char *path, int cmd, int forfd, void *data, int len);
|
||||||
|
//#endif
|
||||||
|
|
||||||
int get_new_fd(int sock);
|
int get_new_fd(int sock);
|
||||||
ssize_t sock_fd_write(int sock, int fd);
|
ssize_t sock_fd_write(int sock, int fd);
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#ifndef _COMMON_H
|
#ifndef _COMMON_H
|
||||||
#define _COMMON_H 1
|
#define _COMMON_H 1
|
||||||
|
|
||||||
#define DEBUG_LEVEL 0
|
#define DEBUG_LEVEL 3
|
||||||
|
|
||||||
#define MSG_WARNING 4
|
#define MSG_WARNING 4
|
||||||
#define MSG_ERROR 1 // Errors
|
#define MSG_ERROR 1 // Errors
|
||||||
|
Loading…
Reference in New Issue
Block a user