Browse Source

Added ButtFlare stub code

Joseph Henry 8 years ago
parent
commit
683ba79ff0
5 changed files with 306 additions and 1 deletions
  1. 4 0
      make-mac.mk
  2. 2 1
      objects.mk
  3. 194 0
      service/ButtFlare.cpp
  4. 94 0
      service/ButtFlare.hpp
  5. 12 0
      service/OneService.cpp

+ 4 - 0
make-mac.mk

@@ -37,6 +37,10 @@ ifeq ($(ZT_ENABLE_CLUSTER),1)
 	DEFS+=-DZT_ENABLE_CLUSTER
 	DEFS+=-DZT_ENABLE_CLUSTER
 endif
 endif
 
 
+ifeq ($(ZT_ENABLE_BUTTFLARE),1)
+	DEFS+=-DZT_ENABLE_BUTTFLARE
+endif
+
 # Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources
 # Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources
 DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
 DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
 OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
 OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o

+ 2 - 1
objects.mk

@@ -31,4 +31,5 @@ OBJS=\
 	osdep/Http.o \
 	osdep/Http.o \
 	osdep/OSUtils.o \
 	osdep/OSUtils.o \
 	service/ClusterGeoIpService.o \
 	service/ClusterGeoIpService.o \
-	service/SoftwareUpdater.o
+	service/SoftwareUpdater.o \
+	service/ButtFlare.o

+ 194 - 0
service/ButtFlare.cpp

@@ -0,0 +1,194 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2016  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "../osdep/Thread.hpp"
+#include "ButtFlare.hpp"
+
+namespace ZeroTier {
+
+	typedef void PhySocket;
+
+	ButtFlare::ButtFlare(
+		void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) 
+		:
+			_handler(handler),
+			_phy(this,false,true),
+			_enabled(true),
+			_run(true)
+	{
+		// HTTP listen socket
+		struct sockaddr_in in4;
+		memset(&in4,0,sizeof(in4));
+		in4.sin_family = AF_INET;
+		in4.sin_addr.s_addr = Utils::hton((uint32_t)(0x7f000001)); // right now we just listen for TCP @127.0.0.1
+		in4.sin_port = Utils::hton((uint16_t)http_listen_port);
+		_tcpHttpListenSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
+		// SSL listen socket
+		in4.sin_port = Utils::hton((uint16_t)ssl_listen_port);
+		_tcpSSLListenSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
+
+		/*
+		struct sockaddr_in6 in6;
+		memset((void *)&in6,0,sizeof(in6));
+		in6.sin6_family = AF_INET6;
+		in6.sin6_port = in4.sin_port;
+		if (_allowManagementFrom.size() == 0)
+			in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
+		_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
+
+		// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
+		// have only IPv4 or only IPv6 stacks.
+		if ((_v4TcpControlSocket)||(_v6TcpControlSocket)) {
+			_ports[0] = _primaryPort;
+			break;
+		} else {
+			if (_v4TcpControlSocket)
+				_phy.close(_v4TcpControlSocket,false);
+			if (_v6TcpControlSocket)
+				_phy.close(_v6TcpControlSocket,false);
+			_primaryPort = 0;
+		}
+		*/
+
+		if(!_tcpHttpListenSocket)
+			printf("Error binding on port %d for HTTP listen socket\n", http_listen_port);
+		if(!_tcpSSLListenSocket)
+			printf("Error binding on port %d for SSL listen socket\n", ssl_listen_port);
+		_thread = Thread::start(this);
+	} 
+
+	ButtFlare::~ButtFlare()
+	{
+		_run = false;
+		_phy.whack();
+		_phy.whack(); // TODO: Rationale?
+		Thread::join(_thread);
+		_phy.close(_tcpHttpListenSocket,false);
+		_phy.close(_tcpSSLListenSocket,false);
+	}
+	void ButtFlare::threadMain()
+		throw()
+	{
+		while(_run) {
+			_phy.poll(50); // in ms
+		}
+	}
+
+	void ButtFlare::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len)
+	{
+		TcpConnection *conn = cmap[sock];
+		unsigned char *buf = (unsigned char*)data;
+		std::string host = "";
+
+		for(int i=0; i<len; i++) { printf("buf[%d] = %d, (char) = %c\n", i, buf[i], (char*)buf[i]); }
+		printf("phyOnTcpData(len=%lu)\n", len);
+
+		if(conn == NULL) {
+			printf("No existing connection for this socket\n");
+			return;
+		}
+		if(!conn->destination_sock) { // no connection yet
+			
+			// Determine if HTTP or TLS/SSL
+			if(buf[0] == 22 && len > 100) // naive and incomplete way of checking for TLS, just for stub code
+			{
+				printf("TLS/SSL\n");
+				host = "127.0.0.1";
+			}
+			else
+			{
+				printf("HTTP\n");
+				host = "127.0.0.1";
+			}
+
+			if(host != "")
+			{
+				bool connected;
+				struct sockaddr_in in4;
+				memset(&in4,0,sizeof(in4));
+				in4.sin_family = AF_INET;
+				in4.sin_addr.s_addr = Utils::hton((uint32_t)(0x7f000001)); // right now we just listen for TCP @127.0.0.1
+				in4.sin_port = Utils::hton((uint16_t)http_listen_port);
+				conn->destination_sock = _phy.tcpConnect((const struct sockaddr *)&in4, connected, this);
+
+				if(!connected) {
+					printf("instant connect has occured\n");
+				}
+				if(!conn->destination_sock) {
+					printf("there was an error connecting to the remote host\n");
+				}
+			}
+		}
+		else // connection already established, just forward the data
+		{
+			int n = _phy.streamSend(conn->destination_sock, buf, len);
+			printf("wrote %d bytes (%p -> %p)\n", conn->origin_sock, conn->destination_sock);
+		}
+	}
+
+	void ButtFlare::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
+	{
+	}
+	void ButtFlare::phyOnTcpWritable(PhySocket *sock,void **uptr)
+	{
+	}
+	void ButtFlare::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable)
+	{
+	}
+
+	void ButtFlare::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
+	{
+		printf("phyOnTcpConnect()\n");
+	}
+
+	void ButtFlare::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from)
+	{
+		TcpConnection *conn = new TcpConnection();
+		conn->origin_sock = sockN;
+		cmap[sockN]=conn; // add new connection
+	}
+
+	void ButtFlare::phyOnUnixClose(PhySocket *sock,void **uptr) 
+	{
+	}
+	void ButtFlare::phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len)
+	{
+	}
+	void ButtFlare::phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked)
+	{
+	}
+
+
+	void ButtFlare::phyOnTcpClose(PhySocket *sock,void **uptr) 
+	{
+		TcpConnection *conn = cmap[sock];
+		if(conn == NULL) {
+			printf("No existing connection for this sock. Only closing origin sock\n");
+			// _phy.close(sock);
+			return;
+		}
+		else
+		{
+			// Close both ends
+			// _phy.close(conn->destination_sock);
+			// _phy.close(conn->origin_sock);
+		}
+	}
+}
+
+//#endif

