فهرست منبع

ZeroTierOne for Windows binary project, builds and runs and mostly works but still some issues with tap.

Adam Ierymenko 12 سال پیش
والد
کامیت
487eb17ec0

+ 5 - 1
.gitignore

@@ -11,6 +11,9 @@ mac-tap/tuntap/tap.kext
 /ZeroTierOne.v11.suo
 /vsprojects/SelfTest/Debug
 /vsprojects/SelfTest/Release
+/vsprojects/ZeroTierOne/Debug
+/vsprojects/ZeroTierOne/Release
+/vsprojects/ZeroTierOne/x64
 /vsprojects/TapDriver/Win32
 /vsprojects/TapDriver/x64
 /Build/*
@@ -18,5 +21,6 @@ mac-tap/tuntap/tap.kext
 *.opensdf
 *.user
 *.cache
-
+*.obj
+*.tlog
 /vsprojects/SelfTest/SelfTest.aps

+ 35 - 0
ZeroTierOne.sln

@@ -10,6 +10,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver Package", "vsproj
 		{689210B1-467C-4850-BB7D-2E10D5B4A3DA} = {689210B1-467C-4850-BB7D-2E10D5B4A3DA}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroTierOne", "vsprojects\ZeroTierOne\ZeroTierOne.vcxproj", "{B00A4957-5977-4AC1-9EF4-571DC27EADA2}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -156,6 +158,39 @@ Global
 		{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
 		{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Build.0 = Win8 Release|x64
 		{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Win32.Build.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|Win32.Deploy.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x64.ActiveCfg = Debug|x64
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Debug|x64.Build.0 = Debug|x64
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Build.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|Win32.Deploy.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Release|x64.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Win32.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Win32.Build.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|Win32.Deploy.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Debug|x64.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Win32.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Win32.Build.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|Win32.Deploy.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Vista Release|x64.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Win32.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Win32.Build.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|Win32.Deploy.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Debug|x64.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Win32.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Win32.Build.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|Win32.Deploy.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win7 Release|x64.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Win32.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Win32.Build.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|Win32.Deploy.0 = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Debug|x64.ActiveCfg = Debug|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Win32.ActiveCfg = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Win32.Build.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|Win32.Deploy.0 = Release|Win32
+		{B00A4957-5977-4AC1-9EF4-571DC27EADA2}.Win8 Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 2 - 2
ext/kissdb/kissdb.c

@@ -179,7 +179,7 @@ int KISSDB_get(KISSDB *db,const void *key,void *vbuf)
 			kptr = (const uint8_t *)key;
 			klen = db->key_size;
 			while (klen) {
-				n = fread(tmp,1,(klen > sizeof(tmp)) ? sizeof(tmp) : klen,db->f);
+				n = (long)fread(tmp,1,(klen > sizeof(tmp)) ? sizeof(tmp) : klen,db->f);
 				if (n > 0) {
 					if (memcmp(kptr,tmp,n))
 						goto get_no_match_next_hash_table;
@@ -224,7 +224,7 @@ int KISSDB_put(KISSDB *db,const void *key,const void *value)
 			kptr = (const uint8_t *)key;
 			klen = db->key_size;
 			while (klen) {
-				n = fread(tmp,1,(klen > sizeof(tmp)) ? sizeof(tmp) : klen,db->f);
+				n = (long)fread(tmp,1,(klen > sizeof(tmp)) ? sizeof(tmp) : klen,db->f);
 				if (n > 0) {
 					if (memcmp(kptr,tmp,n))
 						goto put_no_match_next_hash_table;

+ 0 - 11
launcher.h

@@ -32,17 +32,6 @@
 #define ZT_LAUNCHER_VERSION_MINOR 0
 #define ZT_LAUNCHER_VERSION_REVISION 1
 
-/* Default locations of data directories on operating systems */
-#ifdef __APPLE__ /* MacOS likes purdy paths, none of this 1970s /var stuff */
-#define ZT_DEFAULT_HOME "/Library/Application Support/ZeroTier/One"
-#else
-#ifdef _WIN32    /* Winbloze */
-need windoze;
-#else            /* Unix/Linux */
-#define ZT_DEFAULT_HOME "/var/lib/zerotier-one"
-#endif
-#endif
-
 /**
  * Normal termination
  * 

+ 25 - 15
main.cpp

@@ -30,14 +30,17 @@
 #include <string.h>
 #include <time.h>
 #include <errno.h>
+
 #include <string>
 #include <stdexcept>
-#include <iostream>
 
 #include "node/Constants.hpp"
 
 #ifdef __WINDOWS__
+#include <WinSock2.h>
 #include <Windows.h>
+#include <tchar.h>
+#include <wchar.h>
 #else
 #include <unistd.h>
 #include <pwd.h>
@@ -48,8 +51,10 @@
 
 #include <openssl/rand.h>
 
-#include "node/Node.hpp"
+#include "node/Constants.hpp"
+#include "node/Defaults.hpp"
 #include "node/Utils.hpp"
+#include "node/Node.hpp"
 
 #include "launcher.h"
 
@@ -89,10 +94,10 @@ static Node *node = (Node *)0;
 
 static void printHelp(const char *cn,FILE *out)
 {
-	fprintf(out,"ZeroTier One version %d.%d.%d\n(c)2012-2013 ZeroTier Networks LLC\nLicensed under the GNU General Public License v3\n\nUsage: %s <home directory>\n",Node::versionMajor(),Node::versionMinor(),Node::versionRevision(),cn);
+	fprintf(out,"ZeroTier One version %d.%d.%d"ZT_EOL_S"(c)2012-2013 ZeroTier Networks LLC"ZT_EOL_S"Licensed under the GNU General Public License v3"ZT_EOL_S""ZT_EOL_S"Usage: %s [home directory]"ZT_EOL_S,Node::versionMajor(),Node::versionMinor(),Node::versionRevision(),cn);
 }
 
-#ifndef _WIN32
+#ifdef __UNIX_LIKE__
 static void sighandlerQuit(int sig)
 {
 	Node *n = node;
@@ -102,9 +107,13 @@ static void sighandlerQuit(int sig)
 }
 #endif
 
+#ifdef __WINDOWS__
+int _tmain(int argc, _TCHAR* argv[])
+#else
 int main(int argc,char **argv)
+#endif
 {
-#ifndef _WIN32
+#ifdef __UNIX_LIKE__
 	signal(SIGHUP,SIG_IGN);
 	signal(SIGPIPE,SIG_IGN);
 	signal(SIGUSR1,SIG_IGN);
@@ -115,17 +124,19 @@ int main(int argc,char **argv)
 	signal(SIGQUIT,&sighandlerQuit);
 #endif
 
-	_initLibCrypto();
+#ifdef __WINDOWS__
+	WSADATA wsaData;
+	WSAStartup(MAKEWORD(2,2),&wsaData);
+#endif
 
-	if (argc < 2) {
-		printHelp(argv[0],stderr);
-		return ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
-	}
+	_initLibCrypto();
 
 	const char *homeDir = (const char *)0;
 	for(int i=1;i<argc;++i) {
 		if (argv[i][0] == '-') {
 			switch(argv[i][1]) {
+				case 'h':
+				case '?':
 				default:
 					printHelp(argv[0],stderr);
 					return ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
@@ -140,11 +151,10 @@ int main(int argc,char **argv)
 		}
 	}
 
-	if ((!homeDir)||(strlen(homeDir) <= 0)) {
-		printHelp(argv[0],stderr);
-		return ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
-	}
-#ifndef _WIN32
+	if ((!homeDir)||(strlen(homeDir) == 0))
+		homeDir = ZT_DEFAULTS.defaultHomePath.c_str();
+
+#ifdef __UNIX_LIKE__
 	mkdir(homeDir,0755); // will fail if it already exists
 #endif
 

+ 1 - 1
node/Buffer.hpp

@@ -284,7 +284,7 @@ public:
 	inline void append(const std::string &s)
 		throw(std::out_of_range)
 	{
-		append(s.data(),s.length());
+		append(s.data(),(unsigned int)s.length());
 	}
 
 	/**

+ 2 - 2
node/Dictionary.hpp

@@ -114,9 +114,9 @@ public:
 		std::string s;
 
 		for(const_iterator kv(begin());kv!=end();++kv) {
-			_appendEsc(kv->first.data(),kv->first.length(),s);
+			_appendEsc(kv->first.data(),(unsigned int)kv->first.length(),s);
 			s.push_back('=');
-			_appendEsc(kv->second.data(),kv->second.length(),s);
+			_appendEsc(kv->second.data(),(unsigned int)kv->second.length(),s);
 			s.append(ZT_EOL_S);
 		}
 

+ 1 - 1
node/EllipticCurveKey.hpp

@@ -78,7 +78,7 @@ public:
 	EllipticCurveKey(const std::string &data)
 		throw(std::out_of_range)
 	{
-		set(data.data(),data.length());
+		set(data.data(),(unsigned int)data.length());
 	}
 
 	inline void set(const void *data,unsigned int len)

+ 2 - 2
node/EllipticCurveKeyPair.cpp

@@ -153,7 +153,7 @@ bool EllipticCurveKeyPair::generate()
 	}
 
 	memset(_priv._key,0,sizeof(_priv._key));
-	len = BN_num_bytes(EC_KEY_get0_private_key(key));
+	len = (int)BN_num_bytes(EC_KEY_get0_private_key(key));
 	if ((len > ZT_EC_PRIME_BYTES)||(len < 0)) {
 		EC_KEY_free(key);
 		return false;
@@ -162,7 +162,7 @@ bool EllipticCurveKeyPair::generate()
 	_priv._bytes = ZT_EC_PRIME_BYTES;
 
 	memset(_pub._key,0,sizeof(_pub._key));
-	len = EC_POINT_point2oct(ZT_EC_GROUP.g,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,_pub._key,sizeof(_pub._key),0);
+	len = (int)EC_POINT_point2oct(ZT_EC_GROUP.g,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,_pub._key,sizeof(_pub._key),0);
 	if (len != ZT_EC_PUBLIC_KEY_BYTES) {
 		EC_KEY_free(key);
 		return false;

+ 141 - 3
node/EthernetTap.cpp

@@ -693,11 +693,37 @@ void EthernetTap::threadMain()
 #include <tchar.h>
 #include <winreg.h>
 #include <wchar.h>
+#include <nldef.h>
+#include <netioapi.h>
 
 #include "..\vsprojects\TapDriver\tap-windows.h"
 
 namespace ZeroTier {
 
+// Helper function to get an adapter's LUID and index from its GUID. The LUID is
+// constant but the index can change, so go ahead and just look them both up by
+// the GUID which is constant. (The GUID is the instance ID in the registry.)
+static inline std::pair<NET_LUID,NET_IFINDEX> _findAdapterByGuid(const GUID &guid)
+	throw(std::runtime_error)
+{
+	MIB_IF_TABLE2 *ift = (MIB_IF_TABLE2 *)0;
+
+	if (GetIfTable2Ex(MibIfTableRaw,&ift) != NO_ERROR)
+		throw std::runtime_error("GetIfTable2Ex() failed");
+
+	for(ULONG i=0;i<ift->NumEntries;++i) {
+		if (ift->Table[i].InterfaceGuid == guid) {
+			std::pair<NET_LUID,NET_IFINDEX> tmp(ift->Table[i].InterfaceLuid,ift->Table[i].InterfaceIndex);
+			FreeMibTable(&ift);
+			return tmp;
+		}
+	}
+
+	FreeMibTable(&ift);
+
+	throw std::runtime_error("interface not found");
+}
+
 static Mutex _systemTapInitLock;
 
 EthernetTap::EthernetTap(
@@ -721,6 +747,9 @@ EthernetTap::EthernetTap(
 	char subkeyClass[4096];
 	char data[4096];
 
+	if (mtu > ZT_IF_MTU)
+		throw std::runtime_error("MTU too large for Windows tap");
+
 	Mutex::Lock _l(_systemTapInitLock); // only init one tap at a time, process-wide
 
 	HKEY nwAdapters;
@@ -813,7 +842,7 @@ EthernetTap::EthernetTap(
 							dataLen = sizeof(data);
 							if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
 								if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
-									RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,strlen(tag)+1);
+									RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
 									_myDeviceInstanceId.assign(data,dataLen);
 									mySubkeyName = subkeyName;
 									subkeyIndex = -1; // break outer loop
@@ -842,8 +871,27 @@ EthernetTap::EthernetTap(
 	if (_myDeviceInstanceId.length() == 0)
 		throw std::runtime_error("unable to create new tap adapter");
 
+	{
+		char nobraces[128];
+		const char *nbtmp1 = _myDeviceInstanceId.c_str();
+		char *nbtmp2 = nobraces;
+		while (*nbtmp1) {
+			if ((*nbtmp1 != '{')&&(*nbtmp1 != '}'))
+				*nbtmp2++ = *nbtmp1;
+			++nbtmp1;
+		}
+		*nbtmp2 = (char)0;
+		if (UuidFromStringA((RPC_CSTR)nobraces,&_deviceGuid) != RPC_S_OK)
+			throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
+	}
+
+#ifdef UNICODE
 	wchar_t tapPath[4096];
 	swprintf_s(tapPath,L"\\\\.\\Global\\%S.tap",_myDeviceInstanceId.c_str());
+#else
+	char tapPath[4096];
+	sprintf_s(tapPath,"\\\\.\\Global\\%s.tap",_myDeviceInstanceId.c_str());
+#endif
 	_tap = CreateFile(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
 	if (_tap == INVALID_HANDLE_VALUE)
 		throw std::runtime_error("unable to open tap in \\\\.\\Global\\ namespace");
@@ -878,14 +926,104 @@ void EthernetTap::whack()
 
 bool EthernetTap::addIP(const InetAddress &ip)
 {
+	Mutex::Lock _l(_ips_m);
+
+	if (_ips.count(ip))
+		return true;
+
+	if (!ip.port())
+		return false;
+
+	try {
+		std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
+		MIB_UNICASTIPADDRESS_ROW ipr;
+
+		InitializeUnicastIpAddressEntry(&ipr);
+		if (ip.isV4()) {
+			ipr.Address.Ipv4.sin_family = AF_INET;
+			ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
+			ipr.OnLinkPrefixLength = ip.port();
+		} else if (ip.isV6()) {
+		} else return false;
+
+		ipr.PrefixOrigin = IpPrefixOriginManual;
+		ipr.SuffixOrigin = IpSuffixOriginManual;
+		ipr.ValidLifetime = 0xffffffff;
+		ipr.PreferredLifetime = 0xffffffff;
+
+		ipr.InterfaceLuid = ifidx.first;
+		ipr.InterfaceIndex = ifidx.second;
+
+		if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
+			_ips.insert(ip);
+			return true;
+		}
+	} catch ( ... ) {}
+
 	return false;
 }
 
 bool EthernetTap::removeIP(const InetAddress &ip)
 {
+	try {
+		MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
+		std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
+
+		if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
+			for(DWORD i=0;i<ipt->NumEntries;++i) {
+				if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
+					InetAddress addr;
+					switch(ipt->Table[i].Address.si_family) {
+						case AF_INET:
+							addr.set(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
+							break;
+						case AF_INET6:
+							addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
+							break;
+					}
+					if (addr == ip) {
+						DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
+						FreeMibTable(&ipt);
+						Mutex::Lock _l(_ips_m);
+						_ips.erase(ip);
+						return true;
+					}
+				}
+			}
+			FreeMibTable(&ipt);
+		}
+	} catch ( ... ) {}
 	return false;
 }
 
+std::set<InetAddress> EthernetTap::allIps() const
+{
+	std::set<InetAddress> addrs;
+
+	try {
+		MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
+		std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
+
+		if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
+			for(DWORD i=0;i<ipt->NumEntries;++i) {
+				if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
+					switch(ipt->Table[i].Address.si_family) {
+						case AF_INET:
+							addrs.insert(InetAddress(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength));
+							break;
+						case AF_INET6:
+							addrs.insert(InetAddress(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength));
+							break;
+					}
+				}
+			}
+			FreeMibTable(&ipt);
+		}
+	} catch ( ... ) {}
+
+	return addrs;
+}
+
 void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
 {
 	if (len > (ZT_IF_MTU))
@@ -939,8 +1077,8 @@ void EthernetTap::threadMain()
 					MAC from(_tapReadBuf + 6);
 					unsigned int etherType = Utils::ntoh(*((const uint16_t *)(_tapReadBuf + 12)));
 					Buffer<4096> tmp(_tapReadBuf + 14,bytesRead - 14);
-					printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
-					//_handler(_arg,from,to,etherType,tmp);
+					//printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
+					_handler(_arg,from,to,etherType,tmp);
 				}
 			}
 			ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);

+ 6 - 0
node/EthernetTap.hpp

@@ -134,6 +134,11 @@ public:
 		return _ips;
 	}
 
+	/**
+	 * @return Set of IP addresses / netmasks included any we did not assign, link-local, etc.
+	 */
+	std::set<InetAddress> allIps() const;
+
 	/**
 	 * Set this tap's IP addresses to exactly this set of IPs
 	 *
@@ -213,6 +218,7 @@ private:
 	OVERLAPPED _tapOvlRead,_tapOvlWrite;
 	char _tapReadBuf[ZT_IF_MTU + 32];
 	HANDLE _injectSemaphore;
+	GUID _deviceGuid;
 	std::string _myDeviceInstanceId;
 	std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
 	Mutex _injectPending_m;

+ 1 - 1
node/Filter.hpp

@@ -298,7 +298,7 @@ public:
 		throw()
 	{
 		Mutex::Lock _l(_chain_m);
-		return _chain.size();
+		return (unsigned int)_chain.size();
 	}
 
 	/**

+ 4 - 4
node/Identity.cpp

@@ -88,7 +88,7 @@ bool Identity::locallyValidate(bool doAddressDerivationCheck) const
 	SHA256_Update(&sha,&zero,1);
 	SHA256_Final(dig,&sha);
 
-	return ((EllipticCurveKeyPair::verify(dig,_publicKey,_signature.data(),_signature.length()))&&((!doAddressDerivationCheck)||(deriveAddress(_publicKey.data(),_publicKey.size()) == _address)));
+	return ((EllipticCurveKeyPair::verify(dig,_publicKey,_signature.data(),(unsigned int)_signature.length()))&&((!doAddressDerivationCheck)||(deriveAddress(_publicKey.data(),_publicKey.size()) == _address)));
 }
 
 std::string Identity::toString(bool includePrivate) const
@@ -98,7 +98,7 @@ std::string Identity::toString(bool includePrivate) const
 	r.append(":1:"); // 1 == IDENTITY_TYPE_NIST_P_521
 	r.append(Utils::base64Encode(_publicKey.data(),_publicKey.size()));
 	r.push_back(':');
-	r.append(Utils::base64Encode(_signature.data(),_signature.length()));
+	r.append(Utils::base64Encode(_signature.data(),(unsigned int)_signature.length()));
 	if ((includePrivate)&&(_keyPair)) {
 		r.push_back(':');
 		r.append(Utils::base64Encode(_keyPair->priv().data(),_keyPair->priv().size()));
@@ -127,7 +127,7 @@ bool Identity::fromString(const char *str)
 	b = Utils::base64Decode(fields[2]);
 	if ((!b.length())||(b.length() > ZT_EC_MAX_BYTES))
 		return false;
-	_publicKey.set(b.data(),b.length());
+	_publicKey.set(b.data(),(unsigned int)b.length());
 
 	_signature = Utils::base64Decode(fields[3]);
 	if (!_signature.length())
@@ -137,7 +137,7 @@ bool Identity::fromString(const char *str)
 		b = Utils::base64Decode(fields[4]);
 		if ((!b.length())||(b.length() > ZT_EC_MAX_BYTES))
 			return false;
-		_keyPair = new EllipticCurveKeyPair(_publicKey,EllipticCurveKey(b.data(),b.length()));
+		_keyPair = new EllipticCurveKeyPair(_publicKey,EllipticCurveKey(b.data(),(unsigned int)b.length()));
 	}
 
 	return true;

+ 5 - 0
node/Logger.cpp

@@ -107,7 +107,12 @@ void Logger::trace(const char *module,unsigned int line,const char *fmt,...)
 
 		if (_log) {
 			time_t now = time(0);
+#ifdef __WINDOWS__
+			ctime_s(tmp,sizeof(tmp),&now);
+			char *nowstr = tmp;
+#else
 			char *nowstr = ctime_r(&now,tmp);
+#endif
 			for(char *c=nowstr;*c;++c) {
 				if (*c == '\n')
 					*c = '\0';

+ 27 - 3
node/Node.cpp

@@ -258,7 +258,7 @@ Node::Node(const char *hp)
 {
 	_NodeImpl *impl = (_NodeImpl *)_impl;
 
-	if (hp)
+	if ((hp)&&(strlen(hp) > 0))
 		impl->renv.homePath = hp;
 	else impl->renv.homePath = ZT_DEFAULTS.defaultHomePath;
 	impl->reasonForTermination = Node::NODE_RUNNING;
@@ -382,10 +382,10 @@ Node::ReasonForTermination Node::run()
 		_r->sysEnv = new SysEnv(_r);
 		try {
 			_r->nc = new NodeConfig(_r,configAuthToken.c_str());
-		} catch ( ... ) {
+		} catch (std::exception &exc) {
 			// An exception here currently means that another instance of ZeroTier
 			// One is running.
-			return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound");
+			return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,(std::string("another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound: ") + exc.what()).c_str());
 		}
 
 		// TODO: make configurable
@@ -618,3 +618,27 @@ const unsigned char EMBEDDED_VERSION_STAMP[20] = {
 };
 
 } // namespace ZeroTier
+
+extern "C" {
+
+ZeroTier::Node *zeroTierCreateNode(const char *hp)
+{
+	return new ZeroTier::Node(hp);
+}
+
+void zeroTierDeleteNode(ZeroTier::Node *n)
+{
+	delete n;
+}
+
+ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
+{
+	return new ZeroTier::Node::LocalClient(authToken,resultHandler,arg);
+}
+
+void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc)
+{
+	delete lc;
+}
+
+} // extern "C"

+ 13 - 1
node/Node.hpp

@@ -163,5 +163,17 @@ extern const unsigned char EMBEDDED_VERSION_STAMP[20];
 
 } // namespace ZeroTier
 
-#endif
+extern "C" {
+
+// Functions with C-style linkage for easy DLL symbol table
+// lookup. These just create instances of Node and LocalClient.
+
+ZeroTier::Node *zeroTierCreateNode(const char *hp);
+void zeroTierDeleteNode(ZeroTier::Node *n);
 
+ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,void (*resultHandler)(void *,unsigned long,const char *),void *arg);
+void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc);
+
+} // extern "C"
+
+#endif

+ 1 - 1
node/Switch.cpp

@@ -142,7 +142,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		outpTmpl.append((uint16_t)data.size());
 		outpTmpl.append((uint16_t)signature.length());
 		outpTmpl.append(data.data(),data.size());
-		outpTmpl.append(signature.data(),signature.length());
+		outpTmpl.append(signature.data(),(unsigned int)signature.length());
 		outpTmpl.compress();
 		send(outpTmpl,true);
 		for(unsigned int i=1;i<np;++i) {

+ 1 - 1
node/Topology.cpp

@@ -232,7 +232,7 @@ void Topology::threadMain()
 		}
 		_PeerDeepVerifyJob job(_peerDeepVerifyJobs.front());
 		_peerDeepVerifyJobs.pop_front();
-		unsigned long queueRemaining = _peerDeepVerifyJobs.size();
+		unsigned long queueRemaining = (unsigned long)_peerDeepVerifyJobs.size();
 		_peerDeepVerifyJobs_m.unlock();
 
 		switch(job.type) {

+ 20 - 3
node/UdpSocket.cpp

@@ -63,7 +63,11 @@ UdpSocket::UdpSocket(
 	_packetHandler(packetHandler),
 	_arg(arg),
 	_localPort(localPort),
+#ifdef __WINDOWS__
+	_sock(INVALID_SOCKET),
+#else
 	_sock(0),
+#endif
 	_v6(ipv6)
 {
 #ifdef __WINDOWS__
@@ -77,8 +81,13 @@ UdpSocket::UdpSocket(
 
 	if (ipv6) {
 		_sock = socket(AF_INET6,SOCK_DGRAM,0);
+#ifdef __WINDOWS__
+		if (_sock == INVALID_SOCKET)
+			throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
+#else
 		if (_sock <= 0)
 			throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
+#endif
 
 #ifdef __WINDOWS__
 		yes = TRUE; setsockopt(_sock,IPPROTO_IPV6,IPV6_V6ONLY,(const char *)&yes,sizeof(yes));
@@ -115,8 +124,13 @@ UdpSocket::UdpSocket(
 		}
 	} else {
 		_sock = socket(AF_INET,SOCK_DGRAM,0);
+#ifdef __WINDOWS__
+		if (_sock == INVALID_SOCKET)
+			throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
+#else
 		if (_sock <= 0)
 			throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
+#endif
 
 #ifdef __WINDOWS__
 		no = FALSE; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(const char *)&no,sizeof(no));
@@ -154,16 +168,19 @@ UdpSocket::UdpSocket(
 UdpSocket::~UdpSocket()
 {
 	int s = _sock;
-	_sock = 0;
-	if (s > 0) {
 #ifdef __WINDOWS__
+	_sock = INVALID_SOCKET;
+	if (s != INVALID_SOCKET) {
 		::shutdown(s,SD_BOTH);
 		::closesocket(s);
+	}
 #else
+	_sock = 0;
+	if (s > 0) {
 		::shutdown(s,SHUT_RDWR);
 		::close(s);
-#endif
 	}
+#endif
 	Thread::join(_thread);
 }
 

+ 8 - 0
node/UdpSocket.hpp

@@ -35,6 +35,10 @@
 #include "InetAddress.hpp"
 #include "Mutex.hpp"
 
+#ifdef __WINDOWS__
+#include <WinSock2.h>
+#endif
+
 namespace ZeroTier {
 
 /**
@@ -100,7 +104,11 @@ private:
 	void (*_packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int);
 	void *_arg;
 	int _localPort;
+#ifdef __WINDOWS__
+	volatile SOCKET _sock;
+#else
 	volatile int _sock;
+#endif
 	bool _v6;
 	Mutex _sendLock;
 };

+ 2 - 2
node/Utils.cpp

@@ -501,7 +501,7 @@ uint64_t Utils::fromRfc1123(const char *tstr)
 	struct tm t;
 	char wdays[128],mons[128];
 
-	int l = strlen(tstr);
+	int l = (int)strlen(tstr);
 	if ((l < 29)||(l > 64))
 		return 0;
 	int assigned = sscanf(tstr,"%3s, %02d %3s %4d %02d:%02d:%02d GMT",wdays,&t.tm_mday,mons,&t.tm_year,&t.tm_hour,&t.tm_min,&t.tm_sec);
@@ -620,7 +620,7 @@ std::vector<std::string> Utils::split(const char *s,const char *const sep,const
 
 std::string Utils::trim(const std::string &s)
 {
-	unsigned long end = s.length();
+	unsigned long end = (unsigned long)s.length();
 	while (end) {
 		char c = s[end - 1];
 		if ((c == ' ')||(c == '\r')||(c == '\n')||(!c)||(c == '\t'))

+ 4 - 4
node/Utils.hpp

@@ -102,7 +102,7 @@ public:
 	 * @return Hexadecimal string
 	 */
 	static std::string hex(const void *data,unsigned int len);
-	static inline std::string hex(const std::string &data) { return hex(data.data(),data.length()); }
+	static inline std::string hex(const std::string &data) { return hex(data.data(),(unsigned int)data.length()); }
 
 	/**
 	 * @param hex Hexadecimal ASCII code (non-hex chars are ignored)
@@ -413,7 +413,7 @@ public:
 	 */
 	static inline bool writeFile(const char *path,const std::string &s)
 	{
-		return writeFile(path,s.data(),s.length());
+		return writeFile(path,s.data(),(unsigned int)s.length());
 	}
 
 	/**
@@ -422,7 +422,7 @@ public:
 	 * @return Base64-encoded string
 	 */
 	static std::string base64Encode(const void *data,unsigned int len);
-	inline static std::string base64Encode(const std::string &data) { return base64Encode(data.data(),data.length()); }
+	inline static std::string base64Encode(const std::string &data) { return base64Encode(data.data(),(unsigned int)data.length()); }
 
 	/**
 	 * @param data Base64-encoded string
@@ -430,7 +430,7 @@ public:
 	 * @return Decoded binary date
 	 */
 	static std::string base64Decode(const char *data,unsigned int len);
-	inline static std::string base64Decode(const std::string &data) { return base64Decode(data.data(),data.length()); }
+	inline static std::string base64Decode(const std::string &data) { return base64Decode(data.data(),(unsigned int)data.length()); }
 
 	/**
 	 * Split a string by delimiter, with optional escape and quote characters

+ 70 - 1
vsprojects/SelfTest/SelfTest.vcxproj

@@ -5,10 +5,18 @@
       <Configuration>Debug</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
     <ProjectConfiguration Include="Release|Win32">
       <Configuration>Release</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
     <ProjectGuid>{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}</ProjectGuid>
@@ -22,6 +30,12 @@
     <PlatformToolset>v110</PlatformToolset>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
@@ -29,23 +43,43 @@
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <LinkIncremental>true</LinkIncremental>
     <OutDir>$(SolutionDir)\Build\$(Configuration)\</OutDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <LinkIncremental>false</LinkIncremental>
-    <OutDir>$(SolutionDir)\Build\$(Configuration)\</OutDir>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -62,6 +96,21 @@
       <AdditionalDependencies>$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;wsock32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;wsock32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
@@ -82,6 +131,26 @@
       <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;$(SolutionDir)\ext\bin\libcrypto\win64-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+  </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="..\..\node\Address.hpp" />
     <ClInclude Include="..\..\node\Array.hpp" />

+ 228 - 0
vsprojects/ZeroTierOne/ZeroTierOne.vcxproj

@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{B00A4957-5977-4AC1-9EF4-571DC27EADA2}</ProjectGuid>
+    <RootNamespace>ZeroTierOne</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <TargetExt>.exe</TargetExt>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
+    <TargetName>zerotier-one-x86</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <TargetExt>.exe</TargetExt>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
+    <TargetName>zerotier-one-x86</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <TargetExt>.exe</TargetExt>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
+    <TargetName>zerotier-one-x64</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <TargetExt>.exe</TargetExt>
+    <OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
+    <TargetName>zerotier-one-x64</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>ZT_LOG_STDOUT;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>ZT_LOG_STDOUT;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win64-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>ZT_LOG_STDOUT;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>ZT_LOG_STDOUT;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;rpcrt4.lib;$(SolutionDir)\ext\bin\libcrypto\win64-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\node\Address.hpp" />
+    <ClInclude Include="..\..\node\Array.hpp" />
+    <ClInclude Include="..\..\node\AtomicCounter.hpp" />
+    <ClInclude Include="..\..\node\BloomFilter.hpp" />
+    <ClInclude Include="..\..\node\Buffer.hpp" />
+    <ClInclude Include="..\..\node\CMWC4096.hpp" />
+    <ClInclude Include="..\..\node\Condition.hpp" />
+    <ClInclude Include="..\..\node\Constants.hpp" />
+    <ClInclude Include="..\..\node\Defaults.hpp" />
+    <ClInclude Include="..\..\node\Demarc.hpp" />
+    <ClInclude Include="..\..\node\Dictionary.hpp" />
+    <ClInclude Include="..\..\node\EllipticCurveKey.hpp" />
+    <ClInclude Include="..\..\node\EllipticCurveKeyPair.hpp" />
+    <ClInclude Include="..\..\node\EthernetTap.hpp" />
+    <ClInclude Include="..\..\node\Filter.hpp" />
+    <ClInclude Include="..\..\node\HMAC.hpp" />
+    <ClInclude Include="..\..\node\Identity.hpp" />
+    <ClInclude Include="..\..\node\InetAddress.hpp" />
+    <ClInclude Include="..\..\node\Logger.hpp" />
+    <ClInclude Include="..\..\node\MAC.hpp" />
+    <ClInclude Include="..\..\node\Multicaster.hpp" />
+    <ClInclude Include="..\..\node\MulticastGroup.hpp" />
+    <ClInclude Include="..\..\node\Mutex.hpp" />
+    <ClInclude Include="..\..\node\Network.hpp" />
+    <ClInclude Include="..\..\node\Node.hpp" />
+    <ClInclude Include="..\..\node\NodeConfig.hpp" />
+    <ClInclude Include="..\..\node\NonCopyable.hpp" />
+    <ClInclude Include="..\..\node\Packet.hpp" />
+    <ClInclude Include="..\..\node\PacketDecoder.hpp" />
+    <ClInclude Include="..\..\node\Peer.hpp" />
+    <ClInclude Include="..\..\node\Range.hpp" />
+    <ClInclude Include="..\..\node\RateLimiter.hpp" />
+    <ClInclude Include="..\..\node\RuntimeEnvironment.hpp" />
+    <ClInclude Include="..\..\node\Salsa20.hpp" />
+    <ClInclude Include="..\..\node\Service.hpp" />
+    <ClInclude Include="..\..\node\SharedPtr.hpp" />
+    <ClInclude Include="..\..\node\Switch.hpp" />
+    <ClInclude Include="..\..\node\SysEnv.hpp" />
+    <ClInclude Include="..\..\node\Thread.hpp" />
+    <ClInclude Include="..\..\node\Topology.hpp" />
+    <ClInclude Include="..\..\node\UdpSocket.hpp" />
+    <ClInclude Include="..\..\node\Utils.hpp" />
+    <ClInclude Include="..\TapDriver\tap-windows.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\ext\kissdb\kissdb.c" />
+    <ClCompile Include="..\..\ext\lz4\lz4.c" />
+    <ClCompile Include="..\..\ext\lz4\lz4hc.c" />
+    <ClCompile Include="..\..\main.cpp" />
+    <ClCompile Include="..\..\node\Defaults.cpp" />
+    <ClCompile Include="..\..\node\Demarc.cpp" />
+    <ClCompile Include="..\..\node\EllipticCurveKeyPair.cpp" />
+    <ClCompile Include="..\..\node\EthernetTap.cpp" />
+    <ClCompile Include="..\..\node\Filter.cpp" />
+    <ClCompile Include="..\..\node\HMAC.cpp" />
+    <ClCompile Include="..\..\node\Identity.cpp" />
+    <ClCompile Include="..\..\node\InetAddress.cpp" />
+    <ClCompile Include="..\..\node\Logger.cpp" />
+    <ClCompile Include="..\..\node\Network.cpp" />
+    <ClCompile Include="..\..\node\Node.cpp" />
+    <ClCompile Include="..\..\node\NodeConfig.cpp" />
+    <ClCompile Include="..\..\node\Packet.cpp" />
+    <ClCompile Include="..\..\node\PacketDecoder.cpp" />
+    <ClCompile Include="..\..\node\Peer.cpp" />
+    <ClCompile Include="..\..\node\Salsa20.cpp" />
+    <ClCompile Include="..\..\node\Service.cpp" />
+    <ClCompile Include="..\..\node\Switch.cpp" />
+    <ClCompile Include="..\..\node\SysEnv.cpp" />
+    <ClCompile Include="..\..\node\Topology.cpp" />
+    <ClCompile Include="..\..\node\UdpSocket.cpp" />
+    <ClCompile Include="..\..\node\Utils.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 228 - 0
vsprojects/ZeroTierOne/ZeroTierOne.vcxproj.filters

@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\node\Address.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Array.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\AtomicCounter.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\BloomFilter.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Buffer.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\CMWC4096.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Condition.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Constants.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Defaults.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Demarc.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Dictionary.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\EllipticCurveKey.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\EllipticCurveKeyPair.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\EthernetTap.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Filter.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\HMAC.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Identity.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\InetAddress.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Logger.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\MAC.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Multicaster.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\MulticastGroup.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Mutex.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Network.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Node.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\NodeConfig.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\NonCopyable.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Packet.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\PacketDecoder.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Peer.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Range.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\RateLimiter.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\RuntimeEnvironment.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Salsa20.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Service.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SharedPtr.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Switch.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SysEnv.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Thread.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Topology.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\UdpSocket.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Utils.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\TapDriver\tap-windows.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\node\Defaults.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Demarc.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\EllipticCurveKeyPair.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\EthernetTap.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Filter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\HMAC.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Identity.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\InetAddress.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Logger.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Network.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Node.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\NodeConfig.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Packet.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\PacketDecoder.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Peer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Salsa20.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Service.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Switch.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\SysEnv.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Topology.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\UdpSocket.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\ext\kissdb\kissdb.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\ext\lz4\lz4.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\ext\lz4\lz4hc.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>