mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Added support for MongoDB (server side)
This commit is contained in:
parent
21889305e0
commit
c8f27da294
6 changed files with 125 additions and 73 deletions
|
@ -170,6 +170,7 @@ void send_command(int rpc_fd, char *cmd)
|
||||||
*/
|
*/
|
||||||
int get_retval()
|
int get_retval()
|
||||||
{
|
{
|
||||||
|
dwr("get_retval()\n");
|
||||||
if(fdret_sock >= 0) {
|
if(fdret_sock >= 0) {
|
||||||
int retval;
|
int retval;
|
||||||
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
|
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
|
||||||
|
@ -186,6 +187,21 @@ int get_retval()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
that the service uses. We don't want to keep state in the intercept, so
|
||||||
|
we simply ask the service via an RPC */
|
||||||
|
int is_mapped_to_service(int sockfd)
|
||||||
|
{
|
||||||
|
dwr("is_mapped_to_service()\n");
|
||||||
|
char cmd[BUF_SZ];
|
||||||
|
memset(cmd, '\0', BUF_SZ);
|
||||||
|
cmd[0] = RPC_MAP_REQ;
|
||||||
|
memcpy(&cmd[1], &sockfd, sizeof(sockfd));
|
||||||
|
send_command(fdret_sock, cmd);
|
||||||
|
return get_retval();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
---------- Unix-domain socket lazy initializer (for fd-transfers)--------------
|
---------- Unix-domain socket lazy initializer (for fd-transfers)--------------
|
||||||
|
@ -194,6 +210,7 @@ int get_retval()
|
||||||
/* Sets up the connection pipes and sockets to the service */
|
/* Sets up the connection pipes and sockets to the service */
|
||||||
int init_service_connection()
|
int init_service_connection()
|
||||||
{
|
{
|
||||||
|
dwr("init_service_connection()\n");
|
||||||
if(!is_initialized) {
|
if(!is_initialized) {
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
int tfd = -1, attempts = 0, conn_err = -1;
|
int tfd = -1, attempts = 0, conn_err = -1;
|
||||||
|
@ -309,6 +326,7 @@ void set_up_intercept()
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
--------------------------------- setsockopt() ---------------------------------
|
--------------------------------- setsockopt() ---------------------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* int socket, int level, int option_name, const void *option_value, socklen_t option_len */
|
/* int socket, int level, int option_name, const void *option_value, socklen_t option_len */
|
||||||
int setsockopt(SETSOCKOPT_SIG)
|
int setsockopt(SETSOCKOPT_SIG)
|
||||||
{
|
{
|
||||||
|
@ -332,8 +350,8 @@ int setsockopt(SETSOCKOPT_SIG)
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
--------------------------------- getsockopt() ---------------------------------
|
--------------------------------- getsockopt() ---------------------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
/* int sockfd, int level, int optname, void *optval, socklen_t *optlen */
|
|
||||||
|
|
||||||
|
/* int sockfd, int level, int optname, void *optval, socklen_t *optlen */
|
||||||
int getsockopt(GETSOCKOPT_SIG)
|
int getsockopt(GETSOCKOPT_SIG)
|
||||||
{
|
{
|
||||||
dwr("setsockopt(%d)\n", sockfd);
|
dwr("setsockopt(%d)\n", sockfd);
|
||||||
|
@ -359,7 +377,6 @@ int getsockopt(GETSOCKOPT_SIG)
|
||||||
|
|
||||||
/* int socket_family, int socket_type, int protocol
|
/* int socket_family, int socket_type, int protocol
|
||||||
socket() intercept function */
|
socket() intercept function */
|
||||||
|
|
||||||
int socket(SOCKET_SIG)
|
int socket(SOCKET_SIG)
|
||||||
{
|
{
|
||||||
dwr("socket()*:\n");
|
dwr("socket()*:\n");
|
||||||
|
@ -407,7 +424,6 @@ int socket(SOCKET_SIG)
|
||||||
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("realsocket, err = %d\n", err);
|
dwr("realsocket, err = %d\n", err);
|
||||||
handle_error("socket", "", err);
|
handle_error("socket", "", err);
|
||||||
|
@ -554,7 +570,7 @@ int connect(CONNECT_SIG)
|
||||||
fd_set *exceptfds, struct timeval *timeout */
|
fd_set *exceptfds, struct timeval *timeout */
|
||||||
int select(SELECT_SIG)
|
int select(SELECT_SIG)
|
||||||
{
|
{
|
||||||
//dwr("select()*:\n");
|
//dwr("select():\n");
|
||||||
return realselect(n, readfds, writefds, exceptfds, timeout);
|
return realselect(n, readfds, writefds, exceptfds, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,17 +610,14 @@ int bind(BIND_SIG)
|
||||||
struct sockaddr_in *connaddr;
|
struct sockaddr_in *connaddr;
|
||||||
connaddr = (struct sockaddr_in *)addr;
|
connaddr = (struct sockaddr_in *)addr;
|
||||||
|
|
||||||
if (addr != NULL && (connaddr->sin_family == AF_LOCAL
|
if(connaddr->sin_family == AF_LOCAL
|
||||||
|| 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 = realbind(sockfd, addr, addrlen);
|
||||||
if(realbind == NULL) {
|
dwr("realbind, err = %d\n", err);
|
||||||
handle_error("bind", "Unresolved symbol [bind]", -1);
|
return err;
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
return(realbind(sockfd, addr, addrlen));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble and send RPC */
|
/* Assemble and send RPC */
|
||||||
char cmd[BUF_SZ];
|
char cmd[BUF_SZ];
|
||||||
struct bind_st rpc_st;
|
struct bind_st rpc_st;
|
||||||
|
@ -767,6 +780,9 @@ int accept(ACCEPT_SIG)
|
||||||
int listen(LISTEN_SIG)
|
int listen(LISTEN_SIG)
|
||||||
{
|
{
|
||||||
dwr("listen(%d):\n", sockfd);
|
dwr("listen(%d):\n", sockfd);
|
||||||
|
int sock_type;
|
||||||
|
socklen_t sock_type_len = sizeof(sock_type);
|
||||||
|
|
||||||
#ifdef CHECKS
|
#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) {
|
||||||
|
@ -775,8 +791,6 @@ int listen(LISTEN_SIG)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Check that it is a socket */
|
/* 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) {
|
if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
|
||||||
errno = ENOTSOCK;
|
errno = ENOTSOCK;
|
||||||
handle_error("listen", "ENOTSOCK", -1);
|
handle_error("listen", "ENOTSOCK", -1);
|
||||||
|
@ -794,6 +808,13 @@ int listen(LISTEN_SIG)
|
||||||
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
|
if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
|
||||||
return(reallisten(sockfd, backlog));
|
return(reallisten(sockfd, backlog));
|
||||||
|
|
||||||
|
if(!is_mapped_to_service(sockfd)) {
|
||||||
|
// We now know this socket is not one of our socketpairs
|
||||||
|
int err = reallisten(sockfd, backlog);
|
||||||
|
dwr("reallisten()=%d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Assemble and send RPC */
|
/* Assemble and send RPC */
|
||||||
char cmd[BUF_SZ];
|
char cmd[BUF_SZ];
|
||||||
memset(cmd, '\0', BUF_SZ);
|
memset(cmd, '\0', BUF_SZ);
|
||||||
|
@ -811,9 +832,6 @@ int listen(LISTEN_SIG)
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
-------------------------------------- clone()----------------------------------
|
-------------------------------------- clone()----------------------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
@ -849,7 +867,7 @@ int poll(POLL_SIG)
|
||||||
|
|
||||||
long syscall(SYSCALL_SIG)
|
long syscall(SYSCALL_SIG)
|
||||||
{
|
{
|
||||||
dwr("syscall():\n");
|
//dwr("syscall(%u, ...):\n", number);
|
||||||
va_list ap;
|
va_list ap;
|
||||||
uintptr_t a,b,c,d,e,f;
|
uintptr_t a,b,c,d,e,f;
|
||||||
va_start(ap, number);
|
va_start(ap, number);
|
||||||
|
|
|
@ -51,8 +51,9 @@
|
||||||
|
|
||||||
/* Administration RPC codes */
|
/* Administration RPC codes */
|
||||||
#define RPC_MAP 20 // Give the service the value we "see" for the new buffer fd
|
#define RPC_MAP 20 // Give the service the value we "see" for the new buffer fd
|
||||||
#define RPC_RETVAL 21 // not RPC per se, but something we should codify
|
#define RPC_MAP_REQ 21 // A call to determine whether an fd is mapped to the service
|
||||||
#define RPC_KILL_INTERCEPT 22 // Tells the service we need to shut down all connections
|
#define RPC_RETVAL 22 // not RPC per se, but something we should codify
|
||||||
|
#define RPC_KILL_INTERCEPT 23 // Tells the service we need to shut down all connections
|
||||||
|
|
||||||
/* Connection statuses */
|
/* Connection statuses */
|
||||||
#define UNSTARTED 0
|
#define UNSTARTED 0
|
||||||
|
|
|
@ -490,6 +490,10 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
||||||
fprintf(stderr, "RPC_MAP\n");
|
fprintf(stderr, "RPC_MAP\n");
|
||||||
handle_retval(sock, uptr, buf);
|
handle_retval(sock, uptr, buf);
|
||||||
break;
|
break;
|
||||||
|
case RPC_MAP_REQ:
|
||||||
|
fprintf(stderr, "RPC_MAP_REQ\n");
|
||||||
|
handle_map_request(sock, uptr, buf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -843,6 +847,29 @@ err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err
|
||||||
----------------------------- RPC Handler functions ----------------------------
|
----------------------------- RPC Handler functions ----------------------------
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Responds to a request from the [intercept] to determine whether a local socket is
|
||||||
|
mapped to this service. In other words, how do the intercept's overridden calls
|
||||||
|
tell the difference between regular AF_LOCAL sockets and one of our socketpairs
|
||||||
|
that is used to communicate over the network?
|
||||||
|
*/
|
||||||
|
void NetconEthernetTap::handle_map_request(PhySocket *sock, void **uptr, unsigned char* buf)
|
||||||
|
{
|
||||||
|
TcpConnection *conn = (TcpConnection*)*uptr;
|
||||||
|
int req_fd;
|
||||||
|
memcpy(&req_fd, &buf[1], sizeof(req_fd));
|
||||||
|
for(size_t i=0; i<tcp_connections.size(); i++) {
|
||||||
|
if(tcp_connections[i]->rpcSock == conn->rpcSock && tcp_connections[i]->perceived_fd == req_fd){
|
||||||
|
send_return_value(conn, 1, ERR_OK); // True
|
||||||
|
fprintf(stderr, " handle_map_request(their=%d): MAPPED (to %d)\n", req_fd,
|
||||||
|
_phy.getDescriptor(tcp_connections[i]->dataSock));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
send_return_value(conn, 0, ERR_OK); // False
|
||||||
|
fprintf(stderr, " handle_map_request(their=%d): NOT MAPPED\n", req_fd);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a return value (client's perceived fd) and completes a mapping
|
* Handles a return value (client's perceived fd) and completes a mapping
|
||||||
* so that we know what connection an RPC call should be associated with.
|
* so that we know what connection an RPC call should be associated with.
|
||||||
|
@ -944,7 +971,8 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||||
d[2] = (ip >> 16) & 0xFF;
|
d[2] = (ip >> 16) & 0xFF;
|
||||||
d[3] = (ip >> 24) & 0xFF;
|
d[3] = (ip >> 24) & 0xFF;
|
||||||
fprintf(stderr, " handle_bind(): error binding to %d.%d.%d.%d : %d\n", d[0],d[1],d[2],d[3], conn_port);
|
fprintf(stderr, " handle_bind(): error binding to %d.%d.%d.%d : %d\n", d[0],d[1],d[2],d[3], conn_port);
|
||||||
fprintf(stderr, "err = %d\n", err);
|
fprintf(stderr, " handle_bind(): err = %d\n", err);
|
||||||
|
|
||||||
if(err == ERR_USE)
|
if(err == ERR_USE)
|
||||||
send_return_value(conn, -1, EADDRINUSE);
|
send_return_value(conn, -1, EADDRINUSE);
|
||||||
if(err == ERR_MEM)
|
if(err == ERR_MEM)
|
||||||
|
@ -987,8 +1015,15 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
|
||||||
*/
|
*/
|
||||||
void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc)
|
void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, " handle_listen(their=%d):\n", listen_rpc->sockfd);
|
||||||
TcpConnection *conn = getConnectionByTheirFD(sock, listen_rpc->sockfd);
|
TcpConnection *conn = getConnectionByTheirFD(sock, listen_rpc->sockfd);
|
||||||
if(conn) {
|
if(!conn){
|
||||||
|
fprintf(stderr, " handle_listen(): unable to locate connection object\n");
|
||||||
|
// ? send_return_value(conn, -1, EBADF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, " handle_listen(our=%d -> their=%d)\n", _phy.getDescriptor(conn->dataSock), conn->perceived_fd);
|
||||||
|
|
||||||
if(conn->pcb->state == LISTEN) {
|
if(conn->pcb->state == LISTEN) {
|
||||||
fprintf(stderr, " handle_listen(): PCB is already in listening state.\n");
|
fprintf(stderr, " handle_listen(): PCB is already in listening state.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -1025,14 +1060,6 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/*
|
|
||||||
// We can't find a connection mapped to the socket fd provided
|
|
||||||
fprintf(stderr, "handle_listen(): can't locate connection for PCB\n");
|
|
||||||
send_return_value(conn, -1, EBADF);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handles an RPC to create a socket (LWIP PCB and associated socketpair)
|
* Handles an RPC to create a socket (LWIP PCB and associated socketpair)
|
||||||
|
@ -1067,7 +1094,7 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
|
||||||
int rpc_fd = _phy.getDescriptor(sock);
|
int rpc_fd = _phy.getDescriptor(sock);
|
||||||
struct tcp_pcb *newpcb = lwipstack->tcp_new();
|
struct tcp_pcb *newpcb = lwipstack->tcp_new();
|
||||||
|
|
||||||
fprintf(stderr, "handle_socket(): pcb=%x, (state == CLOSED) = %d\n", newpcb, (newpcb->state==CLOSED));
|
fprintf(stderr, " handle_socket(): pcb=%x\n", newpcb);
|
||||||
|
|
||||||
if(newpcb != NULL) {
|
if(newpcb != NULL) {
|
||||||
ZT_PHY_SOCKFD_TYPE fds[2];
|
ZT_PHY_SOCKFD_TYPE fds[2];
|
||||||
|
@ -1077,7 +1104,7 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "socketpair = {%d, %d}\n", fds[0], fds[1]);
|
fprintf(stderr, " handle_socket(): socketpair = {%d, %d}\n", fds[0], fds[1]);
|
||||||
TcpConnection *new_conn = new TcpConnection();
|
TcpConnection *new_conn = new TcpConnection();
|
||||||
new_conn->dataSock = _phy.wrapSocket(fds[0], new_conn);
|
new_conn->dataSock = _phy.wrapSocket(fds[0], new_conn);
|
||||||
*uptr = new_conn;
|
*uptr = new_conn;
|
||||||
|
@ -1201,7 +1228,7 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn
|
||||||
conn->pending=true;
|
conn->pending=true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "could not locate PCB based on their fd\n");
|
fprintf(stderr, " handle_connect(): could not locate PCB based on their fd\n");
|
||||||
send_return_value(conn, -1, EBADF);
|
send_return_value(conn, -1, EBADF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1266,7 +1293,6 @@ void NetconEthernetTap::handle_write(TcpConnection *conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
#endif // ZT_ENABLE_NETCON
|
#endif // ZT_ENABLE_NETCON
|
||||||
|
|
|
@ -106,6 +106,7 @@ private:
|
||||||
// RPC handlers (from NetconIntercept)
|
// RPC handlers (from NetconIntercept)
|
||||||
void handle_bind(PhySocket *sock, void **uptr, struct bind_st *bind_rpc);
|
void handle_bind(PhySocket *sock, void **uptr, struct bind_st *bind_rpc);
|
||||||
void handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc);
|
void handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc);
|
||||||
|
void handle_map_request(PhySocket *sock, void **uptr, unsigned char* buf);
|
||||||
void handle_retval(PhySocket *sock, void **uptr, unsigned char* buf);
|
void handle_retval(PhySocket *sock, void **uptr, unsigned char* buf);
|
||||||
void handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc);
|
void handle_socket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc);
|
||||||
void handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc);
|
void handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc);
|
||||||
|
|
|
@ -108,7 +108,7 @@ Network Containers have been tested with the following:
|
||||||
vsftpd [BROKEN as of 20151021] Server sends 500 when 220 is expected
|
vsftpd [BROKEN as of 20151021] Server sends 500 when 220 is expected
|
||||||
mysql [BROKEN as of 20151021]
|
mysql [BROKEN as of 20151021]
|
||||||
postresql [BROKEN as of 20151021]
|
postresql [BROKEN as of 20151021]
|
||||||
MongoDB [BROKEN as of 20151021]
|
MongoDB [ WORKS as of 20151021] Only basic connection tested, no DB operations yet
|
||||||
Redis-server [ WORKS as of 20151027]
|
Redis-server [ WORKS as of 20151027]
|
||||||
pure-ftpd [BROKEN as of 20151021] Socket operation on non-socket
|
pure-ftpd [BROKEN as of 20151021] Socket operation on non-socket
|
||||||
|
|
||||||
|
@ -125,6 +125,12 @@ To Test:
|
||||||
|
|
||||||
### Extended Version Notes
|
### Extended Version Notes
|
||||||
|
|
||||||
|
20151028 Added MongoDB support:
|
||||||
|
|
||||||
|
- Added logic (RPC_MAP_REQ) to check whether a given AF_LOCAL socket is mapped to anything
|
||||||
|
inside the service instance.
|
||||||
|
|
||||||
|
|
||||||
20151027 Added Redis-server support:
|
20151027 Added Redis-server support:
|
||||||
|
|
||||||
- Added extra logic to detect socket re-issuing and consequent service-side double mapping.
|
- Added extra logic to detect socket re-issuing and consequent service-side double mapping.
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue