refactor almost complete

This commit is contained in:
Joseph Henry 2015-09-10 20:02:13 -04:00
parent 8d82ac5cc8
commit 20beafedc5
8 changed files with 213 additions and 172 deletions

View file

@ -75,7 +75,7 @@ ifeq ($(ZT_DEBUG),1)
DEFS+=-DZT_TRACE DEFS+=-DZT_TRACE
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS) CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
CXXFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS) CXXFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
LDFLAGS= LDFLAGS=-ldl
STRIP=echo STRIP=echo
# The following line enables optimization for the crypto code, since # The following line enables optimization for the crypto code, since
# C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box! # C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box!
@ -85,7 +85,7 @@ else
CFLAGS+=-Wall -fPIE -fvisibility=hidden -pthread $(INCLUDES) -DNDEBUG $(DEFS) CFLAGS+=-Wall -fPIE -fvisibility=hidden -pthread $(INCLUDES) -DNDEBUG $(DEFS)
CXXFLAGS?=-O3 -fstack-protector CXXFLAGS?=-O3 -fstack-protector
CXXFLAGS+=-Wall -fPIE -fvisibility=hidden -fno-rtti -pthread $(INCLUDES) -DNDEBUG $(DEFS) CXXFLAGS+=-Wall -fPIE -fvisibility=hidden -fno-rtti -pthread $(INCLUDES) -DNDEBUG $(DEFS)
LDFLAGS=-pie -Wl,-z,relro,-z,now LDFLAGS=-ldl -pie -Wl,-z,relro,-z,now
STRIP=strip --strip-all STRIP=strip --strip-all
endif endif

View file

@ -175,6 +175,7 @@ struct shutdown_st
/* LWIP error beautification */ /* LWIP error beautification */
/*
const char *lwiperror(int n) const char *lwiperror(int n)
{ {
switch(n) switch(n)
@ -215,5 +216,6 @@ const char *lwiperror(int n)
return "UNKNOWN_RET_VAL"; return "UNKNOWN_RET_VAL";
} }
} }
*/
#endif #endif

View file

@ -29,6 +29,8 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <dlfcn.h>
#include "NetconEthernetTap.hpp" #include "NetconEthernetTap.hpp"
@ -43,7 +45,7 @@
#include "lwip/ip_frag.h" #include "lwip/ip_frag.h"
#include "LWIPStack.hpp" #include "LWIPStack.hpp"
#include "NetconService.h" #include "NetconService.hpp"
#include "Intercept.h" #include "Intercept.h"
#include "NetconUtilities.hpp" #include "NetconUtilities.hpp"
@ -114,6 +116,7 @@ bool NetconEthernetTap::addIp(const InetAddress &ip)
// TODO: alloc IP in LWIP // TODO: alloc IP in LWIP
//netif_set_addr(netif, ipaddr, netmask, gw); //netif_set_addr(netif, ipaddr, netmask, gw);
} }
return true; // TODO: what is exapected?
} }
bool NetconEthernetTap::removeIp(const InetAddress &ip) bool NetconEthernetTap::removeIp(const InetAddress &ip)
@ -194,7 +197,7 @@ NetconClient *NetconEthernetTap::getClientByPCB(struct tcp_pcb *pcb)
void NetconEthernetTap::closeClient(NetconClient *client) void NetconEthernetTap::closeClient(NetconClient *client)
{ {
// erase from clients vector // erase from clients vector
client->close(); client->closeClient();
} }
@ -219,7 +222,7 @@ void NetconEthernetTap::threadMain()
unsigned long since_etharp; unsigned long since_etharp;
struct timeval tv; struct timeval tv;
struct timeval tv_sel; //struct timeval tv_sel;
while (_run) { while (_run) {
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
@ -267,7 +270,7 @@ void NetconEthernetTap::phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void *
void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr) void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr)
{ {
((NetconClient*)*uptr)->close(); ((NetconClient*)*uptr)->closeClient();
} }
void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
@ -313,7 +316,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
handle_bind(client, &bind_rpc); handle_bind(client, &bind_rpc);
break; break;
case RPC_KILL_INTERCEPT: case RPC_KILL_INTERCEPT:
client->close(); client->closeClient();
break; break;
case RPC_CONNECT: case RPC_CONNECT:
struct connect_st connect_rpc; struct connect_st connect_rpc;
@ -361,22 +364,17 @@ int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
--------------------------------- LWIP callbacks ------------------------------- --------------------------------- LWIP callbacks -------------------------------
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *tpcb)
{
NetconConnection *c = getConnectionByPCB(tpcb); // TODO: make sure this works, if not, use arg to look up the connection
if(c)
handle_write(c);
return ERR_OK;
}
err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{ {
Larg *l = (Larg*)arg;
NetconConnection *c = l->tap->getConnectionByPCB(tpcb);
NetconEthernetTap *tap = l->tap;
int n; int n;
struct pbuf* q = p; struct pbuf* q = p;
NetconConnection *c = getConnectionByPCB(tpcb); // TODO: make sure this works, if not, use arg as "buf sock" int our_fd = tap->_phy.getDescriptor(c->sock);
int our_fd = _phy.getDescriptor(c->sock);
if(c) { if(c) {
//dwr(c->owner->tid, "nc_recved(%d)\n", (intptr_t)arg); //dwr(c->owner->tid, "nc_recved(%d)\n", (intptr_t)arg);
@ -386,47 +384,45 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf
return ERR_OK; // ? return ERR_OK; // ?
} }
if(p == NULL) { if(p == NULL) {
//dwr(c->owner->tid, "nc_recved() = %s\n", lwiperror(err));
if(c)
//dwr(c->owner->tid, "nc_recved()\n"); //dwr(c->owner->tid, "nc_recved()\n");
if(c) { if(c) {
//dwr(c->owner->tid, "closing connection\n"); //dwr(c->owner->tid, "closing connection\n");
nc_close(tpcb); nc_close(tpcb);
close(our_fd); /* TODO: Check logic */ close(our_fd); /* TODO: Check logic */
//nc_service->remove_connection(c); //nc_service->remove_connection(c);
c->owner->close(c); c->owner->closeConnection(c);
} }
else { else {
//dwr(-1, "can't locate connection via (arg)\n"); // can't locate connection via (arg)
} }
return err; return err;
} }
q = p; q = p;
while(p != NULL) { // Cycle through pbufs and write them to the socket while(p != NULL) { // Cycle through pbufs and write them to the socket
//dwr(c->owner->tid, "writing data to mapped sock (%d)\n", c->our_fd);
if(p->len <= 0) if(p->len <= 0)
break; // ? break; // ?
if((n = write(our_fd, p->payload, p->len)) > 0) { if((n = write(our_fd, p->payload, p->len)) > 0) {
if(n < p->len) { if(n < p->len) {
//dwr(c->owner->tid, "ERROR: unable to write entire pbuf to buffer\n"); // ERROR: unable to write entire pbuf to buffer
} }
lwipstack->tcp_recved(tpcb, n); tap->lwipstack->tcp_recved(tpcb, n);
} }
else { else {
//dwr(c->owner->tid, "ERROR: No data written to intercept buffer.\n"); // Error: No data written to intercept buffer
} }
p = p->next; p = p->next;
} }
lwipstack->pbuf_free(q); /* free pbufs */ tap->lwipstack->pbuf_free(q); // free pbufs
return ERR_OK; return ERR_OK;
} }
void NetconEthernetTap::nc_err(void *arg, err_t err) void NetconEthernetTap::nc_err(void *arg, err_t err)
{ {
NetconConnection *c = getConnectionByThisFD((intptr)arg); Larg *l = (Larg*)arg;
NetconEthernetTap *tap = l->tap;
NetconConnection *c = tap->getConnectionByThisFD(tap->_phy.getDescriptor(l->sock));
if(c) { if(c) {
//nc_service->remove_connection(c); c->owner->closeConnection(c);
c->owner->close(c);
//tcp_close(c->pcb); //tcp_close(c->pcb);
} }
else { else {
@ -436,13 +432,14 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
void NetconEthernetTap::nc_close(struct tcp_pcb* tpcb) void NetconEthernetTap::nc_close(struct tcp_pcb* tpcb)
{ {
//NetconConnection *c = getConnectionByPCB(tpcb); /*
lwipstack->tcp_arg(tpcb, NULL); lwipstack->tcp_arg(tpcb, NULL);
lwipstack->tcp_sent(tpcb, NULL); lwipstack->tcp_sent(tpcb, NULL);
lwipstack->tcp_recv(tpcb, NULL); lwipstack->tcp_recv(tpcb, NULL);
lwipstack->tcp_err(tpcb, NULL); lwipstack->tcp_err(tpcb, NULL);
lwipstack->tcp_poll(tpcb, NULL, 0); lwipstack->tcp_poll(tpcb, NULL, 0);
lwipstack->tcp_close(tpcb); lwipstack->tcp_close(tpcb);
*/
} }
err_t NetconEthernetTap::nc_send(struct tcp_pcb *tpcb) err_t NetconEthernetTap::nc_send(struct tcp_pcb *tpcb)
@ -452,17 +449,17 @@ err_t NetconEthernetTap::nc_send(struct tcp_pcb *tpcb)
err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *tpcb, u16_t len) err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *tpcb, u16_t len)
{ {
//NetconConnection *c = _phy->getConnectionByPCB(tpcb);
//if(c)
//c->data_sent += len;
return len; return len;
} }
err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err) err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{ {
for(int i=0; i<clients.size(); i++) { Larg *l = (Larg*)arg;
if(clients[i].containsPCB(tpcb)) { NetconEthernetTap *tap = l->tap;
send_return_value(clients[i],err);
for(size_t i=0; i<tap->clients.size(); i++) {
if(tap->clients[i]->containsPCB(tpcb)) {
tap->send_return_value(tap->clients[i],err);
} }
} }
return err; return err;
@ -481,14 +478,16 @@ void NetconEthernetTap::handle_bind(NetconClient *client, struct bind_st *bind_r
ip_addr_t conn_addr; ip_addr_t conn_addr;
IP4_ADDR(&conn_addr, 192,168,0,2); IP4_ADDR(&conn_addr, 192,168,0,2);
/*
int ip = connaddr->sin_addr.s_addr; int ip = connaddr->sin_addr.s_addr;
unsigned char bytes[4]; unsigned char bytes[4];
bytes[0] = ip & 0xFF; bytes[0] = ip & 0xFF;
bytes[1] = (ip >> 8) & 0xFF; bytes[1] = (ip >> 8) & 0xFF;
bytes[2] = (ip >> 16) & 0xFF; bytes[2] = (ip >> 16) & 0xFF;
bytes[3] = (ip >> 24) & 0xFF; bytes[3] = (ip >> 24) & 0xFF;
// "binding to: %d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] "binding to: %d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]
NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd); */
NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd);
if(c) { if(c) {
if(c->pcb->state == CLOSED){ if(c->pcb->state == CLOSED){
int err = lwipstack->tcp_bind(c->pcb, &conn_addr, conn_port); int err = lwipstack->tcp_bind(c->pcb, &conn_addr, conn_port);
@ -520,8 +519,7 @@ void NetconEthernetTap::handle_listen(NetconClient *client, struct listen_st *li
if(listening_pcb != NULL) { if(listening_pcb != NULL) {
c->pcb = listening_pcb; c->pcb = listening_pcb;
lwipstack->tcp_accept(listening_pcb, nc_accept); lwipstack->tcp_accept(listening_pcb, nc_accept);
int our_fd = _phy.getDescriptor(c->sock); lwipstack->tcp_arg(listening_pcb, new Larg(this, c->sock));
lwipstack->tcp_arg(listening_pcb, (void*)(intptr_t)our_fd);
client->waiting_for_retval=true; client->waiting_for_retval=true;
} }
else { else {
@ -565,14 +563,13 @@ void NetconEthernetTap::handle_connect(NetconClient *client, struct connect_st*
int conn_port = lwipstack->ntohs(connaddr->sin_port); int conn_port = lwipstack->ntohs(connaddr->sin_port);
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);
NetconConnection *c = client->getConnectionByTheirFD(connect_rpc->__fd); NetconConnection *c = client->getConnectionByTheirFD(connect_rpc->__fd);
int our_fd = _phy.getDescriptor(c->sock);
if(c!= NULL) { if(c!= NULL) {
lwipstack->tcp_sent(c->pcb, nc_sent); // FIXME: Move? lwipstack->tcp_sent(c->pcb, nc_sent); // FIXME: Move?
lwipstack->tcp_recv(c->pcb, nc_recved); lwipstack->tcp_recv(c->pcb, nc_recved);
lwipstack->tcp_err(c->pcb, nc_err); lwipstack->tcp_err(c->pcb, nc_err);
lwipstack->tcp_poll(c->pcb, nc_poll, APPLICATION_POLL_FREQ); lwipstack->tcp_poll(c->pcb, nc_poll, APPLICATION_POLL_FREQ);
lwipstack->tcp_arg(c->pcb,(void*)(intptr_t)our_fd); lwipstack->tcp_arg(c->pcb, new Larg(this, c->sock));
int err = 0; int err = 0;
if((err = lwipstack->tcp_connect(c->pcb,&conn_addr,conn_port, nc_connected)) < 0) if((err = lwipstack->tcp_connect(c->pcb,&conn_addr,conn_port, nc_connected)) < 0)

View file

@ -44,7 +44,8 @@
#include "../osdep/Thread.hpp" #include "../osdep/Thread.hpp"
#include "../osdep/Phy.hpp" #include "../osdep/Phy.hpp"
#include "NetconService.h" #include "NetconService.hpp"
#include "NetconUtilities.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -84,6 +85,15 @@ public:
throw(); throw();
private: private:
// RPC handlers (from NetconIntercept)
void handle_bind(NetconClient *client, struct bind_st *bind_rpc);
void handle_listen(NetconClient *client, struct listen_st *listen_rpc);
void handle_retval(NetconClient *client, unsigned char* buf);
void handle_socket(NetconClient *client, struct socket_st* socket_rpc);
void handle_connect(NetconClient *client, struct connect_st* connect_rpc);
void handle_write(NetconConnection *c);
void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *from,void *data,unsigned long len); void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *from,void *data,unsigned long len);
void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success); void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from); void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from);
@ -95,10 +105,26 @@ private:
void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len); void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len);
void phyOnUnixWritable(PhySocket *sock,void **uptr); void phyOnUnixWritable(PhySocket *sock,void **uptr);
void phyOnSocketPairEndpointClose(void *sock, void **uptr);
void phyOnSocketPairEndpointData(PhySocket *sock, void **uptr, void *buf, unsigned long n);
void phyOnSocketPairEndpointWritable(PhySocket *sock, void **uptr);
int send_return_value(NetconClient *client, int retval); int send_return_value(NetconClient *client, int retval);
// For LWIP Callbacks // For LWIP Callbacks
static err_t nc_poll(void *arg, struct tcp_pcb *tpcb); static err_t nc_poll(void* arg, struct tcp_pcb *tpcb)
{
Larg *l = (Larg*)arg;
NetconConnection *c = l->tap->getConnectionByPCB(tpcb);
NetconEthernetTap *tap = l->tap;
if(c)
tap->handle_write(c);
return ERR_OK;
}
static err_t nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err); static err_t nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); static err_t nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void nc_err(void *arg, err_t err); static void nc_err(void *arg, err_t err);
@ -107,13 +133,7 @@ private:
static err_t nc_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); static err_t nc_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static err_t nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err); static err_t nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
// RPC handlers (from NetconIntercept)
void handle_bind(NetconClient *client, struct bind_st *bind_rpc);
void handle_listen(NetconClient *client, struct listen_st *listen_rpc);
void handle_retval(NetconClient *client, unsigned char* buf);
void handle_socket(NetconClient *client, struct socket_st* socket_rpc);
void handle_connect(NetconClient *client, struct connect_st* connect_rpc);
void handle_write(NetconConnection *c);
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg; void *_arg;

View file

@ -29,16 +29,29 @@
#include <string> #include <string>
#include "../osdep/Phy.hpp" #include "../osdep/Phy.hpp"
#include "NetconEthernetTap.hpp"
#include "Intercept.h" #include "Intercept.h"
#include "LWIPStack.hpp" #include "LWIPStack.hpp"
#ifndef _NETCON_SERVICE_H_ #ifndef _NETCON_SERVICE_HPP
#define _NETCON_SERVICE_H_ #define _NETCON_SERVICE_HPP
using namespace std; using namespace std;
namespace ZeroTier { namespace ZeroTier {
class NetconEthernetTap;
// Helper class for passing reference to Phy to LWIP callbacks
class Larg
{
public:
NetconEthernetTap *tap;
PhySocket *sock;
Larg(NetconEthernetTap *_tap, PhySocket *_sock) : tap(_tap), sock(_sock) {}
};
enum NetconConnectionType { RPC, BUFFER }; enum NetconConnectionType { RPC, BUFFER };
// prototypes // prototypes
@ -103,7 +116,7 @@ namespace ZeroTier {
NetconConnection *getConnectionByPCB(struct tcp_pcb *pcb) NetconConnection *getConnectionByPCB(struct tcp_pcb *pcb)
{ {
for(size_t i=0; i<connections.size(); i++) { for(size_t i=0; i<connections.size(); i++) {
if(connections[i]->pcb = pcb) { return connections[i]; } if(connections[i]->pcb == pcb) { return connections[i]; }
} }
return NULL; return NULL;
} }
@ -111,17 +124,23 @@ namespace ZeroTier {
NetconConnection *containsPCB(struct tcp_pcb *pcb) NetconConnection *containsPCB(struct tcp_pcb *pcb)
{ {
for(size_t i=0; i<connections.size(); i++) { for(size_t i=0; i<connections.size(); i++) {
if(connections[i]->pcb = pcb) { return connections[i]; } if(connections[i]->pcb == pcb) { return connections[i]; }
} }
return NULL; return NULL;
} }
void close() void closeConnection(NetconConnection *c)
{ {
// close all connections // close all connections
// -- pcb // -- pcb
// -- PhySocket // -- PhySocket
} }
void closeClient()
{
}
}; };
} // namespace ZeroTier } // namespace ZeroTier
#endif #endif

View file

@ -7,126 +7,127 @@
#ifndef _NETCON_UTILITIES_CPP #ifndef _NETCON_UTILITIES_CPP
#define _NETCON_UTILITIES_CPP #define _NETCON_UTILITIES_CPP
namespace ZeroTier
ip_addr_t convert_ip(struct sockaddr_in * addr)
{ {
ip_addr_t conn_addr; ip_addr_t convert_ip(struct sockaddr_in * addr)
struct sockaddr_in *ipv4 = addr;
short a = ip4_addr1(&(ipv4->sin_addr));
short b = ip4_addr2(&(ipv4->sin_addr));
short c = ip4_addr3(&(ipv4->sin_addr));
short d = ip4_addr4(&(ipv4->sin_addr));
IP4_ADDR(&conn_addr, a,b,c,d);
return conn_addr;
}
ip_addr_t ip_addr_sin(register struct sockaddr_in *sin) {
ip_addr_t ip;
*((struct sockaddr_in*) &ip) = *sin;
return ip;
}
// Functions used to pass file descriptors between processes
ssize_t sock_fd_write(int sock, int fd);
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
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; ip_addr_t conn_addr;
char control[CMSG_SPACE(sizeof (int))]; struct sockaddr_in *ipv4 = addr;
} cmsgu; short a = ip4_addr1(&(ipv4->sin_addr));
struct cmsghdr *cmsg; short b = ip4_addr2(&(ipv4->sin_addr));
short c = ip4_addr3(&(ipv4->sin_addr));
iov.iov_base = &buf; short d = ip4_addr4(&(ipv4->sin_addr));
iov.iov_len = buflen; IP4_ADDR(&conn_addr, a,b,c,d);
return conn_addr;
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); ip_addr_t ip_addr_sin(register struct sockaddr_in *sin) {
if (size < 0) ip_addr_t ip;
perror ("sendmsg"); *((struct sockaddr_in*) &ip) = *sin;
return size; return ip;
} }
// Functions used to pass file descriptors between processes
ssize_t sock_fd_write(int sock, int fd);
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
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;
}
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd) ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
{ {
ssize_t size; ssize_t size;
if (fd) { if (fd) {
struct msghdr msg; struct msghdr msg;
struct iovec iov; struct iovec iov;
union union
{ {
struct cmsghdr cmsghdr; struct cmsghdr cmsghdr;
char control[CMSG_SPACE(sizeof (int))]; char control[CMSG_SPACE(sizeof (int))];
} cmsgu; } cmsgu;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
iov.iov_base = buf; iov.iov_base = buf;
iov.iov_len = bufsize; iov.iov_len = bufsize;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_iov = &iov; msg.msg_iov = &iov;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
msg.msg_control = cmsgu.control; msg.msg_control = cmsgu.control;
msg.msg_controllen = sizeof(cmsgu.control); msg.msg_controllen = sizeof(cmsgu.control);
size = recvmsg (sock, &msg, 0); size = recvmsg (sock, &msg, 0);
if (size < 0) { if (size < 0) {
perror ("recvmsg"); perror ("recvmsg");
exit(1); exit(1);
} }
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmsg->cmsg_level != SOL_SOCKET) { if (cmsg->cmsg_level != SOL_SOCKET) {
fprintf (stderr, "invalid cmsg_level %d\n", fprintf (stderr, "invalid cmsg_level %d\n",
cmsg->cmsg_level); cmsg->cmsg_level);
exit(1); exit(1);
} }
if (cmsg->cmsg_type != SCM_RIGHTS) { if (cmsg->cmsg_type != SCM_RIGHTS) {
fprintf (stderr, "invalid cmsg_type %d\n", fprintf (stderr, "invalid cmsg_type %d\n",
cmsg->cmsg_type); cmsg->cmsg_type);
exit(1); exit(1);
} }
*fd = *((int *) CMSG_DATA(cmsg)); *fd = *((int *) CMSG_DATA(cmsg));
} else } else
*fd = -1; *fd = -1;
} else { } else {
size = read (sock, buf, bufsize); size = read (sock, buf, bufsize);
if (size < 0) { if (size < 0) {
perror("read"); perror("read");
exit(1); exit(1);
} }
} }
return size; return size;
}
} }
#endif #endif

View file

@ -2,10 +2,12 @@
#ifndef _NETCON_UTILITIES_H #ifndef _NETCON_UTILITIES_H
#define _NETCON_UTILITIES_H #define _NETCON_UTILITIES_H
ip_addr_t convert_ip(struct sockaddr_in * addr); namespace ZeroTier
ip_addr_t ip_addr_sin(register struct sockaddr_in *sin); {
ip_addr_t convert_ip(struct sockaddr_in * addr);
ssize_t sock_fd_write(int sock, int fd); ip_addr_t ip_addr_sin(register struct sockaddr_in *sin);
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
ssize_t sock_fd_write(int sock, int fd);
ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
}
#endif #endif

View file

@ -289,7 +289,7 @@ public:
* @param uptr Pointer to associate with local side of socket pair * @param uptr Pointer to associate with local side of socket pair
* @return PhySocket for local side of socket pair * @return PhySocket for local side of socket pair
*/ */
static inline PhySocket *createSocketPair(ZT_PHY_SOCKFD_TYPE &remoteSocketDescriptor,void *uptr = (void *)0) inline PhySocket *createSocketPair(ZT_PHY_SOCKFD_TYPE &remoteSocketDescriptor,void *uptr = (void *)0)
{ {
if (_socks.size() >= ZT_PHY_MAX_SOCKETS) if (_socks.size() >= ZT_PHY_MAX_SOCKETS)
return (PhySocket *)0; return (PhySocket *)0;