+ 94 - 0
service/ButtFlare.hpp

@@ -0,0 +1,94 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2016  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ZT_BUTTFLARE_HPP
+#define ZT_BUTTFLARE_HPP
+
+#include "../node/InetAddress.hpp"
+#include "../osdep/Phy.hpp"
+
+namespace ZeroTier {
+
+	typedef void PhySocket;
+	class ButtFlare;
+
+	struct TcpConnection
+	{
+		enum {
+			TCP_HTTP_INCOMING,
+			TCP_HTTP_OUTGOING,
+			TCP_TUNNEL_OUTGOING 
+		} type;
+
+		InetAddress from;
+		InetAddress realhost;
+		
+		PhySocket *origin_sock;
+		PhySocket *destination_sock;
+	};
+
+	class ButtFlare
+	{
+		friend class Phy<ButtFlare *>;
+
+	public:
+		ButtFlare(
+			void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
+			void *arg);
+
+		~ButtFlare();
+
+		// Send incoming data to intended host
+		void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len);
+
+		void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len);
+		void phyOnTcpWritable(PhySocket *sock,void **uptr);
+		void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable);
+
+		// Establish outgoing connection to intended host
+		void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success);
+		// Accept connection 
+		void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from);
+		// Handle the closure of a Unix Domain socket
+		void phyOnUnixClose(PhySocket *sock,void **uptr);
+		void phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len);
+		void phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked);
+		
+		// Handle the closure of a TCP connection
+		void phyOnTcpClose(PhySocket *sock,void **uptr);
+
+		void threadMain()
+			throw();
+
+	  	void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
+
+	private:
+		int http_listen_port = 80;
+		int ssl_listen_port = 8899;
+
+		volatile bool _enabled;
+		volatile bool _run;	
+
+		Thread _thread;
+		Phy<ButtFlare*> _phy;
+		PhySocket *_tcpHttpListenSocket, *_tcpSSLListenSocket;
+		std::map<PhySocket*, TcpConnection*> cmap;
+	};
+}
+
+#endif

+ 12 - 0
service/OneService.cpp

@@ -67,6 +67,10 @@
 #include <ifaddrs.h>
 #include <ifaddrs.h>
 #endif
 #endif
 
 
+#ifdef ZT_ENABLE_BUTTFLARE
+#include "ButtFlare.hpp"
+#endif
+
 #ifdef ZT_USE_SYSTEM_HTTP_PARSER
 #ifdef ZT_USE_SYSTEM_HTTP_PARSER
 #include <http_parser.h>
 #include <http_parser.h>
 #else
 #else
@@ -474,6 +478,10 @@ public:
 	unsigned int _clusterMemberId;
 	unsigned int _clusterMemberId;
 #endif
 #endif
 
 
+#ifdef ZT_ENABLE_BUTTFLARE
+	ButtFlare *butt;
+#endif
+
 	// Set to false to force service to stop
 	// Set to false to force service to stop
 	volatile bool _run;
 	volatile bool _run;
 	Mutex _run_m;
 	Mutex _run_m;
@@ -1914,6 +1922,10 @@ public:
 					try {
 					try {
 						char friendlyName[128];
 						char friendlyName[128];
 						Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
 						Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
+
+#ifdef ZT_ENABLE_BUTTFLARE
+						butt = new ButtFlare(StapFrameHandler, (void *)this);
+#endif
 						n.tap = new EthernetTap(
 						n.tap = new EthernetTap(
 							_homePath.c_str(),
 							_homePath.c_str(),
 							MAC(nwc->mac),
 							MAC(nwc->mac),