From 20beafedc5e62fdd1b6f7d93c735b7a17c4374bb Mon Sep 17 00:00:00 2001
From: Joseph Henry <joseph.henry@zerotier.com>
Date: Thu, 10 Sep 2015 20:02:13 -0400
Subject: [PATCH] refactor almost complete

---
 make-linux.mk                                 |   4 +-
 netcon/Intercept.h                            |   2 +
 netcon/NetconEthernetTap.cpp                  |  77 +++---
 netcon/NetconEthernetTap.hpp                  |  38 ++-
 netcon/{NetconService.h => NetconService.hpp} |  29 ++-
 netcon/NetconUtilities.cpp                    | 221 +++++++++---------
 netcon/NetconUtilities.hpp                    |  12 +-
 osdep/Phy.hpp                                 |   2 +-
 8 files changed, 213 insertions(+), 172 deletions(-)
 rename netcon/{NetconService.h => NetconService.hpp} (84%)

diff --git a/make-linux.mk b/make-linux.mk
index 35e7c07e5..e30f210cf 100644
--- a/make-linux.mk
+++ b/make-linux.mk
@@ -75,7 +75,7 @@ ifeq ($(ZT_DEBUG),1)
 	DEFS+=-DZT_TRACE
 	CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
 	CXXFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
-	LDFLAGS=
+	LDFLAGS=-ldl
 	STRIP=echo
 	# The following line enables optimization for the crypto code, since
 	# 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)
 	CXXFLAGS?=-O3 -fstack-protector
 	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
 endif
 
diff --git a/netcon/Intercept.h b/netcon/Intercept.h
index 97075dcbe..30d118cf9 100755
--- a/netcon/Intercept.h
+++ b/netcon/Intercept.h
@@ -175,6 +175,7 @@ struct shutdown_st
 
 
 /* LWIP error beautification */
+/*
 const char *lwiperror(int n)
 {
 	switch(n)
@@ -215,5 +216,6 @@ const char *lwiperror(int n)
 			return "UNKNOWN_RET_VAL";
 	}
 }
+*/
 
 #endif
diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp
index 723a5f55e..d3deb8ce3 100644
--- a/netcon/NetconEthernetTap.cpp
+++ b/netcon/NetconEthernetTap.cpp
@@ -29,6 +29,8 @@
 
 #include <algorithm>
 #include <utility>
+#include <dlfcn.h>
+
 
 #include "NetconEthernetTap.hpp"
 
@@ -43,7 +45,7 @@
 #include "lwip/ip_frag.h"
 
 #include "LWIPStack.hpp"
-#include "NetconService.h"
+#include "NetconService.hpp"
 #include "Intercept.h"
 #include "NetconUtilities.hpp"
 
@@ -114,6 +116,7 @@ bool NetconEthernetTap::addIp(const InetAddress &ip)
 		// TODO: alloc IP in LWIP
 		//netif_set_addr(netif, ipaddr, netmask, gw);
 	}
+	return true; // TODO: what is exapected?
 }
 
 bool NetconEthernetTap::removeIp(const InetAddress &ip)
@@ -194,7 +197,7 @@ NetconClient *NetconEthernetTap::getClientByPCB(struct tcp_pcb *pcb)
 void NetconEthernetTap::closeClient(NetconClient *client)
 {
 	// erase from clients vector
-	client->close();
+	client->closeClient();
 }
 
 
@@ -219,7 +222,7 @@ void NetconEthernetTap::threadMain()
   unsigned long since_etharp;
 
 	struct timeval tv;
-  struct timeval tv_sel;
+  //struct timeval tv_sel;
 
 	while (_run) {
 		gettimeofday(&tv, NULL);
@@ -267,7 +270,7 @@ void NetconEthernetTap::phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void *
 
 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)
@@ -313,7 +316,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
 		    handle_bind(client, &bind_rpc);
 				break;
 		  case RPC_KILL_INTERCEPT:
-		    client->close();
+		    client->closeClient();
 				break;
 	  	case RPC_CONNECT:
 		    struct connect_st connect_rpc;
@@ -361,22 +364,17 @@ int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
 --------------------------------- 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)
 {
+	Larg *l = (Larg*)arg;
+	NetconConnection *c = l->tap->getConnectionByPCB(tpcb);
+	NetconEthernetTap *tap = l->tap;
+
 	int n;
   struct pbuf* q = p;
-	NetconConnection *c = getConnectionByPCB(tpcb); // TODO: make sure this works, if not, use arg as "buf sock"
-	int our_fd = _phy.getDescriptor(c->sock);
+	int our_fd = tap->_phy.getDescriptor(c->sock);
 
   if(c) {
     //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; // ?
   }
   if(p == NULL) {
-    //dwr(c->owner->tid, "nc_recved() = %s\n", lwiperror(err));
-    if(c)
       //dwr(c->owner->tid, "nc_recved()\n");
     if(c) {
       //dwr(c->owner->tid, "closing connection\n");
       nc_close(tpcb);
       close(our_fd); /* TODO: Check logic */
       //nc_service->remove_connection(c);
-			c->owner->close(c);
+			c->owner->closeConnection(c);
     }
     else {
-      //dwr(-1, "can't locate connection via (arg)\n");
+      // can't locate connection via (arg)
     }
     return err;
   }
   q = p;
   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)
       break; // ?
     if((n = write(our_fd, p->payload, p->len)) > 0) {
       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 {
-      //dwr(c->owner->tid, "ERROR: No data written to intercept buffer.\n");
+      // Error: No data written to intercept buffer
     }
     p = p->next;
   }
-  lwipstack->pbuf_free(q); /* free pbufs */
+  tap->lwipstack->pbuf_free(q); // free pbufs
   return ERR_OK;
 }
 
 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) {
-    //nc_service->remove_connection(c);
-    c->owner->close(c);
+    c->owner->closeConnection(c);
 		//tcp_close(c->pcb);
   }
   else {
@@ -436,13 +432,14 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
 
 void NetconEthernetTap::nc_close(struct tcp_pcb* tpcb)
 {
-  //NetconConnection *c = getConnectionByPCB(tpcb);
+	/*
   lwipstack->tcp_arg(tpcb, NULL);
   lwipstack->tcp_sent(tpcb, NULL);
   lwipstack->tcp_recv(tpcb, NULL);
   lwipstack->tcp_err(tpcb, NULL);
   lwipstack->tcp_poll(tpcb, NULL, 0);
   lwipstack->tcp_close(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)
 {
-	//NetconConnection *c = _phy->getConnectionByPCB(tpcb);
-	//if(c)
-		//c->data_sent += len;
 	return len;
 }
 
 err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
 {
-	for(int i=0; i<clients.size(); i++) {
-		if(clients[i].containsPCB(tpcb)) {
-			send_return_value(clients[i],err);
+	Larg *l = (Larg*)arg;
+	NetconEthernetTap *tap = l->tap;
+
+	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;
@@ -481,14 +478,16 @@ void NetconEthernetTap::handle_bind(NetconClient *client, struct bind_st *bind_r
   ip_addr_t conn_addr;
   IP4_ADDR(&conn_addr, 192,168,0,2);
 
+	/*
   int ip = connaddr->sin_addr.s_addr;
   unsigned char bytes[4];
   bytes[0] = ip & 0xFF;
   bytes[1] = (ip >> 8) & 0xFF;
   bytes[2] = (ip >> 16) & 0xFF;
   bytes[3] = (ip >> 24) & 0xFF;
-  // "binding to: %d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]
-  NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd);
+  "binding to: %d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]
+  */
+	NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd);
   if(c) {
     if(c->pcb->state == CLOSED){
       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) {
       c->pcb = listening_pcb;
       lwipstack->tcp_accept(listening_pcb, nc_accept);
-			int our_fd = _phy.getDescriptor(c->sock);
-      lwipstack->tcp_arg(listening_pcb, (void*)(intptr_t)our_fd);
+			lwipstack->tcp_arg(listening_pcb, new Larg(this, c->sock));
       client->waiting_for_retval=true;
     }
     else {
@@ -565,14 +563,13 @@ void NetconEthernetTap::handle_connect(NetconClient *client, struct connect_st*
 	int conn_port = lwipstack->ntohs(connaddr->sin_port);
 	ip_addr_t conn_addr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr);
 	NetconConnection *c = client->getConnectionByTheirFD(connect_rpc->__fd);
-	int our_fd = _phy.getDescriptor(c->sock);
 
 	if(c!= NULL) {
 		lwipstack->tcp_sent(c->pcb, nc_sent); // FIXME: Move?
 		lwipstack->tcp_recv(c->pcb, nc_recved);
 		lwipstack->tcp_err(c->pcb, nc_err);
 		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;
 		if((err = lwipstack->tcp_connect(c->pcb,&conn_addr,conn_port, nc_connected)) < 0)
diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp
index c79a11c0d..3eb39eb66 100644
--- a/netcon/NetconEthernetTap.hpp
+++ b/netcon/NetconEthernetTap.hpp
@@ -44,7 +44,8 @@
 #include "../osdep/Thread.hpp"
 #include "../osdep/Phy.hpp"
 
-#include "NetconService.h"
+#include "NetconService.hpp"
+#include "NetconUtilities.hpp"
 
 namespace ZeroTier {
 
@@ -84,6 +85,15 @@ public:
 		throw();
 
 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 phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
 	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 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);
 
 	// 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_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, 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_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 *_arg;
diff --git a/netcon/NetconService.h b/netcon/NetconService.hpp
similarity index 84%
rename from netcon/NetconService.h
rename to netcon/NetconService.hpp
index 3ca37b112..93431f759 100644
--- a/netcon/NetconService.h
+++ b/netcon/NetconService.hpp
@@ -29,16 +29,29 @@
 #include <string>
 
 #include "../osdep/Phy.hpp"
+#include "NetconEthernetTap.hpp"
 
 #include "Intercept.h"
 #include "LWIPStack.hpp"
 
-#ifndef _NETCON_SERVICE_H_
-#define _NETCON_SERVICE_H_
+#ifndef _NETCON_SERVICE_HPP
+#define _NETCON_SERVICE_HPP
 
 using namespace std;
 
 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 };
 
   // prototypes
@@ -103,7 +116,7 @@ namespace ZeroTier {
     NetconConnection *getConnectionByPCB(struct tcp_pcb *pcb)
     {
       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;
     }
@@ -111,17 +124,23 @@ namespace ZeroTier {
     NetconConnection *containsPCB(struct tcp_pcb *pcb)
     {
       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;
     }
 
-    void close()
+    void closeConnection(NetconConnection *c)
     {
       // close all connections
       // -- pcb
       // -- PhySocket
     }
+
+    void closeClient()
+    {
+
+    }
   };
 } // namespace ZeroTier
+
 #endif
diff --git a/netcon/NetconUtilities.cpp b/netcon/NetconUtilities.cpp
index 8f501ce2e..bb870669b 100644
--- a/netcon/NetconUtilities.cpp
+++ b/netcon/NetconUtilities.cpp
@@ -7,126 +7,127 @@
 #ifndef _NETCON_UTILITIES_CPP
 #define _NETCON_UTILITIES_CPP
 
-
-
-ip_addr_t convert_ip(struct sockaddr_in * addr)
+namespace ZeroTier
 {
-  ip_addr_t conn_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
+	ip_addr_t convert_ip(struct sockaddr_in * addr)
 	{
-		  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;
+	  ip_addr_t conn_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;
 	}
 
-	size = sendmsg(sock, &msg, 0);
-	if (size < 0)
-		  perror ("sendmsg");
-	return size;
-}
+	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;
+			  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 size;
+	ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
+	{
+	    ssize_t size;
 
-    if (fd) {
-        struct msghdr msg;
-        struct iovec iov;
-        union
-				{
-            struct cmsghdr cmsghdr;
-            char control[CMSG_SPACE(sizeof (int))];
-        } cmsgu;
-        struct cmsghdr *cmsg;
+	    if (fd) {
+	        struct msghdr msg;
+	        struct iovec iov;
+	        union
+					{
+	            struct cmsghdr cmsghdr;
+	            char control[CMSG_SPACE(sizeof (int))];
+	        } cmsgu;
+	        struct cmsghdr *cmsg;
 
-        iov.iov_base = buf;
-        iov.iov_len = bufsize;
+	        iov.iov_base = buf;
+	        iov.iov_len = bufsize;
 
-        msg.msg_name = NULL;
-        msg.msg_namelen = 0;
-        msg.msg_iov = &iov;
-        msg.msg_iovlen = 1;
-        msg.msg_control = cmsgu.control;
-        msg.msg_controllen = sizeof(cmsgu.control);
-        size = recvmsg (sock, &msg, 0);
-        if (size < 0) {
-            perror ("recvmsg");
-            exit(1);
-        }
-        cmsg = CMSG_FIRSTHDR(&msg);
-        if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
-            if (cmsg->cmsg_level != SOL_SOCKET) {
-                fprintf (stderr, "invalid cmsg_level %d\n",
-                     cmsg->cmsg_level);
-                exit(1);
-            }
-            if (cmsg->cmsg_type != SCM_RIGHTS) {
-                fprintf (stderr, "invalid cmsg_type %d\n",
-                     cmsg->cmsg_type);
-                exit(1);
-            }
+	        msg.msg_name = NULL;
+	        msg.msg_namelen = 0;
+	        msg.msg_iov = &iov;
+	        msg.msg_iovlen = 1;
+	        msg.msg_control = cmsgu.control;
+	        msg.msg_controllen = sizeof(cmsgu.control);
+	        size = recvmsg (sock, &msg, 0);
+	        if (size < 0) {
+	            perror ("recvmsg");
+	            exit(1);
+	        }
+	        cmsg = CMSG_FIRSTHDR(&msg);
+	        if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+	            if (cmsg->cmsg_level != SOL_SOCKET) {
+	                fprintf (stderr, "invalid cmsg_level %d\n",
+	                     cmsg->cmsg_level);
+	                exit(1);
+	            }
+	            if (cmsg->cmsg_type != SCM_RIGHTS) {
+	                fprintf (stderr, "invalid cmsg_type %d\n",
+	                     cmsg->cmsg_type);
+	                exit(1);
+	            }
 
-            *fd = *((int *) CMSG_DATA(cmsg));
-        } else
-            *fd = -1;
-    } else {
-        size = read (sock, buf, bufsize);
-        if (size < 0) {
-            perror("read");
-            exit(1);
-        }
-    }
-    return size;
+	            *fd = *((int *) CMSG_DATA(cmsg));
+	        } else
+	            *fd = -1;
+	    } else {
+	        size = read (sock, buf, bufsize);
+	        if (size < 0) {
+	            perror("read");
+	            exit(1);
+	        }
+	    }
+	    return size;
+	}
 }
 
 #endif
diff --git a/netcon/NetconUtilities.hpp b/netcon/NetconUtilities.hpp
index 56b0ed945..5ce062f35 100644
--- a/netcon/NetconUtilities.hpp
+++ b/netcon/NetconUtilities.hpp
@@ -2,10 +2,12 @@
 #ifndef _NETCON_UTILITIES_H
 #define _NETCON_UTILITIES_H
 
-ip_addr_t convert_ip(struct sockaddr_in * addr);
-ip_addr_t ip_addr_sin(register struct sockaddr_in *sin);
-
-ssize_t sock_fd_write(int sock, int fd);
-ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
+namespace ZeroTier
+{
+  ip_addr_t convert_ip(struct sockaddr_in * addr);
+  ip_addr_t ip_addr_sin(register struct sockaddr_in *sin);
 
+  ssize_t sock_fd_write(int sock, int fd);
+  ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
+}
 #endif
diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp
index e4209d3cd..7f790e5d2 100644
--- a/osdep/Phy.hpp
+++ b/osdep/Phy.hpp
@@ -289,7 +289,7 @@ public:
 	 * @param uptr Pointer to associate with 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)
 			return (PhySocket *)0;